05/30/2020
06/13/2020 HLSL 数学库
HLSL 语法
HLSL
HLSL是一个着色器语言,独立于WIndows平台,只能供微软Direct3D使用。HLSL不能与OpenGL抗衡,用来抗衡GLSL产品1
HLSL代码
hlsli声明文件
//.hlsli 声明文件可以写到hlsli文件中,不进行编译
//HLSL结构体进行声明
struct VertexIn
{
float3 pos:POSITION; //描述坐标系
float4 color:COLOR; //描述颜色
};
struct VertexOut
{
float4 posH:SV_POSITION; //说明改顶点的位置从顶点着色器输出后,后续不能改变它了
float4 color:COLOR;
};
//常量缓冲区
//cbuffer 用于声明一个常量缓冲区
//matrix 等于float4*4
//HLSL默认为列主矩阵
//register(b0)该常量缓冲区位于寄存器索引为0的缓冲区
cbuffer ConstantBuffer:register(b0)
{
matrix gWorld;
matrix gView;
matrix gProjection;
}
顶点着色器
#include "Triangle.hlsli"
//返回值,与参数在hlsli声明过了
//VS 函数名表示入口函数名
VertexOut VS(VertexIn vIn)
{
VertexOut vOut;
vOut.posH = float4(vIn.pos,1.0f);
vOut.color = vIn.color;
return vOut;
}
像素着色器
#include "Triangle.hlsli"
float4 PS(vertexOut pIn):SV_Target //SV_Target 说明输出的颜色将会直接保存到渲染目标视图的后备缓冲区对应位置
{
return pIn.color; //pIn的值由 顶点着色器传递而来
}
HLSL数学库
向量与矩阵相乘或者矩阵之间相乘(mul函数)
matrix g_View; //matrix 数据类型 是 4x4矩阵
matrix g_Proj;
matrix viewProj = mul(g_View,g_Proj); //矩阵之间的相乘
float4 PosL;
float4 PosW = mul(PosL,viewProj); //向量与矩阵的相乘
- 用于矩阵相乘和向量变换等问题
- matrix 和 float4x4 是一样的,但是用的是列主序矩阵
- 可以使用row_major 强行把列主序矩阵转为行主序矩阵
(row_major) matrix g_View;
规矩
- 行向量×行主序向量
- 列主序向量×列向量
- matrix 中列主序矩阵会发生转置
但是由于汇编dp4运算可以直接取列主序矩阵的行,从而避免大量转置,所以可以采用行向量×列主序向量
- C++代码端不进行转置,HLSL中使用row_major matrix(行主序矩阵),mul函数让向量放在左边(行向量),这样实际运算就是(行向量 X 行主序矩阵) 。这种方法易于理解,但是这样做dp4运算取矩阵的列很不方便,在HLSL中会产生用于转置矩阵的大量指令,性能上有损失。
- **C++代码端进行转置,HLSL中使用matrix(列主序矩阵) ,mul函数让向量放在左边(行向量),这样就是(行向量 X 列主序矩阵),但C++这边需要进行一次矩阵转置,HLSL内部不产生转置 。**这是官方例程所使用的方式,这样可以使得dp4运算可以直接取列主序矩阵的行,从而避免内部产生大量的转置指令。后续我会将教程的项目也使用这种方式。
- **C++代码端不进行转置,HLSL中使用matrix(列主序矩阵),mul函数让向量放在右边(列向量),**实际运算是(列主序矩阵 X 列向量)。这种方法的确可行,取列矩阵的行也比较方便,效率上又和2等同,就是HLSL那边的矩阵乘法都要反过来写,然而DX本身就是崇尚行主矩阵的,把OpenGL的习惯带来这边有点。。。
- C++代码端进行转置,HLSL中使用row_major matrix(行主序矩阵),mul函数让向量放在右边(列向量),实际运算是(行主序矩阵 X 列向量)。 就算这种方法也可以绘制出来,但还是很让人难受,比第2点还难受,我甚至不想去说它。
float4,float3,float2与C++的结构体相似
//float4 有4个分量,每个分量是float型的
float4 posL;
float temp = posL.x * posL.y * posL.z * posL.w;
//C++ 中
struct float4
{
float x;
float y;
float z;
float w;
};
分量乘法(*)
float3 color1;
float3 color2;
float3 blend = color1 * color2; // blend.x = color1.x * color2.x;
- 可以用于灯光,颜色混合,纹理颜色混合等等