水面反射贴图为什么会出现扭曲现象

本文探讨了在游戏开发中实现水面反射时遇到的纹理扭曲问题,并详细解释了如何通过调整纹理坐标计算方法及利用Pixel Shader 1.4来解决这一问题。
最近在研究如何制作水面反射,当渲染好反射贴图后,需要将反射贴图贴到湖面上。

 

最开始,我想到最直接的办法就是利用湖面顶点在View-Projection空间的X、Z坐标值进行插值,来映射纹理,纹理坐标=ViewProj空间X、Z坐标 * 0.5 + 0.5。

但是发现反射图像出现奇怪的扭曲现象,一开始以为是纹理坐标环绕设置有问题( 设置成D3DTADDRESS_WRAP或者D3DTADDRESS_CLAMP等值后发现没有任何改观 )。同时,又发现一个奇怪的现象:如果湖面的顶点数量越多,则扭曲程度越小。由于我一直在纹理坐标寻址上转不过弯,所以始终没有找到解决办法。


后来,通过参考微软DX SDK的程序,发现这么一段话
If D3DPTEXTURECAPS_PROJECTED is set, projected textures are computed per pixel,
so this sample will work fine with just a quad for the water model.  If it's 
not set, textures are projected per vertex rather than per pixel, so distortion
will be visible unless we use more vertices.

这段话揭示了我发现的顶点数量越多,则扭曲程度越小的现象,同时指出如果“D3DPTEXTURECAPS_PROJECTED”标志被设置,则纹理是按照逐像素方式计算投影坐标,逐像素方式可以避免扭曲的出现。

再通过查找DX的Help档,发现这么一段针对PixelShader中的_dw/_da/_dz/_db操作符的重要的说明:

For pixel shader version 1.4, the D3DTTFF_PROJECTED flag under D3DTSS_TEXTURETRANSFORMFLAGS
is ignored because a projective divide is accomplished by the source register modifiers 
listed previously.( 在PS1.4中,由于在纹理坐标寄存器具有预先除法的功能,所以,“D3DTTFF_PROJECTED”标志可以忽略。)

所以,结论是通过利用PS.1.4中的texcrd指令和dw操作符组合,可以解决扭曲现象。

至此,终于明白了扭曲的原因,因为纹理坐标 U = X / w * 0.5 + 0.5, V = Y / w * 0.5 + 0.5,其中:由于齐次坐标中的w分量是一个变化量而非一个常数,所以U与X并非一个线性变化( 比如,X扩大2倍,U并非同时扩大2倍,因为w也变化了 ),所以,如此通过per-Vertex方式插值出来的UV坐标必然是不对的( U = x / w并非一个线性变化 ),所以,只能把X、Y、W统统送到PS中去运算才对,而在VS中运算好后再通过硬件插值的方案是行不通的。

最终,可以很容易得到如下逐像素投影纹理坐标的解决方案:
PS.1.4
texcrd r0.rg, t0_dw.xyw
...
phase
texld r0, r0
....

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值