Bump mapping的GLSL实现 [转]
原文 http://www.cnblogs.com/CGDeveloper/archive/2008/07/03/1234206.html
如果物体表面细节很多,我们可以不断的精细化物体的几何数据,但是这样会产生大量的Lighting & Transformation等计算,
为了实现丰富真实的物体表面,除了贴上一般纹理之外,往往还使用Bump mapping(凹凸纹理)技术。
Bump mapping并没有增加物体的几何复杂度,它只是在计算物体的光照效果时作了“弊”,不使用物体本身的法向量,而是
使用了经过处理的法向量。如果这样的法向量使用normal map,我们可以使用GLSL实现凹凸效果。
首先,因为没有改变对象的几何形状,所以bump mapping的实现是在FS之中进行的,因此光照计算就必须在FS之中进行。
由于normal map之中的法向量是在SURFACE_LOCAL COORDINATE SPACE,所以用于光照计算的光源的方向和视向都
必须变换到同一空间进行光照计算。也就是说,必须使用所谓TBN矩阵的逆矩阵对光源的方向和视向进行变换,转换之后的值
作为varying传入到FS之中。
对于三角形mesh而言,TBN的一种计算方法如下:
void FindInvTBN(Vertor3f Vertices[3], Vector2f TexCoords[3], Vector3f & InvNormal,
Vector3f & InvBinormal, Vector3f & InvTangent)
{
/* Calculate the vectors from the current vertex
to the two other vertices in the triangle */
Vector3f v2v1 = Vertices[0] - Vertices[2];
Vector3f v3v1 = Vertices[1] - Vertices[2];
//Calculate the “direction” of the triangle based on texture coordinates.
// Calculate c2c1_T and c2c1_B
float c2c1_T = TexCoords[0].x() - TexCoords[2].x();
float c2c1_B = TexCoords[0].y() - TexCoords[2].y();
// Calculate c3c1_T and c3c1_B
float c3c1_T = TexCoords[1].x() - TexCoords[2].x();
float c3c1_B = TexCoords[1].y() - TexCoords[2].y();
//Look at the references for more explanation for this one.
float fDenominator = c2c1_T * c3c1_B - c3c1_T * c2c1_B;
/*ROUNDOFF here is a macro that sets a value to 0.0f if the value is a very small
value, such as > -0.001f and < 0.001. */
/* EDIT by c programmer: you should NEVER perform an equality test against a floating point value, even if
your macro has set fDenominator to 0.0f. The comparison can still fail. The code needs fixed.
Instead you should check if fDenominator is within an epsilon value of 0.0f. */
if (ROUNDOFF(fDenominator) == 0.0f)
{
/* We won't risk a divide by zero, so set the tangent matrix to the
identity matrix */
InvTangent = Vector3f(1.0f, 0.0f, 0.0f);
InvBinormal = Vector3f(0.0f, 1.0f, 0.0f);
InvNormal = Vector3f(0.0f, 0.0f, 1.0f);
}
else
{
// Calculate the reciprocal value once and for all (to achieve speed)
float fScale1 = 1.0f / fDenominator;
/* Time to calculate the tangent, binormal, and normal.
Look at Søren’s article for more information. */
Vector3f T, B, N;
T = Vector3f((c3c1_B * v2v1.x() - c2c1_B * v3v1.x()) * fscale1,
(c3c1_B * v2v1.y() - c2c1_B * v3v1.y()) * fScale1,
(c3c1_B * v2v1.z() - c2c1_B * v3v1.z()) * fScale1);
B = Vector3f((-c3c1_T * v2v1.x() + c2c1_T * v3v1.x()) * fScale1, (-c3c1_T * v2v1.y() + c2c1_T * v3v1.y()) * fScale1, (-c3c1_T * v2v1.z() + c2c1_T * v3v1.z()) * fScale1); N = T%B; //Cross product! /*This is where programmers should break up the function to smooth the tangent, binormal and normal values. */ //Look at “Derivation of the Tangent Space Matrix” for more information. float fScale2 = 1.0f / ((T.x() * B.y() * N.z() - T.z() * B.y() * N.x()) + (B.x() * N.y() * T.z() - B.z() * N.y() * T.x()) + (N.x() * T.y() * B.z() - N.z() * T.y() * B.x())); InvTangent.set((B%N).x() * fScale2, ((-1.0f * N)%T).x() * fScale2, (T%B).x() * fScale2); InvTangent.normalize(); InvBinormal.set(((-1.0f *B)%N).y() * fScale2, (N%T).y() * fScale2, ((-1.0f * T)%B).y() * fScale2); InvBinormal.normalize(); InvNormal.set((B%N).z() * fScale2, ((-1.0f * N)%T).z() * fScale2, (T%B).z() * fScale2); InvNormal.normalize(); }
上述计算中可以只计算T。
相应的VS如下:
varying vec3 LightDir;
varying vec3 EyeDir; attribute vec3 Tangent; void main()
{
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
gl_TexCoord[0] = gl_MultiTexCoord0; // 眼坐标系下的TBN
vec3 n = normalize(gl_NormalMatrix * gl_Normal);
vec3 t = normalize(gl_NormalMatrix * Tangent);
vec3 b = cross(n, t);
mat3 TBN = mat3(t, b, n);
vec4 pos = gl_ModelViewMatrix * gl_Vertex;
vec3 epos = vec3(pos)/pos.w;
vec3 v = gl_LightSource[0].position.xyz - epos;
v = v * TBN;
LightDir = normalize(v); v = -epos * TBN;
EyeDir = normalize(v);
}
相应的FS如下:
uniform sampler2D BumpTex;
uniform sampler2D DecalTex; varying vec3 LightDir;
varying vec3 EyeDir; void main()
{
vec3 BumpNorm = vec3(texture2D(BumpTex, gl_TexCoord[0].xy));
BumpNorm = (BumpNorm -0.5) * 2.0;
vec4 DecalCol = texture2D(DecalTex, gl_TexCoord[0].xy);
float NdotL = max(dot(BumpNorm, LightDir), 0.0);
vec3 h = normalize(LightDir+EyeDir);
float NdotH = max(dot(BumpNorm, h), 0.0);
vec3 diffuse = vec3(NdotL * gl_LightSource[0].diffuse * DecalCol);
vec3 specular = vec3(pow(NdotH, 6) * gl_LightSource[0].specular);
gl_FragColor = vec4(diffuse + specular, 1.0);
}
Bump mapping的GLSL实现 [转]的更多相关文章
- 《The Cg Tutorial》阅读笔记——凹凸贴图 Bump Mapping
本文为大便一箩筐的原创内容,转载请注明出处,谢谢:http://www.cnblogs.com/dbylk/p/5018103.html 凹凸贴图 Bump Mapping 一.简介 凹凸贴图用于在不 ...
- Directx11教程(42) 纹理映射(12)-简单的bump mapping
原文:Directx11教程(42) 纹理映射(12)-简单的bump mapping 有时候,我们只有一个粗糙的模型,但是我们想渲染纹理细节,比如一个砖墙,我们如何在只有一个平面的时候 ...
- Parallax Occlusion Mapping in GLSL [转]
http://www.sunandblackcat.com/tipFullView.php?topicid=28 This lesson shows how to implement differ ...
- 翻译:非常详细易懂的法线贴图(Normal Mapping)
翻译:非常详细易懂的法线贴图(Normal Mapping) 本文翻译自: Shaders » Lesson 6: Normal Mapping 作者: Matt DesLauriers 译者: Fr ...
- Step deep into GLSL
1 Lighting computation is handled in eye space(需要根据眼睛的位置来计算镜面发射值有多少进入眼睛), hence, when using GLSL (GP ...
- 翻译:GLSL的顶点位移贴图
翻译:GLSL的顶点位移贴图 翻译自: Vertex Displacement Mapping using GLSL 译者: FreeBlues 说明: 之所以选择这篇文档, 是因为现在但凡提到位移贴 ...
- 在 OpenGL ES 2.0 上实现视差贴图(Parallax Mapping)
在 OpenGL ES 2.0 上实现视差贴图(Parallax Mapping) 视差贴图 最近一直在研究如何在我的 iPad 2(只支持 OpenGL ES 2.0, 不支持 3.0) 上实现 视 ...
- 【ZZ】 移位贴图 Displacement Mapping
http://blog.csdn.net/huazai434/article/details/5650629 说明:该技术需要VS3.0的支持!!! 一,移位贴图类似于地形渲染.不过由于移位纹理可以做 ...
- 3DShader之法线贴图(normal mapping)
凹凸贴图(bump mapping)实现的技术有几种,normal mapping属于其中的一种,这里实现在物体的坐标系空间中实现的,国际惯例,上图先: 好了讲下原理 可以根据高度图生成法线量图,生成 ...
随机推荐
- mysql大内存高性能优化方案
mysql优化是一个相对来说比较重要的事情了,特别像对mysql读写比较多的网站就显得非常重要了,下面我们来介绍mysql大内存高性能优化方案 8G内存下MySQL的优化 按照下面的设置试试看:key ...
- MySQL基础之第11章 插入、更新与删除数据
11.1.插入数据 11.1.1.为表的所有字段插入数据 1.INSERT语句中不指定具体的字段名 insert into 表名 values (值1,值2…值n)2.INSERT语句 ...
- WPF应用加载图片URI指定需要注意的地方
应用程序(.exe)加载图片: 可以省略"pack://application:,,," 打头,因为系统运行时需要的图片文件在Exe程序集(组合体)中:譬如: <Image ...
- 有关T-SQL的10个好习惯(转)
1. 在生产环境中不要出现Select * 这一点我想大家已经是比较熟知了,这样的错误相信会犯的人不会太多.但我这里还是要说一下. 不使用Select *的原因主要不是坊间所流传的将*解析成具体的列需 ...
- 典型的 SQL 注入过程(转)
无意间发现某站点存在 SQL 注入漏洞,于是利用这个漏洞提权并获取服务器控制权.这个案例很典型,像是教科书式的典型入侵步骤,下面就以这个案例展示从 SQL 注入到获取目标服务器控制权限的全过程. 发现 ...
- Minimax Triangulation
题意: 按顺序给定一些点,把这些点分割为n - 2个三角形,花费为最大三角形面积,求最小花费 分析: 区间dp,dp[i][j]表示完成区间[i,j]最小花费,dp[i][j]=min(dp[i][j ...
- SPOJ DISUBSTR Distinct Substrings 后缀数组
题意:统计母串中包含多少不同的子串 然后这是09年论文<后缀数组——处理字符串的有力工具>中有介绍 公式如下: 原理就是加上新的,减去重的,这题是因为打多校才补的,只能说我是个垃圾 #in ...
- 【Windows核心编程】VirtualAlloc 例子
// VirtualAlloc.cpp : 定义控制台应用程序的入口点. // #include "stdafx.h" #include <Windows.h> #in ...
- wuzhicms 后台登录存留时间实现方式
在五指后台管理登录后,超过半小时不操作后台(不刷新页面或切换页面),就就会强制退出后台. 实现的思路是,在每次刷新页面都把当前时间存储下来,利用php的session机制来检测比对当前时间和数据库中存 ...
- XNA Game Studio4.0 Programming 随便读,随便记。
一.精灵和2D图形 1.什么是2D ? 2D可以理解为 two-Dimentionanl , 2-dimentional 的缩写. 意就是两维的,比如 数学中的 直角坐标系 所能描述的就是一个2D的 ...