下面对微软所给的HLSL官方文档进行简单梳理,将其基本语法总结如下。
用法:Buffer
示例:Buffer
说明:Type可以为标量、向量或一些矩阵类型
bool:布尔值,true或false。
int: 32位有符号整型。
uint: 32位无符号整型。
dword: 32位无符号整型。
half: 16位浮点型。该类型只是为了保持语言兼容性,Direct3D 10将所有half都映射为float型,该类型不能用作标准全局变量。
float:32位浮点型。
用法:TypeNumber Name 或 vector <Type, Number> VariableName
示例:
bool bVector; // scalar containing 1 Boolean
int1 iVector = 1;
float3 fVector = { 0.2f, 0.3f, 0.4f };
vector <int, 1> iVector = 1;
vector <double, 4> dVector = { 0.2, 0.3, 0.4, 0.5 };
用法:TypeNumberxNumber Name 或 matrix <Type, Number> VariableName
示例:
int1x1 iMatrix; // integer matrix with 1 row, 1 column
int4x1 iMatrix; // integer matrix with 4 rows, 1 column
int1x4 iMatrix; // integer matrix with 1 row, 4 columns
double3x3 dMatrix; // double matrix with 3 rows, 3 columns
float2x2 fMatrix = { 0.0f, 0.1, // row 1
2.1f, 2.2f // row 2
};
matrix <float, 2, 2> fMatrix = { 0.0f, 0.1, // row 1
2.1f, 2.2f // row 2
};
Direct3D 9:
sampler Name = SamplerType{ Texture = <texture_variable>; [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:可选状态设置,所有状态赋值必须出现在状态块中(大括号中),由分号分隔。
用法:
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
用法: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;
用法:
struct struct2
{
int a;
float b;
int4x4 iMatrix;
}
访问方式与C语言类似,通过.来访问。
用法: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;
输入 | 描述 | 类型 |
---|---|---|
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 |
输入 | 描述 | 类型 |
---|---|---|
COLOR[n] | 固有色与高光色 | float4 |
TEXCOORD[n] | 纹理坐标 | float4 |
VFACE | 用于标记一个背面图元的浮点标量值,负值表示面向背面,正值表示面向相机,该语义仅在Direct3D 9的Shader Model 3.0中可用,Direct3D 10以后使用SV_IsFrontFace替代 | float |
VPOS | 屏幕空间像素位置(x,y). 该语义用于Direct3D 9,之后版本请使用SV_Position | float2 |
输出 | 描述 | 类型 |
---|---|---|
COLOR[n] | 输出颜色 | float4 |
DEPTH[n] | 输出深度 | float |
Direct3D 10语义 | Direct3D 9等价语义 |
---|---|
SV_Depth | DEPTH |
SV_Position | POSITION |
SV_Target | COLOR |
套用《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
}
}
}
在DX10版本之前没有引入SV_的预定义语义,POSITION被用作vertex shader的输入和输出,fragment shader的输入参数。但DX10之后就推荐使用SV_POSITION作为vertex shader的输出和fragment shader的输入,**注意vertex shader的输入还是使用POSITION!** **不过,DX10以后的代码依旧兼容POSITION作为全程表达。**
HLSL的函数定义与C语言也基本类型,形式如下:
[StorageClass] [clipplanes()] [precise] 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;
}
参数形式如下:
[InputModifier] 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 )
{
...
}
参数形式如下:
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);
}
着色器签名是着色器函数输入或输出的一个参数列表(通过语义来实现),输入签名由着色器输入声明产生,输出签名由着色器输出声明产生,若输出签名为输入签名的子集(声明类型及顺序相同),则称输入签名兼容输出签名。最简单的兼容方式便是让着色器的输入输出为相同结构体。
示例一:可兼容签名(官方给出的例子是输入签名输出签名的子集,官方给出的上面定义应该是写错了)
// 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;
}
HLSL的流程控制语句与C语言基本相似,支持以下流程控制语句:
比较特殊的流程控制语句仅为discard语句:
功能:当前结果不输出至当前像素点。
备注:该语句只能像素着色器调用,不能被几何着色器或顶点着色器调用。