|
注:这篇笔记的目的不在于如何制作玻璃特效(毛玻璃作为实践的素材),目的在于升级任何使用了【cmd.Blit】这个api的URP特效,以撑持Single-Pass Instanced VR
本篇包含内容:
unity版本2021.3.8,URP版本v12.1.7:暂未能撑持Single-Pass Instanced VR;
unity版本2022.2.7,URP版本v14.0.6:可撑持Single-Pass Instanced VR;
(URP在不竭升级,技术更迭…这篇笔记里的东西过不了多久可能也会变成过时的东西,但愿能帮到此刻的你 )
0.一个BRP示例(含毛玻璃shader)
先看一个过时的BRP示例,来自: https://blog.unity.com/technology/extending-unity-5-rendering-pipeline-command-buffers
流程概括:
一个用于做Blur计算的shader(”Hidden/SeparableGlassBlur”);(下面的shader语法已改为URP)- Shader ”Hidden/SeparableGlassBlur” {
- Properties {
- _MainTex (”Base (RGB)”, 2D) = ”” {}
- }
- ......//注:我喜欢把代码分块排版,这样看起来斗劲舒服,代码里呈现的【......】意思是这部门内容在长虚线下面
- }
- ------------------------------------------------------------------------------------------
- Subshader {
- Tags { ”RenderPipeline”=”UniversalPipeline” }
- Pass {
- Name ”01”
- Tags { ”LightMode”=”UniversalForward” }
- ZTest Always
- Cull Off
- ZWrite Off
- Fog { Mode off }
-
- HLSLPROGRAM
- #include ”Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl”
- #pragma fragmentoption ARB_precision_hint_fastest
- #pragma vertex vert
- #pragma fragment frag
- ......
- ENDHLSL
- }
- }
- ------------------------------------------------------------------------------------------
- struct appdata_img {
- float4 vertex : POSITION;
- half2 uv : TEXCOORD0;
- UNITY_VERTEX_INPUT_INSTANCE_ID
- };
- struct v2f {
- float4 pos : POSITION;
- float2 uv : TEXCOORD0;
- float4 uv01 : TEXCOORD1;
- float4 uv23 : TEXCOORD2;
- float4 uv45 : TEXCOORD3;
- };
- float4 offsets;
- sampler2D _MainTex;
- v2f vert (appdata_img v) {
- v2f o;
- o.pos = TransformObjectToHClip(v.vertex);
- o.uv.xy = v.uv.xy;
- o.uv01 = v.uv.xyxy + offsets.xyxy * float4(1,1, -1,-1);
- o.uv23 = v.uv.xyxy + offsets.xyxy * float4(1,1, -1,-1) * 2.0;
- o.uv45 = v.uv.xyxy + offsets.xyxy * float4(1,1, -1,-1) * 3.0;
- return o;
- }
- half4 frag (v2f i) : COLOR {
- half4 color = float4 (0,0,0,0);
- color += 0.40 * tex2D (_MainTex, i.uv);
- color += 0.15 * tex2D (_MainTex, i.uv01.xy);
- color += 0.15 * tex2D (_MainTex, i.uv01.zw);
- color += 0.10 * tex2D (_MainTex, i.uv23.xy);
- color += 0.10 * tex2D (_MainTex, i.uv23.zw);
- color += 0.05 * tex2D (_MainTex, i.uv45.xy);
- color += 0.05 * tex2D (_MainTex, i.uv45.zw);
-
- return color;
- }
复制代码 一个用于衬着玻璃的shader(GlassWithoutGrab.shader);(下面的shader语法已改为URP)- Shader ”FX/Glass/Stained BumpDistort (no grab)” {
- Properties {
- _BumpAmt (”Distortion”, range (0,64)) = 10
- _TintAmt (”Tint Amount”, Range(0,1)) = 0.1
- _MainTex (”Tint Color (RGB)”, 2D) = ”white” {}
- _BumpMap (”Normalmap”, 2D) = ”bump” {}
- }
- ......
- }
- ------------------------------------------------------------------------------------------
- SubShader{
- // We must be transparent, so other objects are drawn before this one.
- Tags { ”RenderPipeline”=”UniversalPipeline” ”Queue”=”Transparent” ”RenderType”=”Opaque” }
- Pass {
- Name ”BASE”
- Tags { ”LightMode”=”UniversalForward” }
-
- HLSLPROGRAM
- #pragma vertex vert
- #pragma fragment frag
- #pragma multi_compile_fog
- #include ”Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl”
- ......
- ENDHLSL
- }
- }
- ------------------------------------------------------------------------------------------
- struct appdata_t {
- float4 vertex : POSITION;
- float2 uv: TEXCOORD0;
- };
- struct v2f {
- float4 vertex : POSITION;
- float4 uvgrab : TEXCOORD0;
- float2 uvbump : TEXCOORD1;
- float2 uvmain : TEXCOORD2;
- // UNITY_FOG_COORDS(3)
- float fogFactor : TEXCOORD3;
- };
- float _BumpAmt;
- half _TintAmt;
- float4 _BumpMap_ST;
- float4 _MainTex_ST;
- v2f vert (appdata_t v)
- {
- v2f o;
- o.vertex = TransformObjectToHClip(v.vertex);
- #if UNITY_UV_STARTS_AT_TOP
- float scale = -1.0;
- #else
- float scale = 1.0;
- #endif
- o.uvgrab.xy = (float2(o.vertex.x, o.vertex.y*scale) + o.vertex.w) * 0.5;
- o.uvgrab.zw = o.vertex.zw;
- o.uvbump = TRANSFORM_TEX( v.uv, _BumpMap );
- o.uvmain = TRANSFORM_TEX( v.uv, _MainTex );
- o.fogFactor = ComputeFogFactor(o.vertex.z);
- return o;
- }
- sampler2D _GrabBlurTexture;
- float4 _GrabBlurTexture_TexelSize;
- sampler2D _BumpMap;
- sampler2D _MainTex;
- half4 frag (v2f i) : SV_Target
- {
- // calculate perturbed coordinates
- // we could optimize this by just reading the x & y without reconstructing the Z
- half2 bump = UnpackNormal(tex2D( _BumpMap, i.uvbump )).rg;
- float2 offset = bump * _BumpAmt * _GrabBlurTexture_TexelSize.xy;
- i.uvgrab.xy = offset * i.uvgrab.z + i.uvgrab.xy;
-
- half4 col = tex2Dproj (_GrabBlurTexture, i.uvgrab/i.uvgrab.w);
- half4 tint = tex2D(_MainTex, i.uvmain);
- col = lerp (col, tint, _TintAmt);
- col.rgb = MixFog(col.rgb, i.fogFactor);
- return col;
- }
复制代码 一个担任自Monobehaviour的脚本(CommandBufferBlurRefraction.cs),没有用到RendererFeature;
把 scene color 传输给 RT_screenCopyID;- CommandBufferBlurRefraction.cs脚本:
- OnWillRenderObject():
- // copy screen into temporary RT
- int screenCopyID = Shader.PropertyToID(”_ScreenCopyTexture”);
- cmd.GetTemporaryRT (screenCopyID, -1, -1, 0, FilterMode.Bilinear);
- cmd.Blit (BuiltinRenderTextureType.CurrentActive, screenCopyID);
- // 但我实在不能理解,即使我把上面的cmd.Blit替换为下面这句,毛玻璃效果也正常显示???
- // 但如果注释掉cmd.Blit,毛玻璃效果就会消掉,合着意思是只要有cmd.Blit,不管他source给了啥,都传 scene color 给 destination???
- cmd.Blit (Shader.PropertyToID(”_ttttttt”), screenCopyID);
复制代码 新建2张RT,长宽是全屏的一半,记为 RT_blurredID 和 RT_blurredID2;把 RT_screenCopyID 传输给 RT_blurredID;- // get two smaller RTs
- int blurredID = Shader.PropertyToID(”_Temp1”);
- int blurredID2 = Shader.PropertyToID(”_Temp2”);
- cmd.GetTemporaryRT (blurredID, -2, -2, 0, FilterMode.Bilinear);
- cmd.GetTemporaryRT (blurredID2, -2, -2, 0, FilterMode.Bilinear);
- // downsample screen copy into smaller RT, release screen RT
- cmd.Blit (screenCopyID, blurredID);
复制代码
- 开始倒腾:
- 把 RT_blurredID 经SeparableGlassBlur.shader计算(偏移”2”在x标的目的加权平均)后传输给 RT_blurredID2;
- 把 RT_blurredID2 经SeparableGlassBlur.shader计算(偏移”2”在y标的目的加权平均)后传输给 RT_blurredID;
- 把 RT_blurredID 经SeparableGlassBlur.shader计算(偏移”4”在x标的目的加权平均)后传输给 RT_blurredID2;
- 把 RT_blurredID2 经SeparableGlassBlur.shader计算(偏移”4”在y标的目的加权平均)后传输给 RT_blurredID;
把 RT_blurredID 传输给 ”_GrabBlurTexture”,传给用于衬着玻璃的shader(GlassWithoutGrab.shader)使用;- cmd.SetGlobalTexture(”_GrabBlurTexture”, blurredID);
复制代码 1. 改用RendererFeature实现
把OnWillRenderObject这个函数里的CommandBuffer改用RendererFeature实现
下面,我们试着把它的脚本(CommandBufferBlurRefraction.cs)改为RendererFeature
参考: https://zhuanlan.zhihu.com/p/248903320
大体照搬上面链接里的脚本,就是记得把 RT_blurredID 传给 ”_GrabBlurTexture”
unity版本2021.3.8,URP版本v12.1.7
代码在[f01_v12_1_7]这个文件夹里:FrostedGlassRenderFeature.cs- public class FrostedGlassRenderFeature : ScriptableRendererFeature{
- //在RendererFeature类里写一个class Settings,并实例化它
- [System.Serializable]
- public class Settings{
- public RenderPassEvent renderEvent = RenderPassEvent.AfterRenderingSkybox;
- public Material blurMat;
- }
- public Settings settings = new Settings();
- //----------------------------------------------------------------
- public class FrostedGlassRenderPass : ScriptableRenderPass{......}
- FrostedGlassRenderPass m_ScriptablePass;
- //----------------------------------------------------------------
- //在ScriptableRendererFeature的Create方式里实例化ScriptableRenderPass类
- public override void Create(){
- m_ScriptablePass = new FrostedGlassRenderPass(settings);
- }
- //----------------------------------------------------------------
- //在AddRenderPasses方式里设置ScriptableRenderPass的source
- public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData){
- var src = renderer.cameraColorTarget;
- m_ScriptablePass.Setup(src);
- //----------------------
- renderer.EnqueuePass(m_ScriptablePass);
- }
- }
- ------------------------------------------------------------------------------------------
- ......的部门:
- public class FrostedGlassRenderPass : ScriptableRenderPass{
- CommandBuffer cmd;
- string m_ProfilerTag;//cmd name
- Material m_blurMat;
- RenderTargetHandle blurredID01;
- RenderTargetHandle blurredID02;
- RenderTargetIdentifier source;
- RenderTargetHandle m_tempColorTex;
- //首先写这个ScriptableRenderPass的构造函数
- public FrostedGlassRenderPass(FrostedGlassRenderFeature.Settings param){
- m_ProfilerTag = ”FrostedGalss”;
- this.renderPassEvent = param.renderEvent;
- m_blurMat = param.blurMat;
- blurredID01.Init(”_Blur01”);
- blurredID02.Init(”_Blur02”);
- }
- //----------------------------------------------------------------
- public void Setup(RenderTargetIdentifier src){
- this.source = src;//传入renderer.cameraColorTarget
- }
- //----------------------------------------------------------------
- //在Execute方式里执行CommandBuffer
- public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData){
- if ((renderingData.cameraData.camera.cullingMask & 1<<LayerMask.NameToLayer(”UI”))>0) {
- //Debug.Log(”camera的cullingMask包含UI层,返回”);//并设置Camera>CullingMask不包罗UI层
- return;
- }
- CommandBuffer cmd = CommandBufferPool.Get(m_ProfilerTag);
- Vector2[] sizes = {
- new Vector2(Screen.width, Screen.height),
- new Vector2(Screen.width / 2, Screen.height / 2),
- new Vector2(Screen.width / 4, Screen.height / 4),
- new Vector2(Screen.width / 8, Screen.height / 8),
- };
- int numIterations = 3;
- RenderTextureDescriptor opaqueDesc = renderingData.cameraData.cameraTargetDescriptor;
- opaqueDesc.depthBufferBits = 0;
- // The precision of the render texture's depth buffer in bits (0, 16, 24 and 32 are supported).// 为什么加这句?
- cmd.GetTemporaryRT(m_tempColorTex.id, opaqueDesc, FilterMode.Bilinear);
- cmd.Blit(source, m_tempColorTex.Identifier());
- for (int i = 0; i < numIterations; ++i){
- cmd.GetTemporaryRT(blurredID01.id, opaqueDesc, FilterMode.Bilinear);
- cmd.GetTemporaryRT(blurredID02.id, opaqueDesc, FilterMode.Bilinear);
- cmd.Blit(m_tempColorTex.Identifier(), blurredID01.Identifier());
- cmd.SetGlobalVector(”offsets”, new Vector4(2.0f / sizes[i].x, 0, 0, 0));
- cmd.Blit(blurredID01.Identifier(), blurredID02.Identifier(), m_blurMat);
- cmd.SetGlobalVector(”offsets”, new Vector4(0, 2.0f / sizes[i].y, 0, 0));
- cmd.Blit(blurredID02.Identifier(), blurredID01.Identifier(), m_blurMat);
- cmd.Blit(blurredID01.Identifier(), m_tempColorTex.Identifier());
- }
- //把最终的内容传给 ”_GrabBlurTexture”
- cmd.SetGlobalTexture(”_GrabBlurTexture”, blurredID01.Identifier());
- //-----------
- context.ExecuteCommandBuffer(cmd);
- CommandBufferPool.Release(cmd);
- }
- //----------------------------------------------------------------
- // 释放临时资源
- public override void FrameCleanup(CommandBuffer cmd){
- cmd.ReleaseTemporaryRT(m_tempColorTex.id);
- cmd.ReleaseTemporaryRT(blurredID01.id);
- cmd.ReleaseTemporaryRT(blurredID02.id);
- }
- }
复制代码 附:一个可以开关RendererFeature的脚本,来自<link>
错误谬误:
①是用cmd.Blit实现的传输,不撑持Single-Pass Instanced VR 且URP不建议使用这个过时的API;
②没有使用RTHandle,v13.1.9之后的URP版本需要使用 RTHandle 替代 RenderTargetIdentifier、RenderTargetHandle;
③玻璃后的半透明物体不成见;
④玻璃前的opaque物体也会被衬着到玻璃上,但是不太明显(大部门被玻璃前的opaque物体自身盖住了,只是边缘有点颜色溢出)
下面升级unity版本,可以撑持Single-Pass Instanced VR;那如果不想升级版本的话,怎么撑持Single-Pass Instanced VR?
呃……我试了一个下午……好吧我不会……
URP v13.1.9之后才有【RenderingUtils.ReAllocateIfNeeded()】方式——用不了RTHandle的话,就用RenderTargetIdentifier;用不了Blitter封装好的方式,那就搬它的源码;可单是源码的话还不够啊,不知道差了什么设置才能撑持Single-Pass Instanced VR;而且不知道为什么在URP版本v12.1.7里,每用1次Blitter源码,画面就会变亮一个等级,为什么会变亮啊…… 2. 迁移至URP v14.0.6
迁移至unity版本2022.2.7,URP版本v14.0.6
报错:You can only call cameraColorTarget inside the scope of a ScriptableRenderPass. Otherwise the pipeline camera target texture might have not been created or might have already been disposed.
解决方式1:参考<github/UniversalRenderingExamples/RenderPasses>在 RenderPass 的 OnCameraSetup(CommandBuffer cmd, ref RenderingData renderingData)方式里获取cameraColorTarget
解决方式2:参考<Perform a full screen blit in URP(V14.0.6)>或者参考< Upgrading to version 2022.1 of URP > 在 RenderFeature 里重写SetupRenderPasses()方式,在SetupRenderPasses()方式里你可以访谒renderer.cameraColorTargetHandle
3.升级至 RTHandle & Blitter
为什么要升级?——URP官网说了:cmd.Blit是已过时的API,且不撑持 Single-Pass Instanced VR;在URP项目中,请避免使用CommandBuffer.Blit及其它依赖于它的API(比如RenderingUtils.Blit);详见:URP Blit 入门(这篇笔记还没发)
◆ 用 Blitter 替换cmd.Blit,是否就可以撑持 Single-Pass Instanced VR?是的!shader也要记得升级,见下一章节
◆ 用 RTHandle 替代 RenderTargetHandle(这个obsolete了必定要被替换的)、RenderTargetIdentifier(这个还是可以用的那要替换吗)——在试图用 Blitter 替换 cmd.Blit 的过程中,我找到的解决方式是“不要用RenderTargetIdentifier,全用RTHandle”
◆ 参与了Blit过程的材质球(shader)也需要改削:增加[_BlitTexture]变量用于绑定Blitter函数的 input texture;
详细的踩坑记录见:URP Blit 入门 -03 Class Blitter(这篇笔记还没发)
代码在[f02_v14_0_6]这个文件夹里:FrostedGlassRenderFeature.cs
(下面这个就是本篇笔记的真心实意了 真是踩了好多坑啊)- public class FrostedGlassRenderFeature : ScriptableRendererFeature{
- //在ScriptableRendererFeature类里写一个class Settings,并实例化它
- [System.Serializable]
- public class Settings{
- public RenderPassEvent renderEvent = RenderPassEvent.BeforeRenderingTransparents;
- public Material blurMat;
- }
- public Settings settings = new Settings();
- //----------------------------------------------------------------
- public class FrostedGlassRenderPass : ScriptableRenderPass{......}
- //----------------------------------------------------------------
- FrostedGlassRenderPass m_ScriptablePass;
- public override void Create(){ //在Create方式里实例化ScriptableRenderPass类
- m_ScriptablePass = new FrostedGlassRenderPass(settings);//实例化包含了renderPassEvent的设置
- }
- public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData){
- //m_ScriptablePass.Setup(renderer.cameraColorTargetHandle);
- //上面这行放在AddRenderPasses()方式里会报错:
- //可以放到RenderPass的OnCameraSetup()里;也可以放到RendererFeature的SetupRenderPasses()里;
- m_ScriptablePass.ConfigureInput(ScriptableRenderPassInput.Color);
- if (renderingData.cameraData.cameraType == CameraType.Game){
- renderer.EnqueuePass(m_ScriptablePass);
- }
- }
- }
- ------------------------------------------------------------------------------------------
- ......
- public class FrostedGlassRenderPass : ScriptableRenderPass{
- CommandBuffer cmd;
- string m_ProfilerTag;//cmd name
- Material m_blurMat;
- RTHandle source;
- RTHandle rth_tempTex;
- RTHandle rth_Blur01;
- RTHandle rth_Blur02;
- //首先写这个ScriptableRenderPass的构造函数
- public FrostedGlassRenderPass(FrostedGlassRenderFeature.Settings param){
- m_ProfilerTag = ”FrostedGalss”;
- this.renderPassEvent = param.renderEvent;
- m_blurMat = param.blurMat;
- }
- //----------------------------------------------------------------
- // This method is called before executing the render pass.
- // It can be used to configure render targets and their clear state. Also to create temporary render target textures.
- // When empty this render pass will render to the active camera render target.
- public override void OnCameraSetup(CommandBuffer cmd, ref RenderingData renderingData) {
- var renderer = renderingData.cameraData.renderer;
- this.source = renderer.cameraColorTargetHandle;
- RenderTextureDescriptor opaqueDesc = renderingData.cameraData.cameraTargetDescriptor;
- opaqueDesc.depthBufferBits = 0; //为什么加这句?// Color and depth cannot be combined in RTHandles
- /*下面这个错误的……就当是记录下黑历史……
- // int id_tempTex = Shader.PropertyToID(”_TempTex”);
- // cmd.GetTemporaryRT(id_tempTex, opaqueDesc, FilterMode.Bilinear);
- // rti_tempTex = new RenderTargetIdentifier(id_tempTex);
- // rth_tempTex = RTHandles.Alloc(rti_tempTex);
- */
- RenderingUtils.ReAllocateIfNeeded(ref rth_tempTex, opaqueDesc, FilterMode.Bilinear, TextureWrapMode.Clamp, name: ”_TempTex”);
- RenderingUtils.ReAllocateIfNeeded(ref rth_Blur01, opaqueDesc, FilterMode.Bilinear, TextureWrapMode.Clamp, name: ”_Blur01”);
- RenderingUtils.ReAllocateIfNeeded(ref rth_Blur02, opaqueDesc, FilterMode.Bilinear, TextureWrapMode.Clamp, name: ”_Blur02”);
- // rth_tempTex = RTHandles.Alloc(in opaqueDesc,FilterMode.Bilinear,TextureWrapMode.Clamp,name: ”_TempTex”);
- // 上面这个也可以正确运行,但是记得要在OnCameraCleanup()里执行Release
- }
- //----------------------------------------------------------------
- // Here you can implement the rendering logic. 在Execute方式里执行CommandBuffer
- public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData){
- CommandBuffer cmd = CommandBufferPool.Get();
- using(new ProfilingScope(cmd, new ProfilingSampler(m_ProfilerTag))){
- Vector2[] sizes = {
- new Vector2(Screen.width, Screen.height),
- new Vector2(Screen.width / 2, Screen.height / 2),
- new Vector2(Screen.width / 4, Screen.height / 4),
- new Vector2(Screen.width / 8, Screen.height / 8),
- };
- int numIterations = 2;//3
- Blitter.BlitCameraTexture(cmd,source,rth_tempTex);//表格里的类型|C|
- for (int i = 0; i < numIterations; ++i){
- Blitter.BlitCameraTexture(cmd,rth_tempTex,rth_Blur01);//表格里的类型|C|
- cmd.SetGlobalVector(”_Offset”, new Vector4(2.0f / sizes[i].x, 0, 0, 0));
- Blitter.BlitCameraTexture(cmd, rth_Blur01, rth_Blur02, m_blurMat, 0);//表格里的类型|A|
- cmd.SetGlobalVector(”_Offset”, new Vector4(0, 2.0f / sizes[i].y, 0, 0));
- Blitter.BlitCameraTexture(cmd, rth_Blur02, rth_Blur01, m_blurMat, 0);//表格里的类型|A|
- Blitter.BlitCameraTexture(cmd, rth_Blur01, rth_tempTex);//表格里的类型|C|
- }
- //把最终内容Blit到一个RenderTexture上。
- cmd.SetGlobalTexture(”_GrabBlurTexture”, (RenderTargetIdentifier)rth_Blur01);
- }
- //---------------------------------------------
- context.ExecuteCommandBuffer(cmd);// Use ScriptableRenderContext to issue drawing commands or execute command buffers
- cmd.Clear();
- CommandBufferPool.Release(cmd);
- }
- //----------------------------------------------------------------
- // Cleanup any allocated resources that were created during the execution of this render pass.
- public override void OnCameraCleanup(CommandBuffer cmd){}
- public override void FrameCleanup(CommandBuffer cmd){}
- public void Dispose(){
- rth_tempTex?.Release();
- rth_Blur01?.Release();
- rth_Blur02?.Release();
- }
- }
复制代码 Shader改削:用于做Blur计算的shader(”Hidden/SeparableGlassBlur”)
使用[_BlitTexture]接受Blitter函数输入的source,不需要手动定义[_BlitTexture],可直接 include Blit.hlsl;- #include ”Packages/com.unity.render-pipelines.core/Runtime/Utilities/Blit.hlsl”
复制代码 Blit.hlsl可以提供 vertex shader (Vert), input structure (Attributes) and output strucutre (Varyings)
(不贴shader了,直接放下一章节里)
4.如何撑持 Single-Pass Instanced VR?
文档: https://docs.unity3d.com/2022.2/Documentation/Manual/SinglePassInstancing.html
我们已经用 Blitter 替换全部的cmd.Blit了,此刻只需要让shader撑持Single-Pass Instanced VR就大功告成啦
用于做Blur计算的shader:- Shader ”Hidden/SeparableGlassBlur_v2” {
- // Properties {}
- Subshader {
- Tags { ”RenderType”=”Opaque” ”RenderPipeline”=”UniversalPipeline” }
- Pass {
- Name ”SeparableGlassBlur”
- ZTest Always
- Cull Off
- ZWrite Off
- HLSLPROGRAM
- #include ”Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl”
- // Blit.hlsl 提供 vertex shader (Vert), input structure (Attributes) and output strucutre (Varyings)
- #include ”Packages/com.unity.render-pipelines.core/Runtime/Utilities/Blit.hlsl”
- #pragma vertex myVert
- #pragma fragment myFrag
- // 由Blit.hlsl来定义Attributes
- // struct Attributes {
- // float4 posOS : POSITION;
- // half2 uv : TEXCOORD0;
- // UNITY_VERTEX_INPUT_INSTANCE_ID //Insert to support Single-Pass Instanced VR
- // };
- struct v2f {
- float4 posCS : SV_POSITION;//POSITION;
- float2 uv : TEXCOORD0;
- float4 uv01 : TEXCOORD1;
- float4 uv23 : TEXCOORD2;
- float4 uv45 : TEXCOORD3;
- UNITY_VERTEX_OUTPUT_STEREO //Insert to support Single-Pass Instanced VR
- };
- float4 _Offset;
- v2f myVert (Attributes input) {
- v2f o;
- UNITY_SETUP_INSTANCE_ID(input);//Insert to support Single-Pass Instanced VR
- UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);//Insert to support Single-Pass Instanced VR
- #if SHADER_API_GLES //拷贝自Blit.hlsl
- float4 pos = input.positionOS;
- float2 uv = input.uv;
- #else
- float4 pos = GetFullScreenTriangleVertexPosition(input.vertexID);
- float2 uv = GetFullScreenTriangleTexCoord(input.vertexID);
- #endif
- o.posCS = pos;
- o.uv = uv * _BlitScaleBias.xy + _BlitScaleBias.zw;
- o.uv01 = o.uv.xyxy + _Offset.xyxy * float4(1,1, -1,-1);
- o.uv23 = o.uv.xyxy + _Offset.xyxy * float4(1,1, -1,-1) * 2.0;
- o.uv45 = o.uv.xyxy + _Offset.xyxy * float4(1,1, -1,-1) * 3.0;
- return o;
- }
- half4 myFrag (v2f i) : SV_Target {//COLOR
- UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(i);//Insert to support Single-Pass Instanced VR
- half4 color = float4 (0,0,0,0);
- color += 0.40 * SAMPLE_TEXTURE2D_X(_BlitTexture, sampler_PointClamp, i.uv);
- color += 0.15 * SAMPLE_TEXTURE2D_X(_BlitTexture, sampler_PointClamp, i.uv01.xy);
- color += 0.15 * SAMPLE_TEXTURE2D_X(_BlitTexture, sampler_PointClamp, i.uv01.zw);
- color += 0.10 * SAMPLE_TEXTURE2D_X(_BlitTexture, sampler_PointClamp, i.uv23.xy);
- color += 0.10 * SAMPLE_TEXTURE2D_X(_BlitTexture, sampler_PointClamp, i.uv23.zw);
- color += 0.05 * SAMPLE_TEXTURE2D_X(_BlitTexture, sampler_PointClamp, i.uv45.xy);
- color += 0.05 * SAMPLE_TEXTURE2D_X(_BlitTexture, sampler_PointClamp, i.uv45.zw);
- return color;
- }
- ENDHLSL
- }
- }
- }
复制代码 用于衬着玻璃的shader:- Shader ”FX/Glass/Stained BumpDistort (no grab) v2” {
- Properties {
- _BumpAmt (”Distortion”, Range (0,256)) = 125
- _TintAmt (”Tint Amount”, Range(0,1)) = 0.1
- _MainTex (”Tint Color (RGB)”, 2D) = ”white” {}
- _BumpMap (”Normalmap”, 2D) = ”bump” {}
- }
- SubShader{
- Tags { ”RenderPipeline”=”UniversalPipeline” ”Queue”=”Transparent” ”RenderType”=”Opaque” }
- Pass {
- Name ”BASE”
- Tags { ”LightMode”=”UniversalForward” }
- HLSLPROGRAM
- #pragma vertex vert
- #pragma fragment frag
- #pragma multi_compile_fog
- #include ”Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl”
- struct appdata_t {
- float4 vertex : POSITION;
- float2 texcoord: TEXCOORD0;
- UNITY_VERTEX_INPUT_INSTANCE_ID //Insert to support Single-Pass Instanced VR
- };
- struct v2f {
- float4 vertex : POSITION;
- float4 uvgrab : TEXCOORD0;
- float2 uvbump : TEXCOORD1;
- float2 uvmain : TEXCOORD2;
- float fogFactor : TEXCOORD3;
- UNITY_VERTEX_OUTPUT_STEREO //Insert to support Single-Pass Instanced VR
- };
- float _BumpAmt;
- half _TintAmt;
- float4 _BumpMap_ST;
- float4 _MainTex_ST;
- v2f vert (appdata_t v){
- v2f o;
- UNITY_SETUP_INSTANCE_ID(v); //Insert to support Single-Pass Instanced VR
- UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o); //Insert to support Single-Pass Instanced VR
- o.vertex = TransformObjectToHClip(v.vertex);
- #if UNITY_UV_STARTS_AT_TOP
- float scale = -1.0;
- #else
- float scale = 1.0;
- #endif
- o.uvgrab.xy = (float2(o.vertex.x, o.vertex.y*scale) + o.vertex.w) * 0.5;
- o.uvgrab.zw = o.vertex.zw;
- o.uvbump = TRANSFORM_TEX( v.texcoord, _BumpMap );
- o.uvmain = TRANSFORM_TEX( v.texcoord, _MainTex );
- o.fogFactor = ComputeFogFactor(o.vertex.z);
- return o;
- }
- sampler2D _BumpMap;
- sampler2D _MainTex;
- float4 _GrabBlurTexture_TexelSize;
- TEXTURE2D_X(_GrabBlurTexture);// sampler2D _GrabBlurTexture; //Insert to support Single-Pass Instanced VR
- SAMPLER(sampler_GrabBlurTexture);//Insert to support Single-Pass Instanced VR
- half4 frag (v2f i) : SV_Target{
- UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(i);//Insert to support Single-Pass Instanced VR
- // calculate perturbed coordinates
- // we could optimize this by just reading the x & y without reconstructing the Z
- half2 bump = UnpackNormal(tex2D( _BumpMap, i.uvbump )).rg;
- float2 offset = bump * _BumpAmt * _GrabBlurTexture_TexelSize.xy;
- i.uvgrab.xy = offset * i.uvgrab.z + i.uvgrab.xy;
- // half4 col = tex2Dproj (_GrabBlurTexture, i.uvgrab/i.uvgrab.w);
- half4 col = SAMPLE_TEXTURE2D_X (_GrabBlurTexture, sampler_GrabBlurTexture, i.uvgrab.xy/i.uvgrab.w);
- half4 tint = tex2D(_MainTex, i.uvmain);
- col = lerp (col, tint, _TintAmt);
- col.rgb = MixFog(col.rgb, i.fogFactor);
- return col;
- }
- ENDHLSL
- }
- }
- }
复制代码
完~✿阿谁……“③玻璃后的半透明物体不成见”啊啊啊啊不想再折腾啦,下次再研究! 5. 完善的毛玻璃效果
Lit+Refraction+Frosted
- Lit:偷懒,用ShaderGraph实现了
- Refraction:折射是玻璃效果的本质啊!教程参考 Screen Space Refraction for Glass and Water using Shader Graph 来自 < https://www.youtube.com/watch?v=VMsOPUUj0JA>
- Frosted:在 shader graph 里 SceneColor节点 是可以撑持single-pass instanced VR的,但如果使用我们自定义的 GrabBlurTexture 就不能撑持single-pass instanced VR了;……才发现我对single-pass instanced VR这个技术其实一点没搞懂
我的解决方式是用 Custom Function 节点,新建一个 hlsl 文件:- //UNITY_SHADER_NO_UPGRADE
- #ifndef MYHLSLINCLUDE_INCLUDED
- #define MYHLSLINCLUDE_INCLUDED
- TEXTURE2D_X(_GrabBlurTexture);// sampler2D _GrabBlurTexture; //Insert to support Single-Pass Instanced VR
- SAMPLER(sampler_GrabBlurTexture);//Insert to support Single-Pass Instanced VR
- float4 _GrabBlurTexture_TexelSize;
- void SampleTextureX_float(float2 uv, out half4 col){
- col = SAMPLE_TEXTURE2D_X(_GrabBlurTexture, sampler_GrabBlurTexture, uv);
- }
- #endif //MYHLSLINCLUDE_INCLUDED
复制代码 唉……
https://www.zhihu.com/video/1670856985879900160 |
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有账号?立即注册
×
|