前言

之前的业务一直对图形学涉及不多,现在打算系统学习一下。

Shader代码见得多,但也仅限于对着代码猜其功能,具体的结构和写法不求甚解,现在总结下。

属性

定义可变属性

  • Color
  • Vector4
  • Texture2D
  • 等等
  Properties
  {
      // 在此处定义您的属性,例如颜色、纹理等
      _Color ("Color", Color) = (1, 1, 1, 1)
      _MainTex ("Texture", 2D) = "white" {}
  }

SubShader

ShaderLab:定义 Shader 对象 - Unity 手册

ShaderLab:定义子着色器 - Unity 手册

子Shader,渲染时会逐个使用,找到第一个生效的,如果都不生效,执行FallBack的Shader。

Tags(子着色器)

ShaderLab:向子着色器分配标签 - Unity 手册

子着色器标签定义了子着色器块或一个通道在何时以及在何种条件下被执行。

RenderPipeline

RenderPipeline 标签向 Unity 告知子着色器是否与通用渲染管线 (URP) 或高清渲染管线 (HDRP) 兼容。

Queue

Queue 标签向 Unity 告知要用于它渲染的几何体的渲染队列。

Queue = [queue name] + [offset]
[queue name]Background指定背景渲染队列。
Geometry指定几何体渲染队列。
AlphaTest指定 AlphaTest 渲染队列。
Transparent指定透明渲染队列。
Overlay指定覆盖渲染队列。
[offset]整数指定 Unity 渲染未命名队列处的索引(相对于命名队列)。

RenderType

在运行时替换着色器 - Unity 手册

使用 RenderType 标签可覆盖 Shader 对象的行为。

DisableBatching

DisableBatching 子着色器标签阻止 Unity 将动态批处理应用于使用此子着色器的几何体。

IgnoreProjector

在内置渲染管线中,IgnoreProjector 子着色器标签向 Unity 告知几何体是否受投影器影响。这对于排除投影器不兼容的半透明几何体多半很有用。

此标签在其他渲染管线中无效。

Pass

ShaderLab:定义一个通道 - Unity 手册

简单的 Shader 对象可能只包含一个通道,但更复杂的着色器可以包含多个通道。您可以为 Shader 对象不同部分定义单独的通道实现不同的工作方式;例如,需要更改渲染状态、不同的着色器程序或不同的 LightMode 标签的部分。

Pass标签

Unity 使用预定义的标签和值来确定如何以及何时渲染给定的通道。您还可以使用自定义值创建自己的自定义通道标签,并从 C# 代码访问它们。

最常用的预定义通道标签是 LightMode 标签。

URP ShaderLab Pass tags | Universal RP | 17.0.3

Pass命令

在 Pass 代码块中使用这些命令可为该 Pass 设置渲染状态,或者在 SubShader 代码块中使用这些命令可为该 SubShader 以及其中的所有 Pass 设置渲染状态。

  • AlphaToMask:设置 alpha-to-coverage 模式。
  • Blend:启用和配置 alpha 混合。
  • BlendOp:设置 Blend 命令使用的操作。
  • ColorMask:设置颜色通道写入掩码。
  • Conservative:启用和禁用保守光栅化。
  • Cull:设置多边形剔除模式。
  • Offset:设置多边形深度偏移。
  • Stencil:配置模板测试,以及向模板缓冲区写入的内容。
  • ZClip:设置深度剪辑模式。
  • ZTest:设置深度测试模式。
  • ZWrite:设置深度缓冲区写入模式。

通道命令

在 SubShader 中使用这些命令可定义具有特定用途的通道。

  • UsePass 定义一个通道,它从另一个 Shader 对象导入指定的通道的内容。
  • GrabPass 创建一个通道,将屏幕内容抓取到纹理中,以便在之后的通道中使用。

代码块

ShaderLab:添加着色器程序 - Unity 手册

模板

Shader "MyURPShader"
{
    Properties
    {
        // 在此处定义您的属性,例如颜色、纹理等
        _Color ("Color", Color) = (1, 1, 1, 1)
        _MainTex ("Texture", 2D) = "white" {}
    }

    SubShader
    {
        Tags
        {
            "RenderPipeline" = "UniversalRenderPipeline"
            "RenderType" = "Opaque"
        }

        Pass
        {
            HLSLPROGRAM
            #pragma vertex Vertex
            #pragma fragment Fragment

            struct Attributes
            {
                float4 positionOS : POSITION;
                float2 uv : TEXCOORD0;
            };

            struct Varyings
            {
                float2 uv : TEXCOORD0;
                float4 positionCS : SV_POSITION;
            };

            Varyings Vertex (Attributes input)
            {
                Varyings output;
                output.positionCS = TransformObjectToHClip(input.positionOS);
                output.uv = input.uv;
                return output;
            }

            half4 Fragment (Varyings input) : SV_Target
            {
                half4 color = half4(1, 1, 1, 1);

                // 在此处进行纹理采样和颜色计算
                color *= tex2D(_MainTex, input.uv);
                color *= _Color;

                return color;
            }
            ENDHLSL
        }
    }

    Fallback "UniversalRenderPipeline/Lit"
}

总结

后续的学习都是以URP为主,参考的资料也是URP和官方的文档,内置的管线暂时不多了解。

Shader代码包含了ShaderLab部分和HSLS部分,下一篇文章将介绍HSLS部分。