Unity Shader 屏幕空间 UVScreen Space UV 完全指南
用裁剪空间坐标除以 w 后重映射到 [0,1]将屏幕纹理投影到任意几何体上—— 无需 UV 展开轻松实现扫描线、水波纹与受击扭曲。1原理从裁剪空间到屏幕坐标在 GPU 管线中顶点着色器最终输出的是裁剪空间坐标clipPos (x, y, z, w)。 GPU 在光栅化前会自动执行透视除法将 xyz 各分量除以 w 得到范围在[-1, 1]的 NDC标准化设备坐标。 屏幕空间 UV 就是在这一步之后把 NDC 的 xy 重映射到[0, 1]的结果。核心公式只有两行// 顶点着色器中o.screenPos ComputeScreenPos(clipPos); // 片元着色器中float2 screenUV i.screenPos.xy / i.screenPos.w;ComputeScreenPos是 URP 提供的工具函数 它在顶点阶段把 clipPos 转换为透视正确的屏幕坐标尚未做透视除法 片元阶段再用screenPos.xy / screenPos.w完成透视除法 得到真正的[0,1]UV。为什么要分两步在顶点阶段就除以 w 会破坏插值的透视正确性。 把screenPos.w即原始 clipPos.w随 varying 传到片元阶段 由 GPU 做透视校正插值后再在片元中相除结果才是正确的。2URP 中获取屏幕空间 UVURP 提供了一张_CameraOpaqueTexture需在 URP Asset 中开启Opaque Texture以及深度纹理_CameraDepthTexture。 下面是完整的 URP Shader 模板展示如何在不透明物体上读取屏幕颜色。Shader Custom/URP_ScreenSpaceUV_Base{ Properties { [HideInInspector] _MainTex (Texture, 2D) white {} } SubShader { Tags { RenderTypeTransparent QueueTransparent RenderPipelineUniversalPipeline } Pass { HLSLPROGRAM #pragma vertex vert #pragma fragment frag #include Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl // URP 提供的屏幕颜色纹理需在 URP Asset 中开启 Opaque Texture TEXTURE2D(_CameraOpaqueTexture); SAMPLER(sampler_CameraOpaqueTexture); struct Attributes { float4 positionOS : POSITION; }; struct Varyings { float4 positionCS : SV_POSITION; float4 screenPos : TEXCOORD0; }; Varyings vert(Attributes IN) { Varyings OUT; OUT.positionCS TransformObjectToHClip(IN.positionOS.xyz); // 关键在顶点阶段存储带 w 的屏幕坐标 OUT.screenPos ComputeScreenPos(OUT.positionCS); return OUT; } half4 frag(Varyings IN) : SV_Target { // 透视除法得到真正的 [0,1] 屏幕 UV float2 screenUV IN.screenPos.xy / IN.screenPos.w; // 直接读取屏幕颜色 half4 sceneColor SAMPLE_TEXTURE2D(_CameraOpaqueTexture, sampler_CameraOpaqueTexture, screenUV); return sceneColor; } ENDHLSL } }}URP Asset 配置检查Project Settings → Graphics → URP Asset确保Opaque Texture已勾选否则_CameraOpaqueTexture采样结果为黑色。Shader Graph 等价节点如果你使用 Shader Graph只需在片元中添加Screen Position节点模式选Default 其输出的 xyzw 等价于 HLSL 中ComputeScreenPos(clipPos)的结果。 再接一个Scene Color节点即可采样 Opaque 纹理。3实战一 — 扫描线Scan Line扫描线效果让物体表面叠加一条沿 Y 轴滚动的亮带常用于科幻 HUD、 能量盾、传送特效。核心思路对屏幕 UV 的 y 分量做正弦或取模运算 生成周期性条纹再乘以遮罩颜色叠加到 BaseColor 上。参数说明_ScanDensity控制条纹数量越大越密_ScanSpeed控制亮带滚动速度_ScanBandWidth控制亮带宽度0.02~0.15 为宜。无需 UV 展开的优势由于screenUV完全由屏幕坐标决定 哪怕是一个没有任何展开 UV 的胶囊体或程序化网格扫描线也能正确覆盖整个表面 且条纹始终平行于屏幕水平线不会随物体旋转而倾斜。4实战二 — 全屏水波纹Screen Ripple全屏水波纹常用于水面、镜面折射或技能特效。做法是用正弦波对screenUV做偏移采样 把原始 UV 加上一个随时间变化的正弦偏移量再去采样_CameraOpaqueTexture 就得到扭曲的背景投影。双轴叠加将 x 和 y 方向分别用不同频率和相位的正弦波偏移 可以得到更自然的随机水波效果而非规整条纹。与透明渲染队列配合水波纹 Shader 需要读取 Opaque 纹理因此 Render Queue 必须设为Transparent (3000)或更靠后 确保场景中不透明物体已经渲染完成并写入了_CameraOpaqueTexture。5实战三 — 角色受击屏幕扭曲Hit Distortion受击扭曲是一种全屏后处理风格效果当角色受到攻击时 屏幕画面短暂发生径向扭曲以角色为中心向外扩散波纹。 做法是在一个铺满屏幕的 Quad 上根据距冲击中心的距离 对screenUV施加径向偏移。6常见问题与注意事项问题现象原因解决方案采样结果全黑URP Asset 未开启 Opaque TextureProject Settings → URP Asset → 勾选Opaque TextureY 轴上下颠倒不同平台 UV 原点不同DX vs GL使用_ProjectionParams.x若 0 则翻转 y 轴扭曲效果在边缘拉伸径向偏移未做边缘衰减乘以1 - saturate(dist / _Radius)衰减因子在移动端帧率下降全屏采样带宽开销高降低效果分辨率或限制触发频率节流 throttleVR 双眼错位屏幕空间 UV 在单目渲染下各自独立使用unity_StereoEyeIndex区分左右眼做偏移修正
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2548054.html
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!