BUMPMAPPING WITH GLSL

2024-03-11 05:38
文章标签 glsl bumpmapping

本文主要是介绍BUMPMAPPING WITH GLSL,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

BUMPMAPPING WITH GLSL

当我开始学习凹凸贴图和视差映射时,我发现很多教程涉及一个简单的矩形,但没有什么接近现实生活的用途:

这是我填补空白的难题。


概念

BumpMapping允许设计师通过100,000多个多边形生物表达自己的创造力。一旦艺术完成,就会自动生成低聚合模型(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 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方面,必须做一些事情:

  • 绑定顶点数组
  • 绑定正常数组
  • 绑定纹理坐标数组
  • 绑定元素索引数组
  • 将切线数组绑定到着色器
  • 绑定颜色纹理
  • 绑定法线贴图(凹凸贴图)
  • 绑定高度贴图纹理(视差映射)
	//为了动画目的,每个帧更新顶点VBOglBindBufferARB(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 vvx = 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是一个很好的资源来学习,每个模型都可以轻松访问和纯文本。

这篇关于BUMPMAPPING WITH GLSL的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/796817

相关文章

glsl着色器学习(九)屏幕像素空间和设置颜色

在上一篇文章中,使用的是裁剪空间进行绘制,这篇文章使用屏幕像素空间的坐标进行绘制。 上一篇的顶点着色器大概是这样子的 回归一下顶点着色的主要任务:  通常情况下,顶点着色器会进行一系列的矩阵变换操作,将输入的顶点坐标从模型空间依次经过世界空间,视图空间,最终转换到裁剪空间。 将顶点着色器改成下面这样: <script id="vertex-shader-2d" type="x-sh

glsl着色器学习(十)缩放

对二维图形进行缩放,需要用到顶点着色器,顶点着色器经过矩阵变换,会将模型空间最终转换成裁剪空间。下面就来操作矩阵 这里需要用到一个库glMatrix。 首先修改顶点着色器 <script id="vertex-shader-2d" type="x-shader/x-vertex">attribute vec4 a_position;uniform mat4 u_matrix;void m

glsl着色器学习(六点五)顶点和片元的处理顺序

在WebGL中,顶点和片元的处理顺序遵循着图形渲染管线的流程。 顶点处理阶段 顶点处理阶段是图形渲染管线的起点,在这一阶段,所有与顶点相关的操作都会被执行。 顶点着色器(Vertex Shader) 顶点着色器接收每个顶点的数据,例如顶点坐标,法线,纹理坐标等。将顶点数据上传到图形硬件的缓冲区。在顶点着色器中,对这些顶点数据进行变换和运算,例如将顶点从模型空间转换到世界空间、视图空间和

Shader特效——“翻页”的实现 【GLSL】

参考自:http://webvfx.rectalogic.com/examples_2transition-shader-pagecurl_8html-example.html 效果图 [cpp] view plain  copy precision mediump float;    varying vec2 texCoord;  uniform sampler2D

Shader GLSL 3D旋转函数

mat4 rotationMatrix(vec3 axis, float angle){axis = normalize(axis);float s = sin(angle);float c = cos(angle)

three.js 中 meshbasic.glsl 文件中的片源着色器的主函数解析

1. three.js 中 meshbasic.glsl 文件中的片源着色器的主函数解析 他的具体代码如下 void main() {#include <uv_vertex>#include <color_vertex>#include <morphcolor_vertex>#if defined ( USE_ENVMAP ) || defined ( USE_SKINNING )#inclu

three.js 中ShaderChunk的, common.glsl 介绍

1. three.js 中ShaderChunk的, common.glsl 介绍 在three.js中,我们可以编写底层的shader代码,是通过 THREE.ShaderMaterial 来进行的。 但是three.js他也通过了一些 shader 代码片段,哎我们可以通过引入这些 shader代码片段,在自己的 THREE.ShaderMaterial中哈哈哈 现在我们讲一下,这个com

Ubuntu16.04 出现error: GLSL 3.30 is not supported. Supported versions are: 1.10, 1.20, 1.30, 1.00 ES

报出这个错误之前,博主找了各种办法尝试解决此问题,发现此问题比较常见。由于每个人的系统操作配置不一样,可能别人的配置使用网上的方法就可以解决,但是用在自己的身上就频频出错。因此,博主在这里先详细介绍自己电脑的配置情况:Ubuntu16.04  nvidia-driver384.130  cuda8.0/9.0  英伟达显卡1050Ti  台式机双系统。这里特意注明一下,博主使用sudo apt-g

GLSL中的std140注意事项

一、关于bool的注意事项 以下是笔者在学习OpenGL相关内容时遇到的问题 struct UniformBufferObject {alignas(16) igm::vec3 viewPos;alignas(4) bool useColor;}; 这是我在C++程序中声明的一个UBO,对应于着色器中的: layout(std140, binding = 1) uniform Unif

Ubuntu22.04平台编译完美解决问题“error: GLSL 4.5 is not supported.”【GLSL(OpenGL着色器语言)】

GLSL介绍 GLSL(OpenGL着色器语言)是用于编写OpenGL着色器程序的语言。GLSL 4.5 是 GLSL 的一个版本,引入了许多新的特性和改进,旨在提高着色器编程的灵活性和性能。GLSL 4.5 工具通常是用于编写、调试和优化 GLSL 4.5 着色器代码的软件工具集。 以下是一些常见的 GLSL 4.5 工具: 文本编辑器: 任何文本编辑器都可以用于编写 GLSL 4.5