UnityShader:选择Pass渲染通道

本文介绍了Unity中通过指定不同的渲染通道实现多效果输出的方法。详细解释了如何在Shader中设置多个Pass,并通过C#脚本在运行时切换不同的Pass以达到不同的渲染效果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

上一篇博客讲了MRT多重渲染,这篇接着学习通过一个shader输出不同效果的另一种方法——指定不同的渲染通道。

渲染通道在unity Shader中就是SubShader中的Pass。之前的shader中都只有一个Pass,也就是单通道渲染,这样的话如果要对同一个RenderTexture在不同的时刻进行不同的渲染效果输出就需要不停的更换shader。当然,也可以使用多重渲染,但是如果一次只用一个效果,用多重渲染则有些浪费。这个时候就需要多通道渲染。

多通道渲染就是在一个shader中有多个Pass,玩家可以根据需求设定通过哪个Pass来进行渲染,从而实现在不同的时候对使用同一个shader对同一个对象进行不同的效果处理。

1. Shader

先上Shader代码:

Shader "Custom/PassTest" {
    Properties{
        _MainTex("Base (RGB)", 2D) = "white" {}
    }

        CGINCLUDE

        #include "UnityCG.cginc"

        sampler2D _CameraDepthTexture;
        uniform sampler2D _MainTex;

        struct v2f {
            float4 pos : SV_POSITION;
            float4 scrPos:TEXCOORD0;
            float2 uv : TEXCOORD1;
        };
        //Vertex Shader
        v2f vert(appdata_base v) {
            v2f o;
            o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
            o.scrPos = ComputeScreenPos(o.pos);
            o.uv = v.texcoord.xy;
            return o;
        }

        //Reverse frag
        float4 fragReverse(v2f i) :COLOR{
            fixed4 col = tex2D(_MainTex, i.uv);
            // just invert the colors
            col = 1 - col;
            return col;
        }
        //Dept frag
        float4 fragDepth(v2f i) :COLOR{
            float depthValue = 1 - Linear01Depth(tex2Dproj(_CameraDepthTexture, UNITY_PROJ_COORD(i.scrPos)).r);
            return float4(depthValue, depthValue, depthValue, 1.0f);
        }

        ENDCG

    Subshader {
        Tags{ "RenderType" = "Opaque" }
        //Pass 0
        Pass{
            ZTest Always Cull Off ZWrite Off
            Fog{ Mode off }

            CGPROGRAM
            #pragma glsl
            #pragma fragmentoption ARB_precision_hint_fastest
            #pragma vertex vert
            #pragma fragment fragReverse
            #pragma target 3.0
            ENDCG
        }
        //Pass 1
        Pass{
            ZTest Always Cull Off ZWrite Off
            Fog{ Mode off }

            CGPROGRAM
            #pragma glsl
            #pragma fragmentoption ARB_precision_hint_fastest
            #pragma vertex vert
            #pragma fragment fragDepth
            #pragma target 3.0
            ENDCG
        }
    }

    Fallback "Diffuse"
}

shader并不难,所有的方法和变量都放在了SubShader外面,其中,vert是顶点方法,fragReverse是颜色反向的片段方法,fragDepth是深度图的片段方法。

在SubShader中有两个Pass,从上到下分别对应0,1,2……。Shader的主体,包括顶点和片段方法的指定都在这些对应的Pass中。这里由于两个Pass共用同一个顶点方法,所以vertex都是vert,第一个Pass调用fragReverse来实现颜色反向效果,二第二个Pass调用fragDepth来输出深度图。

现在shader有了,再来看看如何在脚本中修改渲染通道。

2. 修改渲染通道

先上代码:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public enum PassType
{
    Reverse,
    Depth
}
public class CameraRanderPass : MonoBehaviour {

    public PassType showType = PassType.Reverse;
    public Material Mat;

    void OnRenderImage(RenderTexture src, RenderTexture dest)
    {
        Graphics.Blit(src, dest, Mat, (int)showType);
    }
}

C#脚本也很简单,和之前差不多,关键的不同是Graphics.Blit(src, dest, Mat, (int)showType);的最后多了个参数。Graphics.Blit的第四个参数是通道指定参数,可省略,默认为0,也就是第一个Pass。

通常写shader都只有一个Pass,省略这个参数将会默认调用这个Pass,现在有了两个Pass,我们就可以通过传入不同的值(int)来指定通过不同的通道进行渲染。在这里,为了方便调用,我定义了一个PassType枚举,Reverse表示颜色反向,Depth表示深度,和Shader中对应。

转载请注明出处:http://blog.csdn.net/ylbs110/article/details/53560444

下面来看看选择这两个Pass后的不同输出效果:
Reverse:
这里写图片描述
Depth:
这里写图片描述

### 实现 Unity ShaderPass 并应用于不同渲染队列 在 Unity 中,通过编写自定义着色器 (Shader),可以实现多个 Pass 的功能,并将其分配给不同渲染队列。这允许更精细地控制对象绘制顺序以及如何处理光照和其他效果。 #### 定义多 Pass 着色器结构 为了支持多种渲染路径,在 HLSL 或 CG 语法下声明多个 `Pass` 块: ```hlsl Shader "Custom/MultiPassExample" { Properties { _MainTex ("Texture", 2D) = "white" {} } SubShader { Tags { "RenderType"="Opaque" } // 第一阶段:不透明物体渲染 Pass { Name "OPAQUE_PASS" Cull Off ZWrite On HLSLPROGRAM #pragma vertex vert #pragma fragment frag struct Attributes { float4 positionOS : POSITION; float2 uv : TEXCOORD0; }; struct Varyings { float2 uv : TEXCOORD0; float4 positionHCS : SV_POSITION; }; sampler2D _MainTex; Varyings vert(Attributes input) { Varyings output; output.positionHCS = TransformObjectToHClip(input.positionOS); output.uv = input.uv; return output; } half4 frag(Varyings input) : SV_Target { return SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, input.uv); } ENDHLSL } // 第二阶段:半透明物体渲染 Pass { Name "TRANSPARENT_PASS" Blend SrcAlpha OneMinusSrcAlpha ZWrite Off Cull Back HLSLPROGRAM #pragma vertex vertTransparent #pragma fragment fragTransparent Varyings vertTransparent(Attributes input) { Varyings output = (Varyings)0; output.positionHCS = TransformObjectToHClip(input.positionOS); output.uv = input.uv; return output; } half4 fragTransparent(Varyings input) : SV_Target { half4 col = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, input.uv); col.a *= 0.5; // 调整透明度 return col; } ENDHLSL } // 可选第三阶段或其他特殊效果... } } ``` 此示例展示了两个主要的渲染通道——一个是针对完全不透明的对象,另一个用于具有部分透明性的表面[^1]。 #### 设置材质属性并指定渲染队列 当创建 Material 对象时,可以通过 Inspector 面板调整其渲染队列参数。对于上述着色器,默认情况下会遵循 `"RenderType"` 标签中的设定 (`Opaque`);但对于其他类型的几何体,则可能需要手动更改这些值来确保正确的排序行为。 - **不透明物体质感**: 使用默认设置即可。 - **半透明质感**: 将 Render Queue 设定为更高的数值(如 3000),以延迟它们被绘制的时间点,从而避免遮挡问题。 此外还可以利用 Unity 提供的各种内置标签进一步优化性能表现,比如 `Queue=Geometry+10` 表明该材质应该紧跟在标准几何图形之后进行渲染[^2]。 #### 应用场景实例分析 假设有一个角色模型由若干个网格组成,其中某些部位带有发光特效或玻璃状外观。此时就可以考虑采用分层的方式构建 Shader Graph 或手写代码形式下的 Multi-Pass 结构,使得每种材料都能按照预期方式呈现出来而不互相干扰。 例如,眼睛区域可能会有独立于身体其余部分的不同反射特性;武器装备也许会有金属光泽或是魔法光芒环绕等独特视觉效果。借助这种方式不仅可以增强画面的真实性和吸引力,同时也便于后期维护和扩展新功能[^3]。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值