Directx11教程(42) 纹理映射(12)-简单的bump mapping
原文:Directx11教程(42) 纹理映射(12)-简单的bump mapping
有时候,我们只有一个粗糙的模型,但是我们想渲染纹理细节,比如一个砖墙,我们如何在只有一个平面的时候,渲染出砖墙凹凸的效果。
比如只有这样的墙:

但是我们想要这样的效果:

怎么办呢?这时候,我们可以考虑对第一张图进行处理,生成它的法向图,存储在一张纹理中,生成法向图的主要算法是:

对于一张图片,假设像素排列如上图所示,Hg,Hr,Ha分别表示这些点的RGB(或灰度)值,我们得到第一个向量(1,0,Hr-Hg),第二个向量(0,1,Ha-Hg),则法向可以通过它们的差积得到:

对所有的像素进行处理,我们可以得到一个纹理的法向图,比如第一张墙纹理贴图,经过计算,它的法向图为:


在物体表面,每个点都都有一个(T,N,B)的局部坐标系,分别对应切向、法向,副法向,有了纹理图后,我们可以通过公式
bumpNormal = normal + bumpMap.x * tangent + bumpMap.y * binormal; 得到最终的法向。其中bumpMap为前面计算得到的法向贴图,或者说normal map。
1、首先我们改写CubeModelClass类,设置顶点格式为:
struct VertexType
{
D3DXVECTOR3 position;
D3DXVECTOR3 normal; //法向
D3DXVECTOR3 tangent; //切向
D3DXVECTOR3 binormal; //副法向
D3DXVECTOR2 texture; //纹理坐标
D3DXVECTOR4 Kd; //材质漫反射系数
D3DXVECTOR4 Ks; //材质的高光系数
};
增加了切向和副法向的计算,主要通过顶点的uv坐标以及顶点值求得
void CubeModelClass::CalculateTangentBinormal(TempVertexType vertex1, TempVertexType vertex2, TempVertexType vertex3,
VectorType& tangent, VectorType& binormal)
{
float vector1[3], vector2[3];
float tuVector[2], tvVector[2];
float den;
float length;
// 计算2个向量.
vector1[0] = vertex2.x - vertex1.x;
vector1[1] = vertex2.y - vertex1.y;
vector1[2] = vertex2.z - vertex1.z;
vector2[0] = vertex3.x - vertex1.x;
vector2[1] = vertex3.y - vertex1.y;
vector2[2] = vertex3.z - vertex1.z;
// 计算tu和tv向量.
tuVector[0] = vertex2.tu - vertex1.tu;
tvVector[0] = vertex2.tv - vertex1.tv;
tuVector[1] = vertex3.tu - vertex1.tu;
tvVector[1] = vertex3.tv - vertex1.tv;
den = 1.0f / (tuVector[0] * tvVector[1] - tuVector[1] * tvVector[0]);
tangent.x = (tvVector[1] * vector1[0] - tvVector[0] * vector2[0]) * den;
tangent.y = (tvVector[1] * vector1[1] - tvVector[0] * vector2[1]) * den;
tangent.z = (tvVector[1] * vector1[2] - tvVector[0] * vector2[2]) * den;
binormal.x = (tuVector[0] * vector2[0] - tuVector[1] * vector1[0]) * den;
binormal.y = (tuVector[0] * vector2[1] - tuVector[1] * vector1[1]) * den;
binormal.z = (tuVector[0] * vector2[2] - tuVector[1] * vector1[2]) * den;
length = sqrt((tangent.x * tangent.x) + (tangent.y * tangent.y) + (tangent.z * tangent.z));
// 归一化
tangent.x = tangent.x / length;
tangent.y = tangent.y / length;
tangent.z = tangent.z / length;
// 计算向量的长度.
length = sqrt((binormal.x * binormal.x) + (binormal.y * binormal.y) + (binormal.z * binormal.z));
// 归一化向量
binormal.x = binormal.x / length;
binormal.y = binormal.y / length;
binormal.z = binormal.z / length;
return;
}
得到面的法向、切向以及副法向后,把他们赋值给顶点。
然后我们在LightTex2ShaderClass中,改变layout,然后修改lighttex2.vs和lighttex2.ps
特别是ps中,我们改变normal的计算方式:
float3 N;
float4 textureColor;
float4 textureColor1 = shaderTexture[0].Sample(SampleType, input.tex);
float4 textureColor2 = shaderTexture[1].Sample(SampleType, input.tex);
float4 bumpMap;
float3 bumpNormal;
//从范围[0,1]转换到[-1,1],因为默认法向图我们用[0,1]的这种方式打开
bumpMap = (textureColor2 * 2.0f) - 1.0f;
N = input.worldnormal + bumpMap.x*input.worldtangent + bumpMap.y*input.worldbinormal;
N = normalize(N);
程序执行后,我们按R键,可以得到下面的结果:

因为使用的是面法向,我们再看侧面,有着不同效果,:

完整的代码请参考:
工程文件myTutorialD3D11_37
代码下载:
http://files.cnblogs.com/mikewolf2002/d3d1127-28.zip
http://files.cnblogs.com/mikewolf2002/pictures.zip
Directx11教程(42) 纹理映射(12)-简单的bump mapping的更多相关文章
- Directx11教程40 纹理映射(10)
原文:Directx11教程40 纹理映射(10) 本章尝试使用纹理行列式,或者说纹理数组,在ps中,使用2个纹理,最终的像素颜色,是光照颜色*纹理1采样颜色*纹理2采样颜色,主要是想达到如 ...
- Directx11教程39 纹理映射(9)
原文:Directx11教程39 纹理映射(9) 在myTutorialD3D11_32中,我们在PlaneModelClass中增加一个纹理TextureClass* m_Texture;读 ...
- Directx11教程(35) 纹理映射(5)
原文:Directx11教程(35) 纹理映射(5) 到现在为止,我们的TextureClass初始化函数非常简单,说白了就是一行代码: result = D3DX11CreateShader ...
- Directx11教程(33) 纹理映射(3)
原文:Directx11教程(33) 纹理映射(3) 现在我们在myTutorialD3D11_5的基础上,来逐步编码实现纹理映射,之所以在myTutorialD3D11_5基础上改写,是 ...
- Directx11教程(19) 画一个简单的地形
原文:Directx11教程(19) 画一个简单的地形 通常我们在xz平面定义一个二维的网格,然后y的值根据一定的函数计算得到,比如正弦.余弦函数的组合等等,可以得到一个看似不错的地形或者 ...
- Directx11教程(5) 画一个简单的三角形(1)
原文:Directx11教程(5) 画一个简单的三角形(1) 在本篇教程中,我们将通过D3D11画一个简单的三角形.在D3D11中,GPU的渲染主要通过shader来操作(当然还有一些操作 ...
- Directx11教程(43) 纹理映射(13)-动态纹理映射
原文:Directx11教程(43) 纹理映射(13)-动态纹理映射 本篇教程中,我们将在前面基于光照的地形与水面程序里面加上纹理映射,而且我们会基于时间动态改变水面的纹理坐标,实现水面纹理 ...
- Directx11教程41 纹理映射(11)
原文:Directx11教程41 纹理映射(11) 1.第一副图我们采用各性异性的滤波方式,并设置最大各性异性值为8. samplerDesc.Filter = D3D11_FILT ...
- Directx11教程38 纹理映射(8)
原文:Directx11教程38 纹理映射(8) 上篇日志中,我们用纹理和光照颜色调制的方式得到最终颜色,本章我们尝试用纹理采样的颜色,直接做为材质的漫反射系数Kd,并用它来做光照计算,最后 ...
随机推荐
- extern “C”的用法
引言 由于不同的代码互相调用起来很容易出错,甚至同一种代码但由不同的编译器编译,为实现C++代码调用其他C语言代码,会在C语言代码的部分加上extern "C",表明这段代码需要按 ...
- MyBatis-Spring(一)--搭建步骤
MyBatis-Spring项目不是Sring项目的子框架,而是由MyBatis社区开发的,所以在使用之前首先要导入mybatis-spring包,我是通过maven添加的依赖: <depend ...
- PAT甲级——A1019 General Palindromic Number
A number that will be the same when it is written forwards or backwards is known as a Palindromic Nu ...
- notes 摘自陶哲轩演讲
摘自陶哲轩演讲http://www.youku.com/playlist_show/id_5267259.htmlA frog in a well 井底之蛙 Aristotle 亚里士多 ...
- docker 安装redis 并配置外网可以访问 - flymoringbird的博客 - CSDN博客
原文:docker 安装redis 并配置外网可以访问 - flymoringbird的博客 - CSDN博客 端口映射,data目录映射,配置文件映射(在当前目录下进行启动). docker run ...
- Hadoop IO 特性详解(2)【文件校验】
(本文引用了microheart,ggjucheng的一些资料,在此感谢.charles觉得知识无价,开源共享无价) 这一次我们接着分析文件IO校验的相关代码,看看最底层是如何实现这种大数据集的文件校 ...
- LUOGU P1779 魔鬼杀手_NOI导刊2010提高(03)
传送门 解题思路 背包,首先先用aoe都打残然后单伤补刀,用f[i]表示AOE打了i的伤害的最小花费,g[i]表示单伤打了i的伤害的最小花费. 代码 #include<iostream> ...
- 对BOM的总结
参考:JavaScript半知半解 TG著 BOM对象 Window对象是客户端JavaScript程序的全局对象. Window对象使得JavaScript与浏览器进行交互. 所有的JavaScri ...
- ubuntu 已安装 post-installation 脚本 返回错误状态 1
1.$ sudo mv /var/lib/dpkg/info /var/lib/dpkg/info_old //现将info文件夹更名 2.$ sudo mkdir /var/lib/dpkg/inf ...
- org.hibernate.service.ServiceRegistryBuilder被弃用
看视频教程是这样写的: //创建配置对象 Configuration config = new Configuration().configure(); //创建服务注册对象 ServiceRegis ...