当前位置:首页 > XNA高级编程-第7章实现法线映射
7.0概览
使用shader最大的好处是每一步的渲染管道都可自定义。支持Pixel Shader版本1.1 (GeForce 3 )你你有8条指令可用,支持Pixel Shader 2.0更灵活且允许实现更多的功能(在上一章的normalize和pow方法只适用于Pixel Shader 2.0)和更多的指令(最多96个,但一些方法需要一个以上的指令) 。
Pixel shader 3.0允许更好的流控制,这意味着您可以更好地优化性能。Pixel Shader 3.0最多可以有512条指令。就算你有16、24或32个像素shader并行处理器,当绘制上百万个像素时,仍要花很多时间来为每个像素执行许多指令,新的NVIDIA 8800 GTX的图形卡甚至有128个shader处理器。有时候当一个像素不受灯光影响或不在阴影里,你可以跳过复杂的计算,通过这种形式,您仍然可以实现漂亮的Pixel Shader的效果,但在现实中最新的游戏只需支持Pixel Shader 2.0,因为它是支持许多图形卡;最典型的游戏不支持较昂贵的图形硬件。
Shader Model 4.0与Direct3D 10(2006年初)一同推出,第一个支持它的图形硬件是2006年年底发布的GeForce 8800,但Direct3D的10只适用于Vista而且硬件相当昂贵。游戏开发商可以充分利用Shader Model 4.0还需要一段时间。xna目前仅支持1.1至3.0版本的Shader模型。 Shader Model 4.0允许更多的指令,并提出了几何shader(可以在顶点和像素shader执行前添加几何数据)。在Shader Model 4.0所有的Shader流处理器被统一在一起,这意味着有不再是8个顶点处理器和16个像素处理器,而是统一128 个shader处理器通用于几何,顶点和像素shader,这对如位移映射之类的effect很有用。在2007年,您可以期望一些很酷的演示,可能直到2008年或稍后才会使用几何shader。
7.1给对象加入细节
为您接下去要制作的游戏中会使用到Normal Mapping(法线映射) shaders,对表面有很多的结构和小细节的物体,比如管道,电缆这些需要用上百万的才能显示所有细节的情况,使用Normal Mapping(法线映射) shaders能大大改善三维物体的表现(见图7-1)。你能经常在网上看到一些Normal Mapping的例子that compare totally ridiculous looking objects and bad textures with a super high resolution Normal Mapped object。我试着use real object from a real game(这本书后面的Racer游戏会用到),因为diffuse纹理有一点阴影效果,所以没有Normal Mapping效果也不错。通过这种方式,您可以不使用Normal Mapping,但物体看上去仍不错。使用Normal Mapping能使物体看起来更好,即使只有1000多边形,看起来也非常平滑。
第 1 页 共 28 页
图7-1
想要得到更好的效果还能使用Parallax Mapping(视差映射),Offset Mapping或Displacement Mapping(位移映射, Shader Model 4支持,但代价昂贵)。这些技术较为复杂,除了diffuse贴图和Normal Map贴图外还需要额外的height map(高度图)。但使用Normal Mapping已经足够好了。
如果您有一块带shader功能的图形卡,Normal Mapping并不难实现。在老的GeForce 3 (shader1.1版)也能工作,就现今支持Pixel Shader 2.0的硬件可以更好地实现反光,效果会更好。通过前一章的学习你已经有了基本的基础,包括如何创造shader、如何转换顶点、像素如何最终显示在屏幕上。
Normal Mapping 需要额外的纹理。diffuse纹理是用来显示基本的材质,颜色等等。Normal Map纹理通过提供顶点向量添加更多的3D细节。
图7-2
第 2 页 共 28 页
请注意,如果您打开仙人掌的三维模型的kaktusseg.dds和kaktussegnormal.dds贴图,会发现kaktussegnormal.dds看上去不同,这是因为正Normal Map是压缩的,并已经被Alpha和红色通道反转,这样可以在没失去很多细节的前提下把纹理压缩至1:4,看起来仍不错。More details about this technique in a second - just remember that internally the Normal Map texture looks like the texture in 图7-2;the compressed version just stores the data differently。
计算每个像素的光线是要用到Normal Mapping 纹理中的数据,Normal Map中的每一个像素代表了多边形表面的法线向量。这一数据是储存在正切空间,可参见图7-4。从贴图中的颜色数据获得法线向量要用到公式(each r, g and b value-0.5)/0.5(见图7-3),Normal Map中的RGB颜色数据以浮点数的形式被用在公式里,要将RGB颜色数据转换成浮点数,只需除以255,这在Pixel Shader里是自动完成的。比起位图文件的字节数据,浮点数更容易使用。
Normal Map中最多的颜色是淡蓝(RGB 128,128,255),这意味着大多数向量是向上的,即vector3(0,0,1)。如果整个纹理都是浅蓝色的,这意味着每个向量都朝上,那么,Normal Map将没有任何效果。
这些Normal Map像素通常存放在切线空间,这意味着法线数据和多边形表面是有联系的。这是所谓
第 3 页 共 28 页
的切空间,通过每个顶点的切线和binormal向量你才能建立切线矩阵,而binormal可以通过叉乘法线向量和切线向量得到(见图7-4) 。在上一章,你只有每一点的位置,法线和纹理坐标数据,这些数据对Normal Mapping来说是不够的,您至少需要每个顶点的切线矢量去建立这个切线矩阵,如果没有切线数据的话Normal Mapping 图像显示将不正确。
你可以把切向和binormal 向量看成指向下一个顶点x和y方向的向量, but they are still octagonal (in a 90 degree angle) to the normal vector。这意味着,即使您的三维模型没有任何切线数据,您也可以遍历所有顶点自己创建(不容易,但是可行的)。
问题
问题是,往往顶点可用于一个以上的多边形,有时纹理坐标合并得也不好。对diffuse mapping来说这问题不大,因为您只使用法线向量计算光线,但如果你通过切线空间转换每个像素的法线,就要求数据必须配合。这意味最好在三维程序中生成切线数据,三维程序知道如何在Normal Mapping shader中更好地使用哪些切线和输出法线。在vertex shader中你只能访问到目前您正在处理的顶点,而不能访问下一个顶点,或建立一个新的向量指向下一个顶点。这意味着,将有效的切线数据传送到vertex shader(顶点着色引擎)是很重要的。如果你只是定义了支持切线的vertex input structure,也不意味着应用程序能够处理有效的切线数据。通常您在内容管道有.x或.fbx文件,它没有任何切线的数据(见图7-5 )。
图7-5
这意味着你仅有法线数据而没有切线数据,这样就无法为Normal Mapping创建切线空间。对于简单的对象比如这个苹果问题不大,但如何模型有更多的曲线和纹理坐标就会出现显示错误。图7-6显示的就是切线错误的苹果模型。
图7-6
第 4 页 共 28 页
共分享92篇相关文档