内容偏多,下图是目录

URP管线下怎么获取屏幕信息。
实现特效中使用的热扭曲效果。
认识摄像机输出的不同阶段效果图。
URP管线环境下,GrabPass是失效的。
在URP管线使用的OpaqueTexture 获取不透明物体的绘制。

在shader Graph 里对应的节点是 SceneColor

注意: OpaqueTexture只能渲染不透明物体。
透明物体是抓取不到的。

设置贴图
SAMPLER(_CameraOpaqueTexture); //注意名字 计算出模型显示UV坐标

全代码
Shader "URP/14_OpaqueTexture_01"
{
Properties
{
}
HLSLINCLUDE
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
CBUFFER_START(UnityPerMaterial)
CBUFFER_END
struct appdata
{
float4 positionOS : POSITION;
float2 texcoord : TEXCOORD0;
};
struct v2f
{
float2 uv : TEXCOORD0;
float4 positionOS : SV_POSITION;
};
SAMPLER(_CameraOpaqueTexture); //定义贴图
ENDHLSL
SubShader
{
Tags { "RenderPipeline"="UniversalPipeline" "RenderType"="Transparent" "Queue" = "Transparent" "IgnoreProjector" = " True"}
LOD 100
Pass
{
Tags{ "LightMode"="UniversalForward" }
Blend SrcAlpha OneMinusSrcAlpha
HLSLPROGRAM
#pragma vertex vert
#pragma fragment frag
v2f vert (appdata v)
{
v2f o;
o.positionOS = TransformObjectToHClip(v.positionOS.xyz);
return o;
}
half4 frag (v2f i) : SV_Target
{
half2 screenUV = (i.positionOS.xy / _ScreenParams.xy);
half4 col = tex2D(_CameraOpaqueTexture, screenUV);
return col;
}
ENDHLSL
}
}
}
效果


制作原理,就是我们获取到屏幕颜色以后,对屏幕颜色UV进行偏移达到扭曲的效果。
原来我们是扭曲纹理,就是对纹理坐标UV扭曲。
现在我们获取一张Niose纹理对屏幕UV扭曲。
输入需要的变量

niose纹理,遮罩纹理,niose纹理移动速度,扭曲力度
计算UV信息,输出

片元着色器阶段
前计算出不同的UV移动方向,
生成俩个扭曲的纹理,计算出不同的UV扭曲程度,
加到屏幕UV里。

计算遮罩,
我们输出设置成遮罩,这样我们就可控扭曲范围大小。

效果


准备好特效刀光贴图

在结构体输入,输出,如果不清楚可以参考上面的文档。
struct appdata
{
float4 positionOS : POSITION;
float2 texcoord : TEXCOORD0;
float4 vertexColor : COLOR;
};
struct v2f
{
float2 uv : TEXCOORD0;
float4 positionOS : SV_POSITION;
float4 vertexColor : COLOR;
}; 顶点着色器阶段输出

计算出俩个方向,使用顶点Alpha控制扭曲强度。
half4 frag (v2f i) : SV_Target
{
half4 mainTex = SAMPLE_TEXTURE2D(_MainTex,sampler_MainTex,i.uv);
half2 screenUV = (i.positionOS.xy / _ScreenParams.xy) + half2(mainTex.rg * _Force * i.vertexColor.a);
half4 col = tex2D(_CameraOpaqueTexture, screenUV);
return col;
} 效果

能看到扭曲越来越弱。

准备贴图

修改变量
Properties
{
_NormalTex("_NormalTex",2D) = "bump" {}
_NormalScale("_NormalScale",range(0,0.05)) = 0.01
} 注意:法线贴图使用**"bump" {} 法线标签**
在片元着色器阶段我们处理法线的方法。
half4 frag (v2f i) : SV_Target
{
half3 NormalTex = UnpackNormalScale(SAMPLE_TEXTURE2D(_NormalTex,sampler_NormalTex,i.uv),_NormalScale);
half2 screenUV = (i.positionOS.xy / _ScreenParams.xy) + half2(NormalTex.rg * i.vertexColor.a);
half4 col = tex2D(_CameraOpaqueTexture, screenUV);
return col;
} 这里和普通贴图不一样,使用一个内置函数,UnpackNormalScale 这函数是控制法线强度。
效果

代码
Shader "URP/14_OpaqueTexture_Normal"
{
Properties
{
_NormalTex("_NormalTex",2D) = "bump" {}
_NormalScale("_NormalScale",range(0,0.05)) = 0.01
}
HLSLINCLUDE
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
CBUFFER_START(UnityPerMaterial)
float4 _NormalTex_ST;
float _NormalScale;
CBUFFER_END
struct appdata
{
float4 positionOS : POSITION;
float2 texcoord : TEXCOORD0;
float4 vertexColor : COLOR;
};
struct v2f
{
float2 uv : TEXCOORD0;
float4 positionOS : SV_POSITION;
float4 vertexColor : COLOR;
};
TEXTURE2D (_NormalTex);
SAMPLER(sampler_NormalTex);
SAMPLER(_CameraOpaqueTexture); //定义贴图
ENDHLSL
SubShader
{
Tags { "RenderPipeline"="UniversalPipeline" "RenderType"="Transparent" "Queue" = "Transparent" "IgnoreProjector" = " True"}
LOD 100
Pass
{
Tags{ "LightMode"="UniversalForward" }
Blend SrcAlpha OneMinusSrcAlpha
HLSLPROGRAM
#pragma vertex vert
#pragma fragment frag
v2f vert (appdata v)
{
v2f o;
o.positionOS = TransformObjectToHClip(v.positionOS.xyz);
o.uv = TRANSFORM_TEX(v.texcoord, _NormalTex);
o.vertexColor = v.vertexColor;
return o;
}
half4 frag (v2f i) : SV_Target
{
half3 NormalTex = UnpackNormalScale(SAMPLE_TEXTURE2D(_NormalTex,sampler_NormalTex,i.uv),_NormalScale);
half2 screenUV = (i.positionOS.xy / _ScreenParams.xy) + half2(NormalTex.rg * i.vertexColor.a);
half4 col = tex2D(_CameraOpaqueTexture, screenUV);
return col;
}
ENDHLSL
}
}
}

上面方法是不支持半透明物体。但是我们特效中都是半透明物体。
怎么让支持半透明物体扭曲。
实际上URP管线中给我提供了很多COPY的图,我们这里使用**_AfterPostProcessTexture**这张贴图

这张图是后处理完保存的一张图。
然后利用RendererFeatures新建一个渲染时机 ,并新建一种LightMode Tags类型.
这样所有Tags是Grab的shader都会在后期处理完成之后在渲染。
简单理解:我们创建一个状态,让这个状态是在摄像机渲染完以后在渲染。
找到URP管线设置——设置后处理资源



设置一个渲染状态

获取屏幕渲染出的一张图。

设置叠加模式和渲染所有层,设置标签

我们前面设置渲染状态了,我们现在还需要创建一个摄像机。
这个摄像机是获取主相机渲染的画面。

设置管线,关闭所有渲染图层。

扩展Overlay Camera 是将其视图呈现在另一个摄影机的输出之上的摄影机.
主相机里绑定 这个子相机

在FrameDebug里我们可以看到俩个摄像机,第二个摄像机就是看到前面渲染效果。

定义渲染后处理图

注意:这里是和上面不一样的图。
标签里修改渲染方式。

片元着色器阶段,替换后处理素材。
half4 frag (v2f i) : SV_Target
{
half3 normal = UnpackNormalScale(SAMPLE_TEXTURE2D(_NormalTex,sampler_NormalTex,i.uv),_NormalScale);
normal.z = lerp(1,normal.z,_NormalScale);
half2 screenUV = (i.positionOS.xy / _ScreenParams.xy) + half2(normal.rg * i.vertexColor.a);
half4 col = tex2D(_AfterPostProcessTexture, screenUV);
return col;
} 效果
现在半透明物体也可以支持扭曲效果。

代码
Shader "URP/14_OpaqueTexture_01"
{
Properties
{
_NormalTex("_NormalTex",2D) = "bump" {}
_NormalScale("_NormalScale",range(0,0.05)) = 0.01
}
HLSLINCLUDE
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
CBUFFER_START(UnityPerMaterial)
float4 _NormalTex_ST;
float _NormalScale;
CBUFFER_END
struct appdata
{
float4 positionOS : POSITION;
float2 texcoord : TEXCOORD0;
float4 vertexColor : COLOR;
};
struct v2f
{
float2 uv : TEXCOORD0;
float4 positionOS : SV_POSITION;
float4 vertexColor : COLOR;
};
TEXTURE2D (_NormalTex);
SAMPLER(sampler_NormalTex);
SAMPLER(_AfterPostProcessTexture); //定义贴图
ENDHLSL
SubShader
{
Tags { "RenderPipeline"="UniversalPipeline" "RenderType"="Transparent" "Queue" = "Transparent" "IgnoreProjector" = " True"}
LOD 100
Pass
{
Tags{ "LightMode"= "Grab" }
Blend SrcAlpha OneMinusSrcAlpha
HLSLPROGRAM
#pragma vertex vert
#pragma fragment frag
v2f vert (appdata v)
{
v2f o;
o.positionOS = TransformObjectToHClip(v.positionOS.xyz);
o.uv = TRANSFORM_TEX(v.texcoord, _NormalTex);
o.vertexColor = v.vertexColor;
return o;
}
half4 frag (v2f i) : SV_Target
{
half3 normal = UnpackNormalScale(SAMPLE_TEXTURE2D(_NormalTex,sampler_NormalTex,i.uv),_NormalScale);
half2 screenUV = (i.positionOS.xy / _ScreenParams.xy) + half2(normal.rg * i.vertexColor.a);
half4 col = tex2D(_AfterPostProcessTexture, screenUV);
return col;
}
ENDHLSL
}
}
}
参考资料
1.人人有功练 Unity URP管线透明折射扭曲材质的一系列实践(一)两种渲染时机的扭曲材质 - 知乎 (zhihu.com)
2. URP 系列教程 | 多相机玩法攻略 - 知乎 (zhihu.com)
在Debug状态下查看这俩个


_CameraColorTexture 是场景渲染后生成的纹理截图,
_CameraOpaqueTexture 是在不透明物体渲染后截图,所以截取不到透明物体。
_AfterPostProcessTexture 是后处理渲染结果输出的图。

第一,我们可以看到最前渲染的是CameraColorTexture

第二是 _CameraOpaqueTexture 不透明物体渲染后截图

最后是后处理渲染出结果在输出的图。


URP管线下怎么抓取渲染图,默认URP管线提供了设置,这里有俩个一个是获取渲染图,一个是渲染深度。

渲染结果输出图的认识,会产生CameraColorTexture ,_CameraOpaqueTexture ,AfterPostProcessTexture ,他们的前后顺序,具体什么情况使用上面图。

变透明实现扭曲,是在管线里,增加一种状态,使用第二个摄像机渲染输出AfterPostProcessTexture 图。在进行扭曲处理。
在编辑窗口是有问题的,需要运行状态查看效果。
