Irrlicht引擎Shader渲染的BUG

来源:互联网 发布:软件开发项目保密协议 编辑:程序博客网 时间:2024/05/21 10:36

----------修改2----------------------------------------------------------------------------------------------------------------

丢人了, 回头一看原来的理解还是不够完整。

如果在视图空间计算光照等, 一般都会将法线变换到视图空间。想当然的做法是用视图矩阵来变换法线,这么做只有在物体没有缩放或是一致性缩放的情况下才是正确的。若是物体有非一致性缩放(uniform-scale),变换出来的法线方向是不正确的。如下图。

                 

这也是gl_NormalMatrix这个矩阵的作用,法线的变换需要使用的是视图矩阵的逆的转置,具体的推导可参见http://blog.csdn.net/racehorse/article/details/6664775


OpenGL计算出的这个矩阵就保存在gl_NormalMatrix里。

如果在世界空间里计算光照  变换法线要用的矩阵就是世界矩阵逆的转置了。

那么再回到正题, 为什么之前的 ”世界矩阵的逆矩阵“ 改成  “世界矩阵”   就正确了? 就是因为没有缩放


所以在Example10里正确的做法是  先取出世界矩阵  求逆  求转置  再传到 shader 里,  如此  大功告成!


----------修改----------------------------------------------------------------------------------------------------------------

最近才发现这个BUG的原因:

vexter shader里在将法线变换到世界坐标系时,乘的是世界矩阵的逆矩阵,导致法线变换错误。

只需将逆世界矩阵改成世界矩阵就可以了


----------原文-------------------------------------------------------------------------------------------------------------------------------

Irrlicht的SDK里带有一系列Example,第10个是关于Shader的。细看了一下,发现有些问题。

我先简单说一下这个demo,它在场景中(sceneMgr)添加了三个CubeBox,一个没有shader,默认使用材质video::EMT_SOLID,另外两个使用了shader,但材质类型分别是video::EMT_SOLID和video::EMT_TRANSPARENT_ADD_COLOR,然后都加了Y方向的自身旋转 。

它使用IShaderConstantSetCallBack来给shader的参数赋值, demo里使用的shader也很简单。

uniform mat4 mWorldViewProj;uniform mat4 mInvWorld;uniform mat4 mTransWorld;uniform vec3 mLightPos;uniform vec4 mLightColor;void main(void){gl_Position = mWorldViewProj * gl_Vertex;vec4 normal = vec4(gl_Normal, 0.0);normal = mInvWorld * normal;normal = normalize(normal);vec4 worldpos = gl_Vertex * mTransWorld;vec4 lightVector = worldpos - vec4(mLightPos,1.0);lightVector = normalize(lightVector);float tmp2 = dot(-lightVector, normal);vec4 tmp = mLightColor * tmp2;gl_FrontColor = gl_BackColor = vec4(tmp.x, tmp.y, tmp.z, 0.0);gl_TexCoord[0] = gl_MultiTexCoord0;}


uniform sampler2D myTexture;void main (void){    vec4 col = texture2D(myTexture, vec2(gl_TexCoord[0]));    col *= gl_Color;    gl_FragColor = col * 4.0;}


它使用当前camera的位置为mLightPos,然后根据法线算一个点乘的值做为受光的强度因子,这样当运行时,随着BOX的旋转,面对镜头的面都是受光的(亮的)。


为了测试结果,我把三个BOX都去了,换成了一个Spere, 使用shader,材质是video::EMT_SOLID,依然有Y方向旋转(从右向左),并且将shader里的贴图颜色去了,只使用光的颜色。



可以看到竟然出现了半黑和全黑的情况,官方demo里那两个使用了shader的cubebox,旋转时也会“黑”



接下来,我将spere的旋转去掉,然后在camera上加了一个“FlyCircle”的旋转,让其围绕场景(0,0,0)点运动,终于出现了想像中的结果,“面向镜头的始终是亮的”。


难道在Shader计算时 “gl_Normal"的值不对吗?

原创粉丝点击