shader学习很长时间了,但是一直没机会写现在开始对rendermonkey所有例子进行翻译...并且亲手写一下要不然老是跃然纸上太装喵了......~个人对shader的理解:语言是脚本式的,难点在思想...从两处入手:1.shader的流水线层次(我自己起的),大概的意思是d3d里面的流水线的规则啦,或者一些遗留技巧啦~ 这些东西往往查一下就豁然开朗了,具体入手点下面说到. 2.算法层....跟着科学家走....
normalmapfilter我在rendermonekey例子里面随便找的.....还是比较小巧他的Description这么说的:
The Sobel filter extracts the first order derivates of the image,
that is, the slope. The slope in X and Y directon allows us to
given a heightmap evaluate the normal for each pixel. This is
the same this as ATI's NormalMapGenerator application does,
except this is in hardware.
These are the filter kernels:
SobelX SobelY
1 0 -1 1 2 1
2 0 -2 0 0 0
1 0 -1 -1 -2 -1
中心思想是要生成出一个normal map的效果.
vs如下
ps如下
开始研究.......
第一句 Pos.xy = sign(Pos.xy); .....忽视.....1.我用的09august查不到....2网上也没查到..... 如果查到请告诉我谢谢
这三句
Out.Pos = float4(Pos.xy, 0, 1);
// Image-space
Out.texCoord.x = 0.5 * (1 + Pos.x);
Out.texCoord.y = 0.5 * (1 - Pos.y);
这一段只有三行包含的内容却很多....
同样的一段在dx的shadowmap 也出现过
//transform from RT space to texture space.
float2 ShadowTexC = 0.5 * vPosLight.xy / vPosLight.w + float2( 0.5, 0.5 );
ShadowTexC.y = 1.0f - ShadowTexC.y;
//出现在ps里面
对比一下dx的sm粒子vPosLight.xy / vPosLight.w 这里除以w.后面会说到怎么跟他对应上
从字面上去理解这句话~就是通过顶点的坐标来求得对应的纹理坐标,------就是投影纹理求纹理坐标的过程.~ 投影纹理决定下篇做个例子,先说他的求纹理过程.~
p'是p透视变换后的点,同时p的纹理坐标也进行了透视变换,然后再对纹理采样的时候就展现出透视纹理的效果.~ 如果不明白可以参考<3d游戏编程大师技巧>里面对 透视纹理和放射纹理的推导.~
普通的情况下d3d对外隐藏了这一过程.~你对某个顶点指定好纹理坐标后,剩下的事情全部都由d3d搞定了.~ 对于本篇来说,需要自己去计算纹理坐标. 所以需要关注他流水线的细节~
如果对p做过透视变换后,规格化到ndc空间,d3d跟opengl规则不同,不考虑深度的z的话 坐标就是(-1,1),(1,1),(1,-1),(-1,-1),你的所有坐标点就在这个范围内~. 此时你对这个坐标系x轴方向 * 0.5 + 0.5 就变成[0,1], 对y方向 (跟opengl又不同.....向下去正) 0.5 - y*0.5 也是[0,1], 于是就对应到纹理坐标了~这就是用顶点求到坐标的过程~.顶点被投影以后,纹理坐标也被投影,d3d,ps的时候是差值的所以,如果在vs里面对顶点进行了变换要考虑w buffer,就是1/z.关于仿射纹理和透视纹理的可以看一下<3d编程大师技巧>这本书,推导的很详细.简单来说由于投影原因导致原本纹理坐标的线性变化,如果是像素级的一一投影纹理的话是没问题的,但是d3d对投影的顶点坐标之间是线性插值.所以如果想保证这个投影后的线性插值跟为投影之前的一一对应,最后推导后得出的结论是线性插值的点/w就跟原来投影前一一对应了,w是1/z.
到这基本上说明了顶点坐标到纹理坐标的一个对应关系. <3d编程大师技巧>的作者说过一句:魔鬼藏在于细节中....rm的normalfilter是写在vs里面的转换纹理坐标, dx的例子写在ps里面的,效果一样吗?
是不一样的,ps里面做的事情是把顶点的坐标进行线性插值来求出中间点的,所以 Out.texCoord.x = 0.5 * (1 + Pos.x);这句话
的理解应该是
Out.texCoord.x = 0.5 * (1 * Pos.w + Pos.x ); //Pos.x 是已经经过透视变换的
同时ps里面的应该是 tex2D(BaseMap, texCoord/w); 或者是tex2Dproj(BaseMap, texCoord)
此例子中w是1,这样的话跟dx里面的情况就一样了~ dx里面的就是直接在ps里面计算每一个点插值 显然dx那个计算比较多....
基本上清楚了rendermonkey里面的例子对opengl和dx的操作一样 所以很容易发现d3d和opengl纹理坐标系的差别
opengl的
颠倒了.....
以上我感觉属于shader的流水线层次(我自己起的),就是3d里面的一些潜规则.~
ps里面剩下的属于ati那些工程师发明的~ 大部分就是用来求其效果
这篇文章来求normal的~ 有点意思晚上 在写~