本文主要是介绍庄懂着色器_L17_屏幕UV/屏幕扰动,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
庄懂-BoyanTata的个人空间_哔哩哔哩_Bilibili
屏幕UV案例
代码部分
观察空间ViewSpace
UnityObjectToViewPos(v.vertex).xyz
以你的摄像机为基准的空间,它的X和Y轴就相当于你显示器上的横轴和竖轴,Z轴就是你摄像机的深度
将摄像机的横轴和竖轴将其理解为一个UV坐标,并去采样贴图,那样就可以将纹理采样到屏幕空间上了
但是如果直接用转换到观察空间的X,Y轴作为UV去采样,会发现贴图在模型的表面上会有一个"畸变",可以用X,Y轴去除以Z的深度即可(o.screenUV = posVS.xy/posVS.z),校正校正"畸变",校正过后还会有另一个问题,你的纹理它是相对于你的屏幕它是不变的(纹理tiling大小相对于显示器是不变的),但是你的模型在视窗显示大小,它相对于你的视口,它是跟它的距离成反比的,它离你越远显示越小,它离你越近显示越大,相对它的tiling的纹理映射在模型身上的时候也是它离你越远tiling越小,它离你越近tiling越大,所以不想出现这样的效果,要将其按距离做一个锁定,那就首先要讲距离求出来
核心代码分析
Shader "AP01/L17/ScreenUV"
{Properties{_MainTex ("RGB:颜色 A:透贴", 2d) = "gray"{}_Opacity ("透明度", range(0, 1)) = 0.5_ScreenTex ("屏幕纹理", 2d) = "black" {}}SubShader{Tags{"Queue"="Transparent" // 调整渲染顺序"RenderType"="Transparent" // 对应改为Cutout"ForceNoShadowCasting"="True" // 关闭阴影投射"IgnoreProjector"="True" // 不响应投射器}Pass{Name "FORWARD"Tags { "LightMode"="ForwardBase" }Blend One OneMinusSrcAlpha // 混合方式CGPROGRAM#pragma vertex vert#pragma fragment frag#include "UnityCG.cginc"#pragma multi_compile_fwdbase_fullshadows#pragma target 3.0// 输入参数uniform sampler2D _MainTex;uniform half _Opacity;uniform sampler2D _ScreenTex; uniform float4 _ScreenTex_ST// 输入结构struct VertexInput{float4 vertex : POSITION; // 顶点位置 OSfloat2 uv : TEXCOORD0; // UV信息};// 输出结构struct VertexOutput{float4 pos : SV_POSITION; // 顶点位置 CSfloat2 uv : TEXCOORD0; // UV信息float2 screenUV : TEXCOORD1; // 屏幕UV};// 输入结构>>>顶点Shader>>>输出结构VertexOutput vert (VertexInput v){VertexOutput o = (VertexOutput)0;o.pos = UnityObjectToClipPos(v.vertex); // 顶点位置 OS>CSo.uv = v.uv; // UV信息float3 posVS = UnityObjectToViewPos(v.vertex).xyz; // 顶点位置 OS>VSfloat originDist = UnityObjectToViewPos(float3(0.0, 0.0, 0.0)).z; // 原点位置 OS>VSo.screenUV = posVS.xy / posVS.z; // VS空间畸变校正o.screenUV *= originDist; // 纹理大小按距离锁定o.screenUV = o.screenUV * _ScreenTex_ST.xy - frac(_Time.x * _ScreenTex_ST.zw); // 启用屏幕纹理STreturn o;}// 输出结构>>>像素half4 frag(VertexOutput i) : COLOR{half4 var_MainTex = tex2D(_MainTex, i.uv); // 采样 基本纹理 RGB颜色 A透贴half var_ScreenTex = tex2D(_ScreenTex, i.screenUV).r; // 采样 屏幕纹理// FinalRGB 不透明度half3 finalRGB = var_MainTex.rgb;half opacity = var_MainTex.a * _Opacity * var_ScreenTex;// 返回值return half4(finalRGB * opacity, opacity);}ENDCG}}
}
屏幕扰动案例
代码部分
GrabPass
就相当于在渲染模型之前,当你把背景的东西存成一张图,这张图的名字就是GrabPass后边大括号内的"_BGTex"
我将它扰动前的背景存下来,然后我在用屏幕的坐标UV把那张图给模型贴上去
核心代码分析
Shader "AP01/L17/ScreenWarp"
{Properties{_MainTex ("RGB:颜色 A:透贴", 2d) = "gray"{}_Opacity ("不透明度", range(0, 1)) = 0.5_WarpMidVal ("扰动中间值", range(0, 1)) = 0.5_WarpInt ("扰动强度", range(0, 5)) = 1}SubShader{Tags{"Queue"="Transparent" // 调整渲染顺序"RenderType"="Transparent" // 对应改为Cutout"ForceNoShadowCasting"="True" // 关闭阴影投射"IgnoreProjector"="True" // 不响应投射器}// 获取背景纹理GrabPass { "_BGTex" }// Forward PassPass{Name "FORWARD"Tags { "LightMode"="ForwardBase" }Blend One OneMinusSrcAlpha // 混合方式CGPROGRAM#pragma vertex vert#pragma fragment frag#include "UnityCG.cginc"#pragma multi_compile_fwdbase_fullshadows#pragma target 3.0// 输入参数uniform sampler2D _MainTex;uniform half _Opacity;uniform half _WarpMidVal;uniform half _WarpInt;uniform sampler2D _BGTex; // 拿到背景纹理// 输入结构struct VertexInput{float4 vertex : POSITION; // 顶点位置 总是必要float2 uv : TEXCOORD0; // UV信息 采样贴图用};// 输出结构struct VertexOutput{float4 pos : SV_POSITION; // 顶点位置 总是必要float2 uv : TEXCOORD0; // UV信息 采样贴图用float4 grabPos : TEXCOORD1; // 背景纹理采样坐标};// 输入结构>>>顶点Shader>>>输出结构VertexOutput vert (VertexInput v){VertexOutput o = (VertexOutput)0;o.pos = UnityObjectToClipPos( v.vertex); // 顶点位置 OS>CSo.uv = v.uv; // UV信息o.grabPos = ComputeGrabScreenPos(o.pos); // 背景纹理采样坐标return o;}// 输出结构>>>像素half4 frag(VertexOutput i) : COLOR{// 采样 基本纹理 RGB颜色 A透贴half4 var_MainTex = tex2D(_MainTex, i.uv);// 扰动背景纹理采样UVi.grabPos.xy += (var_MainTex.b - _WarpMidVal) * _WarpInt * _Opacity;// 采样背景half3 var_BGTex = tex2Dproj(_BGTex, i.grabPos).rgb;// FinalRGB 不透明度half3 finalRGB = lerp(1.0, var_MainTex.rgb, _Opacity) * var_BGTex;half opacity = var_MainTex.a;// 返回值return half4(finalRGB * opacity, opacity);}ENDCG}}
}
这篇关于庄懂着色器_L17_屏幕UV/屏幕扰动的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!