有时候,我们只有一个粗糙的模型,但是我们想渲染纹理细节,比如一个砖墙,我们如何在只有一个平面的时候,渲染出砖墙凹凸的效果。

比如只有这样的墙:

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

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

对于一张图片,假设像素排列如上图所示,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

转载于:https://www.cnblogs.com/mikewolf2002/archive/2012/04/21/2461372.html

Directx11教程(42) 纹理映射(12)-简单的bump mapping相关推荐

  1. Directx11教程39 纹理映射(9)

    Directx11教程39 纹理映射(9) 原文:Directx11教程39 纹理映射(9) 在myTutorialD3D11_32中,我们在PlaneModelClass中增加一个纹理Texture ...

  2. Directx11教程40 纹理映射(10)

    本章尝试使用纹理行列式,或者说纹理数组,在ps中,使用2个纹理,最终的像素颜色,是光照颜色*纹理1采样颜色*纹理2采样颜色,主要是想达到如下的效果: 把这两个图像以及光照产生的颜色融合生成以下图像: ...

  3. Directx11教程(6) 画一个简单的三角形(2)

    在上篇教程中,我们实现了在D3D11中画一个简单的三角形,但是,当我们改变窗口大小时候,三角形形状却随着窗口高宽比例改变而改变,如下图所示: 这是因为我们改变了窗口大小,但后缓冲大小在程序初始化时候, ...

  4. Directx11教程(19) 画一个简单的地形

    通常我们在xz平面定义一个二维的网格,然后y的值根据一定的函数计算得到,比如正弦.余弦函数的组合等等,可以得到一个看似不错的地形或者水面的效果. 在本教程中我们修改ModelClass.h和Model ...

  5. Directx11教程(33) 纹理映射(3)

    现在我们在myTutorialD3D11_5的基础上,来逐步编码实现纹理映射,之所以在myTutorialD3D11_5基础上改写,是因为这个工程只是画了一个三角形,便于我们贴一个纹理上去,然后改变纹 ...

  6. 【C# 教程系列第 12 篇】抽象类的简单实现

    这是[C# 教程系列第 12 篇],如果觉得有用的话,欢迎关注专栏. 上一篇博客讲到了 C# 中的抽象类与抽象方法,对这两个概念不清楚的可以 点击此处 通过上篇博客我们会发现,使用 abstract ...

  7. DirectX11教程

    最近在看DirectX11的教程,我对dx的接触也只是皮毛,边看边学吧. 看看网上只有w18767104183翻译了前三章,想着能不能继续他翻译一点呢,希望自己能一起成长. 点击图片是官方网站,译文点 ...

  8. 《Groovy极简教程》第12章 Groovy的JSON包

    <Groovy极简教程>第12章 Groovy的JSON包 Groovy自带了转换JSON的功能,相关类都在groovy.json包下.本文参考自Groovy文档 Parsing and ...

  9. Directx11教程(14) D3D11管线(2)

    Directx11教程(14) D3D11管线(2) 原文:Directx11教程(14) D3D11管线(2) 下面我们来了解一些GPU memory的知识,主要参考资料:http://fgiese ...

最新文章

  1. 新技术、新思维开创公共安全管理新模式
  2. 首发 | 13篇京东CVPR 2019论文!你值得一读~ 技术头条
  3. Python 面试总结
  4. 【CVPR2019】Workshops 研讨会列表及链接
  5. Oracle视图分类及各种操作讲解(超级好文)
  6. java http服务_springboot官方例子中文翻译--RESTful服务启用CORS支持
  7. python unique函数_每30秒学会一个Python小技巧,GitHub星数4600+
  8. DeskFX for Mac(音频增强软件) 适配M1芯片
  9. 《Android游戏编程之从零开始》笔记
  10. Java 正则表达式,正则表达式匹配a标签下的链接,正则表达式基础
  11. html站点地图怎么做,如何制作网站地图,制作网站地图的步骤
  12. 安卓和win环境下扫描局域网下设备IP的工具
  13. Netty websocket 推送数据压缩以 js解压
  14. c# winform 任务栏显示和隐藏
  15. 怎么压缩动态图片?手机怎么压缩gif动图?
  16. Devexpress Xtrareport 创建主从报表
  17. TM4C123G学习记录(6)--UART
  18. 智芯传感推出性能卓越的多量程硅微加速传感器ZXA
  19. ssh无输入密码登录问题
  20. windows linux 共享鼠标,Synergy工具 共享Windows系统电脑Linux系统电脑 鼠标键盘

热门文章

  1. python将csv文件拆分_【中年阿姨python入门】CSV文件拆分(DictReaderDictWriter)
  2. SpringBoot 2 + Spring Security 5 + JWT 的单页应用 Restful 解决方案
  3. swift LOG 输出
  4. Python测试框架pytest(02)PyCharm设置运行pytest、pytest.main()
  5. angularjs和mysql_AngularJS SQL
  6. js中显示一个指定html文档,JS实现选定指定HTML元素对象中指定文本内容功能示例...
  7. http get请求相同的key_B站微服务框架Kratos详细教程(2)HTTP服务
  8. nginx mysql设置远程连接超时_docker -mysql服务设置远程连接 解决1251 client does not support ..问题...
  9. 获取地区html代码,根据ip地址获取所在城市信息(省市县)代码
  10. 女生读计算机专业好,女生选择计算机专业就读好吗?