当前位置: 首页 > news >正文

BUMPMAPPING WITH GLSL

BUMPMAPPING WITH GLSL




原文链接 https://fabiensanglard.net/bumpMapping/index.php

当 我 开始 学习 凹凸贴图 和 视差映射 时,

我发现 很多 教程 涉及 一个 简单的矩形,

但没有什么 接近 现实生活 的 用途:

这是我填补空白的难题。

概念

BumpMapping允许 设计师 通过10 0000

( 也就是 10万个,原来 表述为 10,0000)

多个 多边形 生物 表达 自己 的 创造力。

一旦 艺术 完成,

就会自动 生成 低聚合模型(5000多边形)以及 法线贴图。

在 运行 时,

通过将 低模型 与 法线贴图 组合 来 加回 细节。

照明模型。

细节 被添加到 低聚合物 (此处 翻译 可能 有误 )表面反应 的 光。

照明方程 是 Blinn-Phong,

其中:(

pixelColor= Ambient + (Diffuse + Specular) * Shadow但让我们忘记阴影)。

// 此处可能有误……

Ambient = ambientMaterial * ambientLight

Diffuse = diffuseMaterial * diffuseLight * lamberFactor


lamberFactor = max (dot (lightVec, normal), 0.0)

Specular = specularMaterial * specularLight * speculatCoef


speculatCoef = pow (max (dot (halfVec, normal), 0.0), shininess)

细节:

  • 环境 几乎是一个 常数。
  • 漫射 取决于 光矢量 与表面法向量之间的角度。
  • 镜面取决于 视觉 (我自己认为应该是 视觉向量)矢量 与表面法向量之间的角度。

注意:当我们处理法向量时,可以用 简单的 点积 来获得 余弦值。

通常,每个计算 都是在 eye 空间 中 进行 的,

但是在凹凸映射中,

法线图中的法向量 表示为 切线空间。

因此,我们需要转换 所有需要的 向量。

为了做到这一点,

我们使用矩阵: Eye space - > Tangent space。

切线 空间 数学。

每个 顶点的 矩阵 如下:

[Normal.x Normal.y Normal.z] [BiNormal.x BiNormal.y BiNormal.z] [Tangent.x tangent.y Tangent.z]

法线 很容易 计算。

一个简单的 交叉产品 每张脸。(应该是每个面??)

顶点的 法 线 等于 法线(与该顶点相关的所有面)的 和,

最后 归一化。

对于模型中的每个面 { 通过交叉产品产生面部正常 在每个顶点前面加上法线 } 对于模型中的每个顶点 规范正态矢量

对于 正切 和 二次 正交,

您可以在 任何 好的数学书 中找到 解决方案(我强烈 推荐3D游戏编程数学)。

这是一个代码示例:

generateNormalAndTangent(float3 v1,float3 v2,text2 st1,text2 st2) { float3 normal = v1.crossProduct(v2); float coef = 1 /(st1.u * st2.v - st2.u * st1.v); float3切线; tangent.x = coef *((v1.x * st2.v)+(v2.x * -st1.v)); tangent.y = coef *((v1.y * st2.v)+(v2.y * -st1.v)); tangent.z = coef *((v1.z * st2.v)+(v2.z * -st1.v)); float3 binormal = normal.crossProduct(tangent); }

就像法线一样:对于 连接 到 该顶点的每个 面积 累积 切线 和 次数,

然后 通过 归一化 进行 平均。

在您的实现中,尝试可视化 您生成的矢量,

它们需要一致,

因为它们将被 GPU插值。

CPU侧

在openGL方面,必须做一些事情:

  • 绑定 顶点数组
  • 绑定正常数组
  • 绑定 纹理 坐标 数组
  • 绑定 元素 索引 数组
  • 将 切线数组 绑定到 着色器
  • 绑定 颜色纹理
  • 绑定 法线贴图(凹凸贴图)
  • 绑定 高度贴图纹理( 视差映射)
//为了动画目的,每个帧更新顶点VBO glBindBufferARB(GL_ARRAY_BUFFER_ARB,vboVertexId); glVertexPointer(3,GL_FLOAT,0,0); //与顶点VBO相同:每帧更新 glBindBufferARB(GL_ARRAY_BUFFER_ARB,vboNormalId); glNormalPointer(GL_FLOAT,0,0); // VBO,创建和填充一次,纹理坐标永远不会改变 glBindBufferARB(GL_ARRAY_BUFFER_ARB,vboTexturId); glTexCoordPointer(2,GL_FLOAT,0,0); //切线生成以前,不需要通过二进制,一个十字制品就会生成它 glVertexAttribPointerARB(tangentLoc,3,GL_FLOAT,GL_FALSE,0,tangentArraySkinPointer); // VBO,创建和填充一次,要绘制的元素永远不会改变 glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB,vboElementsId); glDrawElements(GL_TRIANGLES,meshes [i] .facesCount * 3,GL_UNSIGNED_INT,0); glActiveTextureARB(GL_TEXTURE0); glBindTexture(diffuseTextureId); glUniform1iARB(diffuseTextureUniform,0); glActiveTextureARB(GL_TEXTURE1); glBindTexture(normalTextureId); glUniform1iARB(normalTextureUniform,0); glActiveTextureARB(GL_TEXTURE2); glBindTexture(heightTextureId); glUniform1iARB(heightTextureUniform,0);

GPU边

顶点着色器的作用是

构建Blinn-Phong模型 中 使用的 矩阵 和 旋转矢量,

因此:

  • 用 正交 和 正切的 交叉积 产生 双切线。
  • 组合 三个 向量以 形成 旋转矩阵,从 相机空间 到 切线空间。
  • 旋转 光源 和 相机矢量。

在片段着色器中:

  • 从 法线贴图 中 检索 正常坐标。
  • 将 值从[-1,1]转换为[0,1]。
  • 计算 角度,产生漫反射,漫反射 和 镜面反射。
  • 添加 漫反射,漫反射 和 镜面成分。

顶点着色器

属性vec3切线 变化的vec3 lightVec; 变化vec3 halfVec; 改变vec3 eyeVec; void main() { gl_TexCoord [0] = gl_MultiTexCoord0; //构建矩阵眼空间 - >切线空间 vec3 n = normalize(gl_NormalMatrix * gl_Normal); vec3 t =归一化(gl_NormalMatrix * tangent); vec3 b =交叉(n,t); vec3顶点位置= vec3(gl_ModelViewMatrix * gl_Vertex); vec3 lightDir = normalize(gl_LightSource [0] .position.xyz - vertexPosition); //通过切线转换光和半角矢量 vec3 v vx = dot(lightDir,t); vy = dot(lightDir,b); vz = dot(lightDir,n); lightVec = normalize(v); vx = dot(vertexPosition,t); vy = dot(vertexPosition,b); vz = dot(vertexPosition,n); eyeVec = normalize(v); vertexPosition = normalize(vertexPosition); / *归一化halfVector以将其传递给片段着色器* / //不需要除以2,结果就是归一化。 // vec3 halfVector = normalize((vertexPosition + lightDir)/ 2.0); vec3 halfVector = normalize(vertexPosition + lightDir); vx = dot(halfVector,t); vy = dot(halfVector,b); vz = dot(halfVector,n); //不需要归一化,t,b,n和halfVector是法向量。 //规范化(v); halfVec = v; gl_Position = ftransform(); }

片段着色器

uniform sampler2D diffuseTexture; 均匀采样器 //新的bumpmapping 变化的vec3 lightVec; 变化vec3 halfVec; 改变vec3 eyeVec; void main() { //从法线图查找正常,从[0,1]移动到[-1,1]范围,进行归一化 vec3 normal = 2.0 * texture2D(normalTexture,gl_TexCoord [0] .st).rgb - 1.0; normal = normalize(normal); //计算漫射照明 float lamberFactor = max(dot(lightVec,normal),0.0); vec4 diffuseMaterial = 0.0; vec4 diffuseLight = 0.0; //计算镜面照明 vec4镜面材料; vec4镜面光 浮萍 //计算环境 vec4 ambientLight = gl_LightSource [0] .ambient; if(lamberFactor> 0.0) { diffuseMaterial = texture2D(diffuseTexture,gl_TexCoord [0] .st); diffuseLight = gl_LightSource [0] .diffuse; //在doom3中,镜面值来自纹理 镜面材料= vec4(1.0); specularLight = gl_LightSource [0] .specular; shininess = pow(max(dot(halfVec,normal),0.0),2.0); gl_FragColor = diffuseMaterial * diffuseLight * lamberFactor; gl_FragColor + = specularMaterial * specularLight * shininess; } gl_FragColor + = ambientLight; }

结果


注意:影子组件 不在 着色器 片段 中,

但可以在 下载的代码中 找到 它。

视频

该视频显示一个2000多边形Hellknight:

  • 原始模型。
  • 型号与512x512凹凸贴图。
  • 模型具有512x512凹凸贴图和漫反射/镜面映射。
  • 模型与512x512凹凸贴图和漫反射/镜面映射和阴影。

该代码具有C ++ md5模型查看器,

您可以通过config.cfg配置很多,

并在scene.cfg中定义场景。

我包括地狱骑士md5,所以任何人都可以运行演示,

我希望这将被容忍作为教育的目的。

ZenFrag引擎的配置示例。

下载

  • 来源。
  • 源码清理了linux。。
  • Windows构建。
  • Mac OSX构建。

2010年4月5日:似乎二进制分发在Windows 7中不起作用。

一旦我有一段时间,我必须看看这个。

推荐阅读

几本书,了解更多关于凹凸贴图和视差映射的书籍。

Doom3是一个很好的资源来学习,

每个模型都可以轻松访问和纯文本。

http://www.cnnetsun.cn/news/4166316.html

相关文章:

  • [光学原理与应用-524]:光的干涉,是单光子的运动特性,而不是不同光子相互作用的特性!!!
  • ol-ext 完全上手指南:5 大场景为 OpenLayers 快速加满功能(含最小示例与避坑清单)
  • ANI-RSS安装使用教程:5分钟部署你的RSS自动追番工具
  • TVA-World具身智能的跨模态因果涌现
  • KKCE网站测速:慢在哪一环
  • python 泛型?看这一篇就够了
  • Botty 暗黑2重制版自动化脚本实战教程:从第一次启动到看懂核心机制
  • AI虚拟角色应援系统技术解析:从Stable Diffusion到语音合成的本地部署实践
  • 基于springboot医院就诊管理系统设计与开发
  • 基于springboot体育馆预约系统设计与开发
  • 如何将 HTML 转成 Word 文档且格式不丢失?html-to-docx 使用教程
  • 多智能体框架实现聚合物粗粒化分子动力学模拟全流程自动化
  • 车机 ODM 供应链稳定性实战:从 CAN 总线适配到品控体系的全链路拆解
  • LSPosed QQ机器人怎么搭?OpenShamrock从安装到跑通的全流程
  • 电商客服想接入微信怎么办?个人微信API接口提供环节开发思路
  • 碳硅共生下认知破壁驱动人机协同科研范式转型:三机制均衡协同全域研究
  • 解析玻璃幕墙施工和验收标准
  • 解析建筑“三缝”:伸缩缝、沉降缝、防震缝
  • MiniMax H3提示词增强器:粗糙想法秒变专业视频分镜与音效描述,专为H3打造
  • 082-刻意练习中的情境学习
  • 电商API接口解析:平台对比、应用场景与代码实现
  • 【预测模型】基于遗传算法优化最小二乘支持向量机实现数据分类matlab代码
  • NUMAP V2.4 正式上线:让复杂系统建模更智能、更清晰、更高效
  • dlssg-to-fsr3:DLSS-G 怎么换成 FSR 3 帧生成?2000/3000 系显卡 10 分钟上手
  • AI Agent 核心原理与七步设计指南:从 ReAct 到企业级落地
  • 电子书简繁转换一键搞定:这个 Calibre 插件让繁简切换不再折腾
  • 20年热转印资深工厂:民宿软装挂布定制流程与品控深度解析
  • Waymo公布自动驾驶出租车计算“大脑”细节:成本降80%,但扩张仍受阻?
  • 低气味低VOC,水性涂料守护喷涂工人职业健康
  • 昇腾AI赋能抖音直播安卓应用