unity3d中如何使用屏幕空间改善shadowmap漏光
这篇文章主要介绍了unity3d中如何使用屏幕空间改善shadowmap漏光,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。
成都创新互联专注于湖南企业网站建设,成都响应式网站建设公司,商城开发。湖南网站建设公司,为湖南等地区提供建站服务。全流程按需策划设计,专业设计,全程项目跟踪,成都创新互联专业和态度为您提供的服务
前因
自从实时阴影发展到了shadowmap时代,漏光和 Shadow Acne就形影不离。除非你可以无脑极大提升shadowmap精度 或可以做到很短距离的实时阴影 否则并不好解决这常见问题。如下图
动态bias方案
我早年在网易引擎部面试的时候 总监大佬问过我这问题。我当年很得意,告诉他我自创并实现过demo的做法,计算shadowmap 不仅写入深度 也写入 投影表面的世界法线(或投影表面的SV_PrimitiveID 这个更省空间),这样绘制阴影的时候就能根据自己表面的世界法线 是否与投影表面接近来判断 是否自己投影给自己 如果是bias算的大些 否则算的小些。因为既然bias 固定数值都不行,那就实现动态bias,这样逻辑上就成立。大佬冷静的说,shadowmap本身就精度不足 你同尺寸数据也不能提升太多。(实际测试确实提升不太大),他接着小心翼翼地问道:你就不能在屏幕空间想想办法?当年的我除了ssao模仿的实现一次 根本没灵活掌握各种其他SS技巧而且也没经验,于是答不出来。但是看得出他的小心翼翼 仿佛再问一句就会泄露做法一般,我就印象深刻的记下:这个点可能很容易想出来有时间了就去尝试。现在刚好是时候了。
屏幕空间改善漏光方案
我想到屏幕空间上一个像素可以根据深度图去检查,他往光线方向上短距离内是否有遮挡物,如果有那么应该有阴影。于是我选择把bias调大,如上图左图,然后想办法去把漏的光补上。没有选自阴影出错然后 把阴影消去是因为,投影者不一定就在附近所以不能简单的消去阴影。但是 漏光处如果有投影一定是在附近所以更好查询。先看效果很不错。
这么大的提升 代码量居然只要6句 采样的也是已有的深度图性能基本没问题.代码直接带详细说明。简单测试函数就写在了 LightingMyStandard_GI 内,根据实际项目可放屏幕阴影计算shader,任何地方只要能获取世界坐标就可以
void LightingMyStandard_GI( SurfaceOutputStandard s, UnityGIInput data,inout UnityGI gi) { //当前位置 往光线方向移动0.1米 定位虚拟投影物 看看那里是否真有物体 如果有就算遮挡 float4 casterWpos =float4( data.worldPos + data.light.dir * 0.1f,1); //转到裁剪空间 float4 casterNdc = mul(UNITY_MATRIX_VP, casterWpos); //转到ndc空间 casterNdc /= casterNdc.w; //转到采样坐标去看看这里实际屏幕深度多少 float2 samplePos = casterNdc.xy * 0.5 + 0.5; //获得虚拟投影物位置实际深度 float depth = SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture, samplePos); // 如果虚拟投影物 被遮挡 就算真有遮挡物 阴影为黑色 //实际项目 最好转到 Linear01Depth(depth) * _ProjectionParams.z 比较真实距离 和 有效范围内才算遮挡 if (depth > casterNdc.z) data.atten = 0; //以下为函数原内容 #if defined(UNITY_PASS_DEFERRED) && UNITY_ENABLE_REFLECTION_BUFFERS gi = UnityGlobalIllumination(data, s.Occlusion, s.Normal); #else Unity_GlossyEnvironmentData g = UnityGlossyEnvironmentSetup(s.Smoothness, data.worldViewDir, s.Normal, lerp(unity_ColorSpaceDielectricSpec.rgb, s.Albedo, s.Metallic)); gi = UnityGlobalIllumination(data, s.Occlusion, s.Normal, g); #endif }
如果虚拟投影物 被遮挡 就算真有遮挡物 阴影为黑色 ,实际项目 最好转到 Linear01Depth(depth) * _ProjectionParams.z 比较真实距离 和 有效范围内才算遮挡
感谢你能够认真阅读完这篇文章,希望小编分享的“unity3d中如何使用屏幕空间改善shadowmap漏光”这篇文章对大家有帮助,同时也希望大家多多支持创新互联,关注创新互联行业资讯频道,更多相关知识等着你来学习!
本文标题:unity3d中如何使用屏幕空间改善shadowmap漏光
文章链接:http://pwwzsj.com/article/ihjieo.html