我一直在为VR项目开发Unity着色器设置,其中包括两种视觉效果。
- 模糊的轮廓发光效果。这个效果很好。
- “内发光”类型的效果。这在VR / 立体声中不起作用,但在单眼渲染中效果很好。
看起来,这个过程中的红色部分没有按预期工作。当我在片段的计算屏幕位置处对Prepass
RenderTexture进行采样时,它与呈现的模型不匹配。因此,“内发光”被偏移。应该在着色区域内的样本落在外面,反之亦然。
代码
"红色"顶点着色器:
v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
// Get screen position of vertex so we can sample _GlowPrePassTex in screenspace
o.screenpos = ComputeScreenPos(o.vertex);
return o;
}
“红色”片段着色器:
fixed4 frag (v2f i) : SV_Target
{
// Get rim component
half tDot = saturate(dot(i.normal, i.viewdir));
// Sample from _GlowPrePassTex at the fragment's screenspace position
float2 screenUV = i.screenpos.xy / i.screenpos.w;
#if UNITY_SINGLE_PASS_STEREO
float4 scaleOffset = unity_StereoScaleOffset[unity_StereoEyeIndex];
screenUV = (screenUV - scaleOffset.zw) / scaleOffset.xy; // I don't know?
#endif
fixed4 hlSample = tex2D(_GlowPrePassTex, screenUV);
// Standard hard rim
fixed4 col = _RimColor * pow(1.0 - tDot, _RimExponent);
// Modulate hlSample by (softer) rim strength and add to result
col += hlSample * pow(1.0 - tDot, _HLExponent);
return col;
}
我尝试过的方法:
我查看了这个Unity手册页面上的示例,并尝试了相关示例(其中一个包含在上面的片段着色器中),但没有成功。我不确定每个示例应该实现什么功能以及使用它们的顺序。另一个问题是:如果我们切换到单通道立体影像呈现,许多其他效果将停止工作,需要进行调整。
我也编写了一个版本,在“红色”片段着色器内重新计算Prepass结果,这种方法有效。但是,在那点上,我们本质上会执行相同(昂贵)的计算两次。如果可能的话,我想避免使用此解决方案。
问题:
- 我是否试图在VR /立体声中做一些根本无法实现的事情?
- 如果不是,如何获得给定片段的正确屏幕空间UV坐标,以从VR中的纹理中采样?
非常感谢您的帮助!