HLSL
+ -

HLSL重点知识梳理

2024-11-21 23 0

本文源于对DirectX11—HLSL语法入门(https://www.cnblogs.com/X-Jun/p/12246859.html ) 一文的总结

浮点

类型 描述
bool 32位整数值用于存放逻辑值true和false
int 32位有符号整数
uint 32位无符号整数
half 16位浮点数(仅提供用于向后兼容)
float 32位浮点数
double 64位浮点数

注意:一些平台可能不支持int, half和double,如果出现这些情况将会使用float来模拟

此外,浮点数还有规格化的形式:

  • snorm float是IEEE 32位有符号且规格化的浮点数,表示范围为-1到1
  • unorm float是IEEE 32位无符号且规格化的浮点数,表示范围为0到1

语义

语义通常是附加在着色器输入/输出参数上的字符串。它在着色器程序的用途如下:

  • 用于描述传递给着色器程序的变量参数的含义
  • 允许着色器程序接受由渲染管线生成的特殊系统值
  • 允许着色器程序传递由渲染管线解释的特殊系统值

语义有三种类型:顶点着色器语义,像素着色器语义和系统着色器语义

顶点着色器语义

输入 描述 类型
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
Output 仅描述输出 Type
FOG 顶点雾 float

n是一个可选的整数,从0开始。比如POSITION0, TEXCOORD1等等。

像素着色器语义

输入 描述 类型
COLOR[n] 漫反射/镜面反射颜色 float4
TEXCOORD[n] 纹理坐标 float4
Output 仅描述输出 Type
DEPTH[n] 深度值 float

系统值语义

所有的系统值都包含前缀SV_。这些系统值将用于某些着色器的特定用途(并未全部列出)

系统值 描述 类型
SV_Depth 深度缓冲区数据,可以被任何着色器写入/读取 float
SV_InstanceID 每个实例都会在运行期间自动生成一个ID。在任何着色器阶段都能读取 uint
SV_IsFrontFace 指定该三角形是否为正面。可以被几何着色器写入,以及可以被像素着色器读取 bool
SV_Position 若被声明用于输入到着色器,它描述的是像素位置,在所有着色器中都可用,可能会有0.5的偏移值 float4
SV_PrimitiveID 每个原始拓扑都会在运行期间自动生成一个ID。可用在几何/像素着色器中写入,也可以在像素/几何/外壳/域着色器中读取 uint
SV_StencilRef 代表当前像素着色器的模板引用值。只可以被像素着色器写入 uint
SV_VertexID 每个实例都会在运行期间自动生成一个ID。仅允许作为顶点着色器的输入 uint

常量缓冲区

着色器常量存在内存中的一个或多个缓冲区资源当中。他们可以被组织成两种类型的缓冲区:常量缓冲区(cbuffers)和纹理缓冲区(tbuffers)。

不同的常量缓冲区使用不同的常量缓冲区声明。如常量缓冲区使用cbuffers

cbuffer VSConstants
{
    float4x4 g_WorldViewProj;
    fioat3 g_Color;
    uint g_EnableFog;
    float2 g_ViewportXY;
    float2 g_ViewportWH;
}

为了进一步优化,可以为常量缓冲区在HLSL的声明中使用关键字register手动指定对应的寄存器索引,然后编译器会为对应的着色器阶段自动将其映射到15个常量缓冲寄存器的其中一个位置。这些寄存器的名字为b0到b14:

cbuffer VSConstants : register(b0)
{
    float4x4 g_WorldViewProj;
    fioat3 g_Color;
    uint g_EnableFog;
    float2 g_ViewportXY;
    float2 g_ViewportWH;
}

在C++端是通过ID3D11DeviceContext::*SSetConstantBuffers指定特定的槽(slot)来给某一着色器阶段对应的寄存器索引提供常量缓冲区的数据。

如果是存在多个不同的着色器阶段使用同一个常量缓冲区,那就需要分别给这两个着色器阶段设置好相同的数据。

综合前面几节内容,下面演示了顶点着色器和常量缓冲区的用法:

cbuffer ConstantBuffer : register(b0)
{
    float4x4 g_WorldViewProj;
}


void VS_Main(
    in float4 inPos : POSITION,         //POSITION语义:绑定变量到输入装配器
    in uint VID : SV_VertexID,          // SV_VertexID语义:绑定变量到系统生成值
    out float4 outPos : SV_Position)    // SV_Position语义:告诉管线将该值解释为输出的顶点位置
{
    outPos = mul(inPos, g_WorldViewProj);
}
`

上面的代码也可以写成:

cbuffer ConstantBuffer : register(b0)
{
    float4x4 g_WorldViewProj;
}

struct VertexIn
{
    float4 inPos : POSITION;    // 源自输入装配器
    uint VID : SV_VertexID;        // 源自系统生成的调用实例ID
};

float4 VS_Main(VertexIn vIn) : SV_Position
{
    return mul(vIn.inPos, g_WorldViewProj);//默认返回值为输出顶点位置
}

0 篇笔记 写笔记

作者信息
站长漫谈
取消
感谢您的支持,我会继续努力的!
扫码支持
扫码打赏,你说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦

您的支持,是我们前进的动力!