ShadowMap渲染阴影方法及问题
来源:互联网 发布:自然语言处理 知乎 编辑:程序博客网 时间:2024/05/21 10:49
ShadowMap基于的原理:SM算法是一个2-pass绘制算法,第一pass从光源视点绘制场景,生成SM纹理,第2pass从视点视图按常规方法绘制场景
从光源的位置观察场景,这时候我们看不到的地方就是该有阴影的地方,于是可以使用比较像素到光源距离的方法来确定某个像素是否在阴影之中。
于是我们需要记录我们看得到的像素的距离值,以便做比较。
首先,创建在光源位置处的观察坐标系,这一步应该在CPU阶段完成,这里为描述方便,写为HLSL代码
这里假设观察方向指向原点
float3 dirZ = -normalize(lightPos);
float3 up = float3(0,0,1);
float3 dirX = cross(up, dirZ);
float3 dirY = cross(dirZ, dirX);
接下来,把场景中所有顶点变换到这个光源-观察空间中(light-view-space)
实际中应使用矩阵进行变换,这里直接做
float4 vPos;
vInPos.xyz-=vLightPos.xyz; //首先是平移变换
vPos.x=dot(vInPos,x_dir); //接下来是分别绕3个轴旋转
vPos.y=dot(vInPos,y_dir);
vPos.z=dot(vInPos,z_dir);
vPos.w=1;
然后进行light-view-space空间里的投影变换,所使用的矩阵要根据光源的特点进行改变,如FOV等
最后将这时得到的结果渲染到一张纹理上,把它称作shadowmap
这张纹理一般使用R16F,或者R32F格式,而一些集成显卡中或者OPENGL不支持这样的格式,还可以使用整数纹理,这时需要对深度值进行压缩。
渲染结束后,在纹理中保存的就是在光源处能看见的像素到光源的距离了,为了节省shader指令,可以使用距离的平方
即在浮点纹理中为 return dot(vLightVec,vLightVec);
在整数纹理中为 float fDepth=dot(vLightVec,vLightVec);
return float4( floor(fDepth) / 256.0f, frac(fDepth), frac(fDepth), frac(fDepth), frac(fDepth));
通过把frac(fDepth)同时写入蓝色和alpha通道,这样可以节省一条指令,否则需要另一个指令来填充这些通道
mov r2.gba r0.g //r0.g包含frac(fDepth)
vertex shader
pixel shader
到这里准备工作就结束了,接下来就是要渲染阴影的时候了
这时回到正常观察位置即camera位置,不再在light-view-space中观察
将场景中每个顶点再变换到light-view-space中,这是为了要找到顶点在light-view-space中的位置,以便与纹理中的距离值做比较
将已经变换的顶点再进行投影,再将投影平面坐标变换到纹理坐标空间,即把范围为[-1,1]的x,y坐标变换到[0,1]的范围中去,以便匹配相应的纹素texel
然后就是光照,既然有阴影必然有光照效果,而且应该是逐像素光照,可以使用任何光照模型,phong,blinn或者Oren-Nayar
最后的距离比较决定是否为阴影,光照计算,都在像素shader中进行
由于SM算法基于图像空间,所以有一些缺陷,如果视点与光源位置差异很大,会产生明显走样,阴影边缘处会出现明显的阶梯状,这可以使用靠近百分比过滤PCF来改善,因为SM纹理中每个纹素texel可能不是投影到单一屏幕像素上,纹理分辨率越低,走样越严重。
这里的算法也不适用于点光源,仅仅在聚光灯时有效,要用于点光源,则需要3D纹理,进行6次渲染,过几天把这个做一下。
- ShadowMap渲染阴影方法及问题
- ShadowMap渲染阴影方法及问题
- GLSL实现ShadowMap及阴影软化
- shadowmap、深度、projector阴影技术
- ShadowMap自阴影在PS.1.x下的实现方法
- UE4旅途之渲染后模型变黑(2UV坑)及阴影不清问题
- ShadowMap实现软阴影,使用整数纹理
- 控制3Delight Deep Shadowmap阴影生成
- 使用shadowmap实现软阴影效果
- UnityEffects(1)之shadowMap(阴影映射)
- 简单理解ShadowMap阴影的实现
- ShadowMap
- ShadowMap
- Shadowmap
- SHADOWMAP
- ShadowMap
- SHADOWMAP
- 3D地形多层纹理混合加阴影渲染方法
- 人月神话—焦油坑
- 设计模式 个人学习总结
- 收集统计信息
- 胡乱代码
- 基于MINA框架快速开发网络应用程序
- ShadowMap渲染阴影方法及问题
- 终于食言了
- 新型的存储系统 Cassandra
- xmpp和jabber的区别
- 为eclipse配置spket插件
- 用photoshop怎么把字清除
- C#(ASP.NET) 下载数据 C#实现通过程序自动抓取远程Web网页信息
- PostgreSQL UUID 函数
- useradd使用问题