【旧博客转移 - 2017年1月20日 01:20 】
前面的话最近很长时间没写博文了,一是太忙 ( lan ) 了,二是这段时间又领悟了一些东西,脑子里很混乱,不知道从何写起。但感觉不能再拖延下去了,来不及解释了,快上车(一脸滑稽)
目前我在做一款3D二次元动作游戏,后面可能会用到动态阴影,有的人可能会直接找一个插件分分钟就把阴影做出来了,这样做当然可以,但自己不去熟悉一下底层原理只是使用工具的话,很难知道性能瓶颈在哪,如果要做一些改动,只能跟策划说:改不了咯
先看效果这个菊花是投影到地上的,这样的平地可能感觉不出来什么是投影
但是像这样遇到凹凸地形的时候就会明显了,菊花不会直接插入平地,而是贴在球体的表面,就像一个投影机把幻灯片照上去的感觉
实现原理如上图所示,左边的图是一个顶点渲染到我们的屏幕上要经过这么多的矩阵变换,这里来复习下MVP变化
顶点从模型坐标空间转换到世界坐标空间 X ModelMaterix
然后从世界坐标空间转换到视点空间 X CameraViewMaterix
再从视点空间转换到裁剪空间 X CameraProjectionMatrix
经过其次空间变化后就到了NDC空间,最后到了屏幕空间
经过这些步骤,一个顶点就确定了在屏幕上的位置
右边是将视点当作投影机,根据模型空间的坐标求出投影纹理的坐标的流程,两边前面的步骤都差不多,但是计算投影纹理坐标需要将投影顶点坐标归一化到【0 ,1 】空间中,实现这一步,可以在需要左乘矩阵normalMatrix , 也可以在着色程序中对顶点投影坐标的每个分量先乘以1/2 然后再加上1/2
总结出投影坐标的矩阵公式为:
textViewProjMatrix = NormalMatrix x ProjectionMatrix x ViewMatrix x WorldMatrix
而Unity的Shader中已经为我们算好了这个矩阵,叫做unity_Projector
我们只需要在vext函数中把顶点左乘这个矩阵就得到了齐次投影纹理坐标
o.proj = mul(_Projector, v.vertex);
使用的时候还需要除以最后一个分量w
o.proj.xy = o.proj.xy / o.proj.xy.w;
当然也可以使用CG里的函数tex2DProj进行纹理采样也是一样的
tex2DProj 函数与 tex2D 函数的区别就在于:前者会对齐次纹理坐标除以最后一个分量 q ,然后再进行纹理检索
总结现在我们知道了投影纹理是如何计算出来的,矩阵的变化过程是怎样的。但是这个Shader是运行在谁身上呢?是在地形上,还是在球上?这个问题我现在也不知道..但是后面我会继续去研究把这个搞懂,然后写一个动态阴影出来