Unity Shader基础【二】- HLSL基本语法

下面对微软所给的HLSL官方文档进行简单梳理,将其基本语法总结如下。

1 数据类型

1.1 缓存(Buffer)
  • 用法:Buffer Name

  • 示例:Buffer g_Buffer;

  • 说明:Type可以为标量、向量或一些矩阵类型

1.2 标量
  • bool:布尔值,true或false。

  • int: 32位有符号整型。

  • uint: 32位无符号整型。

  • dword: 32位无符号整型。

  • half: 16位浮点型。该类型只是为了保持语言兼容性,Direct3D 10将所有half都映射为float型,该类型不能用作标准全局变量。

  • float:32位浮点型。

  • fixed: 11位低精度浮点数。

  • double: 64位浮点型。
1.3 向量类型
  • 用法:TypeNumber Name 或 vector

1.4 矩阵类型
  • 用法:TypeNumberxNumber Name 或 matrix

1.5 采样器类型(Sampler)
  • 用法:

    Direct3D 9:

    sampler Name = SamplerType{ Texture = ; [state_name = state_value;] … };

    Direct3D 10之后:

    SamplerType Name[Index]{ [state_name = state_value;] … };

  • 示例:

    Direct3D 9:
    
    sampler MeshTextureSampler = 
    sampler_state
    {
        Texture = <g_MeshTexture>;
        MipFilter = LINEAR;
        MinFilter = LINEAR;
        MagFilter = LINEAR;
    };
    
    Direct3D 10之后:
    
    SamplerState MeshTextureSampler
    {
        Filter = MIN_MAG_MIP_LINEAR;
        AddressU = Wrap;
        AddressV = Wrap;
    };
    
  • 说明:
    sampler:只有Direct3D 9需要。

    Name:采样器名称

    [Index]:Direct3D 10后需要,定义数据长度

    SamplerType:采样器类型,可为: sampler, sampler1D, sampler2D, sampler3D, samplerCUBE, sampler_state, SamplerState,SamplerComparisonState(仅Direct3D 10之后支持)。

    Texture = :纹理变量。

    state_name = state_value:可选状态设置,所有状态赋值必须出现在状态块中(大括号中),由分号分隔。

1.6 着色器类型(Shader)
  • 用法:

    Direct3D 10之后: SetXXXShader Compile( ShaderTarget, ShaderFunction );

    Direct3D 9之前: XXXShader = compile ShaderTarget ShaderFunction(…);

  • 示例:

    // Direct3D 10
    technique10 Render
    {
        pass P0
        {
            SetVertexShader( CompileShader( vs_4_0, VS() ) );
            SetGeometryShader( NULL );
            SetPixelShader( CompileShader( ps_4_0, PS() ) );
        }
    }
    
    // Direct3D 9
    technique RenderSceneWithTexture1Light
    {
        pass P0
        {          
            VertexShader = compile vs_2_0 RenderSceneVS( 1, true, true );
            PixelShader  = compile ps_2_0 RenderScenePS( true );
        }
    }
    
  • 说明:
    SetXXXShader: Direct3Dy调用底层API创建Shader对象,可为SetPixelShader、SetGeometryShader 或SetVertexShader。(Direct3D 9中XXXShader可为SetPixelShader或SetVertexShader)

    ShaderTarget: 用于编译的shader模型:vs_4_0, gs_4_0或ps_4_0

    ShaderFunction(…):Shader名称,包含着色器入口点函数名,当Shader被调用时,该函数会被执行;(…)表示函数参数,这些参数同样会被传递给创建Shader对象的API函数:SetPixelShader或SetVertexShader

1.7 纹理类型(Texture)
  • 用法:Type Name;

  • 示例:Texture2D g_MeshTexture;

  • 说明:Type可以为texture,Texture1D, Texture1DArray, Texture2D, Texture2DArray, Texture3D, TextureCube。

  • 备注:调用Texture在Direct3D 9和10中有比较大的差异

    //9
    Output.RGBColor = tex2D(MeshTextureSampler, In.TextureUV) * In.Diffuse;
    //10
    Output.RGBColor = g_MeshTexture.Sample(MeshTextureSampler, In.TextureUV) * In.Diffuse;
    
1.8 结构体

用法:

    struct struct2
    {
      int    a;
      float  b;
      int4x4 iMatrix;
    }

访问方式与C语言类似,通过.来访问。

1.9 自定义类型
  • 用法:typedef [const] Type Name[Index];

  • 示例:

    typedef int DWORD;
    typedef float FLOAT; 
    typedef vector <float, 4> VECTOR;
    typedef matrix <float, 4, 4> MATRIX;
    typedef string STRING;
    typedef texture TEXTURE;
    typedef pixelshader PIXELSHADER;
    typedef vertexshader VERTEXSHADER;
    
  • 说明:Type可以为HLSL定义的固定类型。

2 HLSL语义

2.1 顶点着色器(Vertex Shader)语义
输入描述类型
BINORMAL[n]次法线float4
BLENDINDICES[n]混合指数uint
BLENDWEIGHT[n]混合权重float
COLOR[n]固有色与高光色float4
NORMAL[n]法向量float4
POSITION[n]模型空间中顶点坐标float4
POSITIONT顶点坐标转置float4
PSIZE[n]点大小float
TANGENT[n]切线float4
TEXCOORD[n]纹理坐标float4
输出描述类型
COLOR[n]固有色与高光色float4
FOG顶点雾化值float
POSITION[n]齐次空间顶点坐标,将(x,y,z)除以w即可得到屏幕坐标空间,每个顶点Shader必须有该语义输出。float4
PSIZE点大小float
TESSFACTOR[n]曲面细分因子float
TEXCOORD[n]纹理坐标float4
2.2 像素着色器(Pixel Shader)语义
输入描述类型
COLOR[n]固有色与高光色float4
TEXCOORD[n]纹理坐标float4
VFACE用于标记一个背面图元的浮点标量值,负值表示面向背面,正值表示面向相机,该语义仅在Direct3D 9的Shader Model 3.0中可用,Direct3D 10以后使用SV_IsFrontFace替代float
VPOS屏幕空间像素位置(x,y). 该语义用于Direct3D 9,之后版本请使用SV_Positionfloat2
输出描述类型
COLOR[n]输出颜色float4
DEPTH[n]输出深度float
2.3 语义变化
Direct3D 10语义Direct3D 9等价语义
SV_DepthDEPTH
SV_PositionPOSITION
SV_TargetCOLOR
2.4 示例

套用《Unity Shader入门精要》一书中的内容作为示例:

// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'

Shader "Unlit/TestShader"
{
    SubShader{
        Pass{
            CGPROGRAM

            #pragma vertex vert
            #pragma fragment frag
            //通过结构体定义顶点着色器输入
            struct a2v{
                //POSTION语义:使用模型空间顶点坐标填充vertex变量
                float4 vertex : POSITION; 
                //NORMAL语义:使用模型空间法向量填充normal变量
                float3 normal : NORMAL; 
                //TEXCOORD0语义:使用模型第一套纹理坐标填充texcoord变量
                float4 texcoord : TEXCOORD0; 
            };

            struct v2f{
                //SV_POSTION语义:pos存储了裁剪空间中顶点位置信息
                float4 pos : SV_POSITION; 
                //COLOR0语义:color存储颜色信息
                float3 color : COLOR0;              
            };


            //SV_POSITION语义:顶点着色器的输出作为裁剪空间顶点坐标
            v2f vert(a2v v){
                v2f o;
                o.pos = UnityObjectToClipPos (v.vertex);
                //将法向量从[-1, 1]映射至[0, 1],通过color传递给像素(片元)着色器
                o.color = v.normal * 0.5 + fixed3(0.5, 0.5, 0.5);
                return o;
            }

            //SV_Target语义:像素着色器的输出存储到一个渲染目标(RenderTarget)当中
            fixed4 frag(v2f i) : SV_Target{         
                return fixed4(i.color, 1.0);
            }
            ENDCG
        }
    }
}
2.5 问题
  • HLSL中POSTION与VS_POSITION的区别?

    SV_前缀的变量代表system value,在DX10以后的语义绑定中被使用代表特殊的意义,和POSITION用法并无不同。唯一区别是 SV_POSTION一旦被作为vertex shader的输出语义,那么这个最终的顶点位置就被固定了,直接进入光栅化处理,如果作为fragment shader的输入语义那么和POSITION是一样的,代表着每个像素点在屏幕上的位置,这个说法其实并不准确,事实是fragment 在view space空间中的位置,但直观的感受是如括号之前所述一般。

    在DX10版本之前没有引入SV_的预定义语义,POSITION被用作vertex shader的输入和输出,fragment shader的输入参数。但DX10之后就推荐使用SV_POSITION作为vertex shader的输出和fragment shader的输入,注意vertex shader的输入还是使用POSITION! 不过,DX10以后的代码依旧兼容POSITION作为全程表达。

3 函数

3.1 函数声明

HLSL的函数定义与C语言也基本类型,形式如下:

[StorageClass] [clipplanes()] [precise] Return_Value Name ( [ArgumentList] ) [: Semantic]
{
  [StatementBlock]
};

参数说明:

  • StorageClass: 重定义函数声明的修改器,目前仅支持inline,因此函数总是内联。
  • clipplanes:可选剪裁平面列表,最多为6个定义裁剪平面;该参数功能等同于SV_ClipDistance(特性层次高于9_x)
  • Return_Value: 返回值
  • Name:函数名
  • ArgumentList:参数列表
  • Semantic:返回值的语义(见上一节)
  • StatementBlock:函数块

示例:

struct VS_OUTPUT
{
    float4 Position   : SV_POSITION; 
    float4 Diffuse    : COLOR0;
    float2 TextureUV  : TEXCOORD0;
};

VS_OUTPUT RenderSceneVS( float4 vPos : POSITION,
                         float3 vNormal : NORMAL,
                         float2 vTexCoord0 : TEXCOORD,
                         uniform int nNumLights,
                         uniform bool bTexture,
                         uniform bool bAnimate )
{
    VS_OUTPUT Output;
    ...
    return Output;    
}
3.2 函数参数

参数形式如下:

[InputModifier] Type Name [: Semantic] [InterpolationModifier] [= Initializers]

参数说明:

  • InputModifier:可选参数,定义参数为输入、输出或两者皆是。 in为输入,out为输出,inout为输入输出,uniform为常量输入。不填时参数默认为in,被定义成uniform可视为全局变量,对于非顶层函数,uniform与in同义。
  • Type:参数类型
  • Name:参数名称
  • Semantic :参数语义
  • InterpolationModifier:插值修改器,用于定义着色器的插值函数,应用于函数参数时,仅用像素着色器函数输入参数
  • Initializers:初始值

示例:

VS_OUTPUT RenderSceneVS( 
  float4 vPos : POSITION,
  float3 vNormal : NORMAL,
  float2 vTexCoord0 : TEXCOORD,
  uniform int nNumLights,
  uniform bool bTexture,
  uniform bool bAnimate )
{
  ...
}
3.3 返回值

参数形式如下:

return [value];

参数说明:返回值可为一个或多个值

示例:

float4x4 WorldViewProj;

struct VS_OUTPUT
{
    float4 Pos  : POSITION;
};

VS_OUTPUT VertexShader_Tutorial_1(float4 inPos : POSITION )
{
    VS_OUTPUT out;
    out.Pos = mul(inPos, WorldViewProj );
    return out;
};

float4 func(float2 a: POSITION): COLOR
{
    return float4(sin(length(a) * 100.0) * 0.5 + 0.5, sin(a.y * 50.0), 0, 1);
}
3.4 签名

着色器签名是着色器函数输入或输出的一个参数列表(通过语义来实现),输入签名由着色器输入声明产生,输出签名由着色器输出声明产生,若输出签名为输入签名的子集(声明类型及顺序相同),则称输入签名兼容输出签名。最简单的兼容方式便是让着色器的输入输出为相同结构体。

示例一:可兼容签名(官方给出的例子是输入签名输出签名的子集,官方给出的上面定义应该是写错了

// Vertex Shader Output Signature
Struct VSOut
{
  float4 Pos: SV_Position;
  float3 MyNormal: Normal;
  float2 MyTex : Texcoord0;
}

// Pixel Shader Input Signature
Struct PSInWorks
{
  float4 Pos: SV_Position;
  float3 MyNormal: Normal;
}

示例二:非兼容签名

// Vertex Shader Output Signature
Struct VSOut
{
  float4 Pos: SV_Position;
  float3 MyNormal: Normal;
  float2 MyTex : Texcoord0;
}

// Pixel Shader Input Signature
Struct PSInFails
{
  float3 MyNormal: Normal;
  float4 Pos: SV_Position;
}

4 流程控制语句

HLSL的流程控制语句与C语言基本相似,支持以下流程控制语句:

  • break
  • continue
  • discard
  • do
  • for
  • if
  • switch
  • while

比较特殊的流程控制语句仅为discard语句:

  • 功能:当前结果不输出至当前像素点。

  • 备注:该语句只能像素着色器调用,不能被几何着色器或顶点着色器调用。

参考

  • 3
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值