admin 管理员组文章数量: 887007
全局光照RSM
Reflective Shadow Maps(RSM)
一切被直接光照照到的物体,会作为次级光源。
问题1:哪些面片被直接照亮
使用ShadowMap就可以知道哪些面片被直接照亮
问题2:各个面片对P点的贡献分别是多少。
对渲染方程代入如上计算,得到如下结果
在上式中, L i ( q → p ) L_i(q\rightarrow p) Li(q→p)可优化为如下函数
因为:
f r = ρ / π , ρ 为反射率 L i = f r ⋅ ϕ d A , ϕ 是直接光照的光强 f_r = \rho / \pi,\rho 为反射率\\ \quad\\ L_i = f_r \cdot \frac{\phi}{dA},\phi 是直接光照的光强 fr=ρ/π,ρ为反射率Li=fr⋅dAϕ,ϕ是直接光照的光强
因此有次级光源光强
E p ( x , n ) = ϕ p m a x { 0 , d o t ( n p , ( x − x p ) } m a x { 0 , d o t ( n , x p − x ) } ∣ ∣ x − x p ∣ ∣ 4 E_p(x,n)=\phi_p \frac{max\{0,dot(n_p,(x-x_p)\}max\{0,dot(n,x_p-x)\}}{||x-x_p||^4} Ep(x,n)=ϕp∣∣x−xp∣∣4max{0,dot(np,(x−xp)}max{0,dot(n,xp−x)}
L 0 = E p ( x , n ) ∗ f r ( p , p → q , w o ) L_0 = E_p(x,n) * f_r(p,p\rightarrow q,w_o) L0=Ep(x,n)∗fr(p,p→q,wo)
其他近似
- 不考虑Visbility项,认为次级光源不会被遮挡。
- 不对所有次级光源采样,只对该点在ShadowMap中周围的部分像素采样。
ShadowMap记录值
- 深度
- 世界坐标
- 法线
- 次级光源强度 ϕ \phi ϕ
特点与效果
对于特定情况效果比较好,如手电筒(用RSM做手电筒!!!?)
好处:非常好写,第一个Path生成RSM,第二个path用眼睛看向场景。
问题:
- 直接光源较多时,间接光源也会成倍增多
- 不会计算反射光的可见性检查
- 次级光源效果和运行速度,会根据采样率的不同的不同
如何实现
第一步,先找到哪些物体表面能够被直接照亮,使用ShadowMap,认为每一个ShadowMap的像素就是一个次级光源。
第二步,次级光源如何贡献到点P:我们认为所有的反射物(次级光源),都是Diffuse的。
RSM与VPL(Virtual Point Light 虚拟点光源)
RSM与离线渲染中的VPL方式是比较相似的,RSM是硬件加速版本的VPL(Virtual Point Light 虚拟点光源)。
RSM实现步骤
第一个Pass
在摄像机视角渲染整个场景,并记录场景中可见的像素点的颜色、视口矩阵下的法线、视口矩阵下的坐标。
得到一组场景信息,可以理解为GBuffer。
第2个Pass
从光源视口下看向场景,生成RSM图。
记录的从光源视口下可见像素点的反射光颜色值、相机视角下的法线、相机视角下的坐标、光源视角下的坐标。
得到的结果是一组256x256的RSM图
············反射光颜色值 ······························· 相机视角下的法线 ··················
··········· 相机视角下的坐标 ·························· 光源视角下的坐标(主要保存z轴深度)·······························
第3个Pass
1.将Pass1中保存的像素坐标转化到与RSM相同的光源坐标
ivec2 FragPos = ivec2(gl_GlobalInvocationID.xy);//当前执行单元在全局工作组中的位置的有效索引vec3 FragViewNormal = normalize(texelFetch(u_NormalTexture, FragPos, 0).xyz);vec3 FragAlbedo = texelFetch(u_AlbedoTexture, FragPos, 0).xyz;vec3 FragViewPos = texelFetch(u_PositionTexture, FragPos, 0).xyz;// 获取 摄像机视口下像素 在光源视口下的位置坐标vec4 FragPosInLightSpace = u_LightVPMatrixMulInverseCameraViewMatrix * vec4(FragViewPos, 1);FragPosInLightSpace /= FragPosInLightSpace.w;vec2 FragNDCPos4Light = (FragPosInLightSpace.xy + 1) / 2;
2. 计算该像素点的直接光照
如果该像素点在光照空间外,则只提供一个基本的环境光照。
当该像素在光照空间内,首先判断该点是否在阴影中
- 如果在阴影中,则只计算环境光照
- 如果不在阴影中,则计算直接光照
// 直接光照&环境光照vec3 testOutput;vec3 DirectIllumination;// 如果该像素在RSM范围之外,以0.1倍源像素作为其环境光照// FragPosInLightSpace.z范围在【-1,0】的区间中.属于可被光照直接照射的范围// 这里可通过与RSM中的深度进行比较,来确定是否有阴影生成,或是否可被作为次级光源if( FragPosInLightSpace.z < -1.0f || FragPosInLightSpace.z > 0.0f||\FragPosInLightSpace.x >= 1.0f || FragPosInLightSpace.x <= -1.0f||\FragPosInLightSpace.y >= 1.0f || FragPosInLightSpace.y <= -1.0f )//{DirectIllumination = vec3(0.1) * FragAlbedo;testOutput = vec3(0.f,0.f,0.f);}else//反之,将原像素经过夹角衰减后的值作为直接光照{ // view space下的光照坐标vec3 RSWLightPosition =texture(u_RSMLightPositionTexture,FragNDCPos4Light.xy).xyz;// 判断是否在阴影中(近小【-1】远大【0】)if(RSWLightPosition.z + 0.001 > FragPosInLightSpace.z){//不在阴影中DirectIllumination = FragAlbedo* max(dot(-u_LightDirInViewSpace, FragViewNormal), 0.1);// ;}else{//在阴影中DirectIllumination = vec3(0.1) * FragAlbedo;}}
3. 计算该像素点的间接光照
将该着色点投影到光照视口下的点,则已知该点在RSM纹理上的xy轴位置。
在RSM图中,在(x,y)像素上以R为半斤的周围进行随机采样,每一个采样点作为次级光源进行光照计算。
// 计算间接光照vec3 IndirectIllumination = vec3(0);float RSMTexelSize = 1.0 / u_RSMSize;for(int i = 0; i < u_VPLNum; ++i){if(FragPosInLightSpace.z > -1.0f && FragPosInLightSpace.z <0.0f){//获取随机采样数组vec3 VPLSampleCoordAndWeight = u_VPLsSampleCoordsAndWeights[i].xyz;// 在光源视口下的该像素点周围一圈进行采样vec2 VPLSamplePos = FragNDCPos4Light + u_MaxSampleRadius * VPLSampleCoordAndWeight.xy * RSMTexelSize;// 在RSM图中获取采样点的次级光源颜色值vec3 VPLFlux = texture(u_RSMFluxTexture, VPLSamplePos).xyz;// 获取采样点在摄像机视口坐标下的的法线和位置坐标vec3 VPLNormalInViewSpace = normalize(texture(u_RSMNormalTexture, VPLSamplePos).xyz);vec3 VPLPositionInViewSpace = texture(u_RSMPositionTexture, VPLSamplePos).xyz;// 计算该采样点对该像素的间接光照值IndirectIllumination += calcVPLIrradiance(VPLFlux, VPLNormalInViewSpace, VPLPositionInViewSpace, FragViewPos, FragViewNormal, VPLSampleCoordAndWeight.z);}}IndirectIllumination *= FragAlbedo;//间接光vec3 Result = IndirectIllumination / u_VPLNum;
4. 将直接光照与间接光照加起来
得到结果,渲染!
vec3 Result = DirectIllumination + IndirectIllumination / u_VPLNum ;
区别【好像没太大区别 dog.jpg】
本文标签: 全局光照RSM
版权声明:本文标题:全局光照RSM 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.freenas.com.cn/jishu/1732356854h1534674.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论