URP 后处理:涟漪效果实现及Shader优化
现在有这么一个URP的Pass类,它已经被添加到了每帧的渲染队列中:
public class RipplePass : ScriptableRenderPass
{
private Material rippleMaterial;
public RipplePass(Material material)
{
rippleMaterial = material;
}
public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData)
{
Debug.LogError('执行渲染后处理');
CommandBuffer cmd = CommandBufferPool.Get('Ripple Pass');
// 将输入纹理和输出纹理传递给材质
cmd.Blit(renderingData.cameraData.renderer.cameraColorTarget,
renderingData.cameraData.renderer.cameraColorTarget, rippleMaterial);
context.ExecuteCommandBuffer(cmd);
CommandBufferPool.Release(cmd);
}
}
它所持有的材质rippleMaterial是没问题的。该材质对应的shader为:
Shader "Custom/RippleEffect"
{
Properties
{
_MainTex("Base", 2D) = "white" {}
_GradTex("Gradient", 2D) = "white" {}
_Reflection("Reflection Color", Color) = (0, 0, 0, 0)
_Params1("Parameters 1", Vector) = (1, 1, 0.8, 0)
_Params2("Parameters 2", Vector) = (1, 1, 1, 0)
_Drop1("Drop 1", Vector) = (0.49, 0.5, 0, 0)
_Drop2("Drop 2", Vector) = (0.50, 0.5, 0, 0)
_Drop3("Drop 3", Vector) = (0.51, 0.5, 0, 0)
_SeaLevel("SeaVevel", Float) = -1.0
}
CGINCLUDE
#include "UnityCG.cginc"
sampler2D _MainTex;//输入源图像(后处理中相机绘制的原始画面)
float2 _MainTex_TexelSize;
sampler2D _GradTex;//涟漪振幅
half4 _Reflection;
float4 _Params1; // [ aspect, 1, scale, 0 ]
float4 _Params2; // [ 1, 1/aspect, refraction, reflection ]
float3 _Drop1;//涟漪1
float3 _Drop2;//涟漪2
float3 _Drop3;//涟漪3
float _SeaLevel;
float wave(float2 position, float2 origin, float time) //当前点位置, 出发点位置, 时间
{
float d = length(position - origin);
float t = time - d * _Params1.z;
if (_SeaLevel > 0 && position.y > _SeaLevel)// 超过海平面则不再扩散
{
return 0;
}
return (tex2D(_GradTex, float2(t, 0)).a - 0.5f) * 2;
}
float allwave(float2 position)// 计算当前点在三个涟漪下的共同作用效果(因为涟漪之间可能相交)
{
return
wave(position, _Drop1.xy, _Drop1.z) +
wave(position, _Drop2.xy, _Drop2.z) +
wave(position, _Drop3.xy, _Drop3.z);
}
//伪代码 [RippleEffect.shader]
half4 frag(v2f_img i) : SV_Target
{
const float2 dx = float2(0.01f, 0);//delta x
const float2 dy = float2(0, 0.01f);// delta y
float2 p = i.uv * _Params1.xy;//根据比例变换uv
float w = allwave(p);//振幅,用振幅来对当前点做UV上面的偏移,即可产生涟漪效果
float2 dw = float2(allwave(p + dx) - w, allwave(p + dy) - w);//xy上振幅
float2 duv = dw * _Params2.xy * 0.2f * _Params2.z; //ux上振幅
half4 c = tex2D(_MainTex, i.uv + duv);//在原图上做偏移
float fr = pow(length(dw) * 3 * _Params2.w, 3);
return lerp(c, _Reflection, fr);//lerp来实现反射效果,优化表现
}
ENDCG
SubShader
{
Pass
{
ZTest Always Cull Off ZWrite Off
Fog { Mode off }
CGPROGRAM
#pragma fragmentoption ARB_precision_hint_fastest
#pragma target 3.0
#pragma vertex vert_img
#pragma fragment frag
ENDCG
}
}
}
但是 这个Pass并没有成功把图像后处理成我想要的效果,是什么原因呢?需要重写shader为urp格式下的shader吗?如果是,请返回修改后的shader,unity2020.3.33可用的内容:
根据您提供的信息,我注意到您的Shader是一个传统的着色器,而您正在使用的是Universal Render Pipeline (URP)。URP使用自己的渲染管线和着色器语言,因此需要对原始着色器进行修改以使其与URP兼容。
要将着色器转换为URP格式,您需要进行以下更改:
-
删除包含UnityCG.cginc的CGINCLUDE部分。在URP中,不再需要该文件并且不应使用。
-
在SubShader块之前添加URP的引用:URP之前的引用可以是:
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
- 在SubShader块中,将Pass的渲染目标更改为URP的渲染目标。这可以通过将Pass块中的片段函数的输入和输出更改为URP的约定来完成。
下面是修改后的Shader代码:
Shader "Custom/RippleEffectURP"
{
Properties
{
_MainTex("Base", 2D) = "white" {}
_GradTex("Gradient", 2D) = "white" {}
_Reflection("Reflection Color", Color) = (0, 0, 0, 0)
_Params1("Parameters 1", Vector) = (1, 1, 0.8, 0)
_Params2("Parameters 2", Vector) = (1, 1, 1, 0)
_Drop1("Drop 1", Vector) = (0.49, 0.5, 0, 0)
_Drop2("Drop 2", Vector) = (0.50, 0.5, 0, 0)
_Drop3("Drop 3", Vector) = (0.51, 0.5, 0, 0)
_SeaLevel("SeaLevel", Float) = -1.0
}
SubShader
{
Tags { "RenderType"="Opaque" }
LOD 100
Pass
{
HLSLPROGRAM
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
#pragma vertex vert
#pragma fragment frag
#pragma target 3.0
#pragma multi_compile_instancing
#pragma shader_feature _ _ALPHATEST_ON _ALPHABLEND_ON _ALPHAPREMULTIPLY_ON
#pragma shader_feature _SURFACE_TYPE_TRANSPARENT
#pragma shader_feature _ENABLE_FOG_ON
struct appdata_t
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};
struct v2f
{
float2 uv : TEXCOORD0;
UNITY_FOG_COORDS(1)
float4 vertex : SV_POSITION;
};
sampler2D _MainTex;
sampler2D _GradTex;
float4 _Reflection;
float4 _Params1;
float4 _Params2;
float3 _Drop1;
float3 _Drop2;
float3 _Drop3;
float _SeaLevel;
float wave(float2 position, float2 origin, float time)
{
float d = length(position - origin);
float t = time - d * _Params1.z;
if (_SeaLevel > 0 && position.y > _SeaLevel)
{
return 0;
}
return (tex2D(_GradTex, float2(t, 0)).a - 0.5f) * 2;
}
float allwave(float2 position)
{
return
wave(position, _Drop1.xy, _Drop1.z) +
wave(position, _Drop2.xy, _Drop2.z) +
wave(position, _Drop3.xy, _Drop3.z);
}
v2f vert(appdata_t v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = v.uv * _Params1.xy;
UNITY_TRANSFER_FOG(o, o.vertex);
return o;
}
fixed4 frag(v2f i) : SV_Target
{
const float2 dx = float2(0.01f, 0);
const float2 dy = float2(0, 0.01f);
float2 p = i.uv * _Params1.xy;
float w = allwave(p);
float2 dw = float2(allwave(p + dx) - w, allwave(p + dy) - w);
float2 duv = dw * _Params2.xy * 0.2f * _Params2.z;
fixed4 c = tex2D(_MainTex, i.uv + duv);
float fr = pow(length(dw) * 3 * _Params2.w, 3);
return lerp(c, _Reflection, fr);
}
ENDHLSL
}
}
}
请注意,这只是一个基本的转换示例。根据您的需求,您可能需要进行其他更改和调整以获得所需的效果。同时,也请确保将此修改后的Shader与URP的版本兼容。
原文地址: https://www.cveoy.top/t/topic/olvu 著作权归作者所有。请勿转载和采集!