使用Cg/HLSL访问着色器属性器完全就是这样的

使用Cg/HLSL访问着色器属性器完全就是这样的

Declaring and using shader keywords in HLSL

使用 Cg/HLSL 访问着色器属性

着色器语义

编写 HLSL 着色器程序时,输入和输出变量需要通过语义来表明其“意图”。这是 HLSL 着色器语言中的标准概念;请参阅 MSDN 上的语义 (Semantics) 文档以了解更多详细信息。

顶点着色器输入语义

The main vertex shader function (indicated by the #pragma vertexdirective) needs to have semantics on all the input parameters.These correspond to individual Mesh data elements, like vertex position, normal mesh, and texture coordinates.See vertex program inputs for more details.

以下是一个简单的顶点着色器的示例,它采用顶点位置和纹理坐标作为输入。像素着色器将纹理坐标可视化为颜色。

Shader "Unlit/Show UVs"
{
    SubShader
    {
        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            struct v2f {
                float2 uv : TEXCOORD0;
                float4 pos : SV_POSITION;
            };
            v2f vert (
                float4 vertex : POSITION, // 顶点位置输入
                float2 uv : TEXCOORD0 // 第一个纹理坐标输入
                )
            {
                v2f o;
                o.pos = UnityObjectToClipPos(vertex);
                o.uv = uv;
                return o;
            }
            fixed4 frag (v2f i) : SV_Target
            {
                return fixed4(i.uv, 0, 0);
            }
            ENDCG
        }
    }
}

顶点着色单元_unity 顶点着色器_顶点着色引擎

Instead of spelling out all individual inputs one by one,it’s also possible to declare a structure of them, and indicatesemantics on each individual member variable of the struct.

片元着色器输出语义

通常,片元(像素)着色器会输出颜色,并具有SV_Target 语义。上面示例中的片元着色器完全就是这样的:

fixed4 frag (v2f i) : SV_Target

函数 frag 的返回类型为 fixed4(低精度RGBA 颜色)。因为它只返回一个值,所以语义由函数自身指示: SV_Target。

It’s also possible to return a structure with the outputs.The fragment shader above could be rewritten this way too, and it woulddo exactly the same:

struct fragOutput {
    fixed4 color : SV_Target;
};
fragOutput frag (v2f i)
{
    fragOutput o;
    o.color = fixed4(i.uv, 0, 0);
    return o;
}

从片元着色器返回结构对于不止返回单个颜色的着色器非常有用。片元着色器输出支持的其他语义如下。

SV_TargetN:多个渲染目标

SV_Target1、SV_Target2 等等:这些是着色器写入的附加颜色。这在一次渲染到多个渲染目标(称为“多渲染目标”渲染技术unity 顶点着色器,简称 MRT)时使用。SV_Target0 等同于 SV_Target。

SV_Depth:像素着色器深度输出

Usually the fragment shader doesn’t override the Z buffer value, and a default value is used from the regular triangle rasterization. However, for some effects it’s useful to output custom Z buffer depth values per pixel.

Note that on many GPUs this turns off some depth buffer optimizations, so don’t override Z buffer value without a good reason. The cost incurred by SV_Depth varies depending on the GPU architecture, but overall it’s fairly similar to the cost of alpha testing (using the built-in clip() function in HLSL). Render shaders that modify depth after all regular opaque shaders (for example, by using the AlphaTest rendering queue.

深度输出值必须为单个 float。

顶点着色器输出和片元着色器输入

顶点着色器需要输出顶点的最终裁剪空间位置,以便 GPU 知道屏幕上的栅格化位置以及深度。此输出需要具有 SV_POSITION 语义,并为 float4 类型。

顶点着色器生成的所有其他输出(“插值器”或“变化”)都是您的特定着色器需要的。从顶点着色器输出的值将在渲染三角形的面上进行插值创作人,并且每个像素的值将作为输入传递给片元着色器。

Many modern GPUs don’t really care what semantics these variables have; however some old systems (most notably, shader model 2 GPUs) did have special rules about the semantics:

为了获得最佳的跨平台支持unity 顶点着色器游戏评测,应将顶点输出和片元输入标记为 TEXCOORDn 语义。

插值器数量限制

对于总共可以使用多少个插值器变量将信息从顶点传递到片元着色器,存在一些限制。该限制取决于平台和 GPU,一般准则如下:

Regardless of your particular target hardware, it’s generally a good idea to use as few interpolators as possible for performance reasons.

其他特殊语义屏幕空间像素位置:VPOS

片元着色器可以接收渲染为特殊 VPOS 语义的像素的位置。此功能仅从着色器模型 3.0 开始存在,因此着色器需要具有 #pragma target 3.0 编译指令。

On different platforms the underlying type of the screen space position input varies, so for maximum portability use the UNITY_VPOS_TYPE type for it, which is float4 on most platforms.

Additionally, using the pixel position semantic makes it hard to have both the clip space position (SV_POSITION) and VPOS in the same vertex-to-fragment structure. Therefore, the vertex shader should output the clip space position as a separate “out” variable. See the example shader below:

Shader "Unlit/Screen Position"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}
    }
    SubShader
    {
        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #pragma target 3.0
            // 注意:此结构中没有 SV_POSITION
            struct v2f {
                float2 uv : TEXCOORD0;
            };
            v2f vert (
                float4 vertex : POSITION, // 顶点位置输入
                float2 uv : TEXCOORD0, // 纹理坐标输入
                out float4 outpos : SV_POSITION // 裁剪空间位置输出
                )
            {
                v2f o;
                o.uv = uv;
                outpos = UnityObjectToClipPos(vertex);
                return o;
            }
            sampler2D _MainTex;
            fixed4 frag (v2f i, UNITY_VPOS_TYPE screenPos : VPOS) : SV_Target
            {
                // screenPos.xy 将包含像素整数坐标。
                // 使用它们来实现一个跳过渲染 4x4 像素块的
                // 棋盘图案
                // 棋盘图案中 4x4 像素块的 checker 值
                // 为负
                screenPos.xy = floor(screenPos.xy * 0.25) * 0.5;
                float checker = -frac(screenPos.r + screenPos.g);
                // 如果值为负,则 clip HLSL 指令停止渲染像素
                clip(checker);
                // 对于保留的像素,读取纹理并将其输出
                fixed4 c = tex2D (_MainTex, i.uv);
                return c;
            }
            ENDCG
        }
    }
}

unity 顶点着色器_顶点着色单元_顶点着色引擎

面对方向:VFACE

片元着色器可以接收一种指示渲染表面是面向摄像机还是背对摄像机的变量。这在渲染应从两侧可见的几何体时非常有用 - 通常用于树叶和类似的薄型物体。VFACE 语义输入变量将包含表示正面三角形的正值,以及表示背面三角形的负值。

此功能从着色器模型 3.0 开始才存在,因此着色器需要具有 #pragma target 3.0 编译指令。

Shader "Unlit/Face Orientation"
{
    Properties
    {
        _ColorFront ("Front Color", Color) = (1,0.7,0.7,1)
        _ColorBack ("Back Color", Color) = (0.7,1,0.7,1)
    }
    SubShader
    {
        Pass
        {
            Cull Off // 关闭背面剔除
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #pragma target 3.0
            float4 vert (float4 vertex : POSITION) : SV_POSITION
            {
                return UnityObjectToClipPos(vertex);
            }
            fixed4 _ColorFront;
            fixed4 _ColorBack;
            fixed4 frag (fixed facing : VFACE) : SV_Target
            {
                // 正面的 VFACE 输入为正,
                // 背面的为负。根据这种情况
                // 输出两种颜色中的一种。
                return facing > 0 ?_ColorFront : _ColorBack;
            }
            ENDCG
        }
    }
}

The shader above uses the Cull state to disable back-face culling (by default back-facing triangles aren’t rendered at all). Here is the shader applied to a bunch of Quad meshes, rotated at different orientations:

unity 顶点着色器_顶点着色引擎_顶点着色单元

顶点 ID:SV_VertexID

顶点着色器可以接收具有“顶点编号”(为无符号整数)的变量。当您想要从纹理或 ComputeBuffers 中获取额外的每顶点数据时,这非常有用。

此功能从 DX10(着色器模型 4.0)和 GLCore/OpenGL ES 3 开始才存在,因此着色器需要具有 #pragma target 3.5 编译指令。

Shader "Unlit/VertexID"
{
    SubShader
    {
        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #pragma target 3.5
            struct v2f {
    fixed4 color : TEXCOORD0;
                float4 pos : SV_POSITION;
            };
            v2f vert (
                float4 vertex : POSITION, // 顶点位置输入
                uint vid : SV_VertexID // 顶点 ID,必须为 uint
                )
            {
                v2f o;
                o.pos = UnityObjectToClipPos(vertex);
                // 基于顶点 ID 输出时髦颜色
                float f = (float)vid;
                o.color = half4(sin(f/10),sin(f/100),sin(f/1000),0) * 0.5 + 0.5;
                return o;
            }
            fixed4 frag (v2f i) : SV_Target
            {
    return i.color;
            }
            ENDCG
        }
    }
}

unity 顶点着色器_顶点着色引擎_顶点着色单元

Declaring and using shader keywords in HLSL

使用 Cg/HLSL 访问着色器属性

文章来源:https://docs.unity3d.com/cn/2022.3/Manual/SL-ShaderSemantics.html