关于ComputeScreenPos和ComputeGrabScreenPos的差别

本文介绍了Unity中ComputeScreenPos和ComputeGrabScreenPos的区别,主要涉及GrabPass、投影矩阵翻转以及不同平台的纹理坐标差异。在修复一个因使用不当导致的渲染Bug过程中,阐述了在Direct3D-like和OpenGL-like平台上,如何根据UNITY_UV_STARTS_AT_TOP来判断并处理纹理坐标翻转,以确保在各种情况下都能正确采样RenderTexture。
摘要由CSDN通过智能技术生成

一个Bug

今天QA报了一个渲染相关的bug:一个用了 扭曲 效果的翅膀特效在场景相机下显示正常,但是在UI相机上却有问题,截图如下:

扭曲背景 上下颠倒 了。


Bug的修正

这里用的 扭曲shader 是我们的美术同学从他们前项目搬过来的,代码很简单:

  • GrabPass 抓取当前屏幕做为扭曲背景。
  • 添加 UV扰动 后再采样屏幕背景,即可达到扭曲效果。

问题是,这里采样 GrabTexture 的时候用的是 screenUV 而非 grabUV,代码如下:

顶点着色器:

	o.screenPos = ComputeScreenPos (o.pos);

像素着色器:

	float2 sceneUVs = (i.screenPos.xy / i.screenPos.w) + (_Value * diffuseTex.a * float2(diffuseTex.r, diffuseTex.g) * i.vertexColor.a);
	half4 sceneColor = tex2D(_GrabTexture, sceneUVs);

修正这个问题很简单,把 ComputeScreenPos 换成 ComputeGrabScreenPos 即可,修正后的代码如下:

顶点着色器:

o.screenPos = ComputeGrabScreenPos (o.pos);

调整完之后就正常了,如下图:


关于ComputeScreenPos和ComputeGrabScreenPos的差别

修正容易,但是搞清楚 Compute

  • 8
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Projective Texture Mapping 是一种常用的 Shader 技术,可以用来在 Unity 中实现纹理投影效果。它的原理是通过将投影纹理映射到场景物体上,并基于物体的表面法线和光照方向来计算出光照效果,从而实现物体表面的投影纹理效果。 以下是一个简单的 Projective Texture Mapping 的 Shader 示例: ```shader Shader "Custom/ProjectiveTextureMapping" { Properties { _MainTex ("Texture", 2D) = "white" {} _ProjTex ("Projection Texture", 2D) = "white" {} _Intensity ("Intensity", Range(0,1)) = 1 } SubShader { Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag #include "UnityCG.cginc" struct appdata { float4 vertex : POSITION; float3 normal : NORMAL; }; struct v2f { float4 projPos : TEXCOORD0; float3 worldNormal : TEXCOORD1; float4 vertex : SV_POSITION; }; sampler2D _MainTex; sampler2D _ProjTex; float _Intensity; v2f vert (appdata v) { v2f o; o.vertex = UnityObjectToClipPos(v.vertex); o.worldNormal = UnityObjectToWorldNormal(v.normal); o.projPos = ComputeGrabScreenPos(o.vertex); return o; } fixed4 frag (v2f i) : SV_Target { // 计算纹理坐标 float2 projCoord = i.projPos.xy / i.projPos.w; projCoord = 0.5 * (projCoord + 1.0); // 计算投影纹理颜色 fixed4 projColor = tex2D(_ProjTex, projCoord); // 计算漫反射光照 float3 worldNormal = normalize(i.worldNormal); float3 worldLightDir = normalize(_WorldSpaceLightPos0.xyz); float intensity = _Intensity * max(0, dot(worldNormal, worldLightDir)); // 计算最终颜色并返回 fixed4 texColor = tex2D(_MainTex, i.uv); fixed4 finalColor = lerp(texColor, projColor, intensity); return finalColor; } ENDCG } } } ``` 这个 Shader 的主要实现思路是,将投影纹理的颜色和物体表面原有的颜色进行插值计算,插值的比例根据光照方向和表面法线来计算。其中,ComputeGrabScreenPos() 函数用于将物体的顶点坐标转换为屏幕坐标,从而计算出纹理坐标。在 Pass 中的 vert 函数中,通过 UnityObjectToWorldNormal() 函数将物体的法线转换为世界坐标系下的法线,从而能够正确计算出光照效果。 使用这个 Shader,将它添加到一个材质中,并将这个材质应用到需要投影纹理的物体上,就可以实现 Projective Texture Mapping 技术了。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值