博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Directx11教程(42) 纹理映射(12)-简单的bump mapping
阅读量:5371 次
发布时间:2019-06-15

本文共 3014 字,大约阅读时间需要 10 分钟。

原文:

 

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

   比如只有这样的墙:

 pic0047.gif

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

pic0061.gif

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

 

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

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

pic0060.gif

      在物体表面,每个点都都有一个(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

代码下载:

posted on
2019-05-06 08:40 阅读(
...) 评论(
...)

转载于:https://www.cnblogs.com/lonelyxmas/p/10817638.html

你可能感兴趣的文章
antiSMASH数据库:微生物次生代谢物合成基因组簇查询和预测
查看>>
UNICODE与ANSI的区别
查看>>
nginx 配置实例
查看>>
Flutter - 创建底部导航栏
查看>>
ASP.NET MVC 教程-MVC简介
查看>>
SQL Server索引 - 聚集索引、非聚集索引、非聚集唯一索引 <第八篇>
查看>>
转载:详解SAP TPM解决方案在快速消费品行业中的应用
查看>>
Android OpenGL ES 开发(N): OpenGL ES 2.0 机型兼容问题整理
查看>>
项目中用到的技术及工具汇总(持续更新)
查看>>
【算法】各种排序算法测试代码
查看>>
HDU 5776 Sum
查看>>
201521123044 《Java程序设计》第9周学习总结
查看>>
winfrom 图片等比例压缩
查看>>
人工智能实验报告一
查看>>
用LR12录制app,用LR11跑场景,无并发数限制,已试验过,可行!
查看>>
python 多线程就这么简单(转)
查看>>
oracle 简述
查看>>
ajax如何向后台传递数组,在后台该如何接收的问题(项目积累)
查看>>
Solr之java实现增删查操作
查看>>
httpClient连接工具类实测可用
查看>>