VR中片段着色器的屏幕空间纹理示例



我一直在开发一个Unity着色器设置,该设置为VR项目集成了两种视觉效果。

  • 轮廓模糊的光晕。这很好用
  • "内部发光"类型的效果。这在VR/立体中不起作用,但在单视场渲染中效果很好

此处为图像和示意图。

这一过程的红色部分似乎没有如预期的那样发挥作用。当我在片段的计算屏幕位置对PrepassRenderTexture进行采样时,它在渲染时与模型不一致。因此,"内部辉光"会发生偏移。应在着色区域内的样本落在外部,反之亦然。

代码

"红色"垂直着色器:

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中从纹理中采样

非常感谢!

VR渲染似乎遇到了一个常见问题,即屏幕空间坐标在两只眼睛之间并不总是正确排列。这是因为每只眼睛从稍微不同的角度渲染场景,因此给定片段的屏幕空间坐标对于每只眼睛来说可能稍微不同。

UNITY_SINGLE_PASS_STEREO宏和UNITY_StereoScaleOffset变量是UNITY处理此问题的方法。在单程立体渲染中,两只眼睛同时渲染,因此需要为每只眼睛调整屏幕空间坐标。

你强调的代码行:


float4 scaleOffset = unity_StereoScaleOffset[unity_StereoEyeIndex];
screenUV = (screenUV - scaleOffset.zw) / scaleOffset.xy;    // I don't know?

正是这样做的。它根据当前渲染的眼睛来调整屏幕空间坐标。unity_StereoEyeIndex变量为0或1,具体取决于渲染的是左眼还是右眼。unity_StereoScaleOffset变量是两个float4值的数组,每只眼睛一个,其中包含调整屏幕空间坐标所需的缩放和偏移值。

如果此调整工作不正常,可能是因为unity_StereoScaleOffset值设置不正确。这可能是由于多种原因造成的,例如VR相机配置错误或VR渲染设置有问题。

关于您的问题:

不,你想做的事情应该在VR/立体中实现。这只是正确处理每只眼睛的屏幕空间坐标的问题。

你发布的代码应该为你提供VR中给定片段的正确屏幕空间UV坐标。如果不是,那么很可能还有其他问题。

最新更新