没有合适的资源?快使用搜索试试~ 我知道了~
首页HLSL(微软高级着色语言)初级教程
资源详情
资源评论
资源推荐

HLSL 初级教程
作者:trcj
目录
前言
1.HLSL 入门
1.1 什么是着色器
1.2 什么是 HLSL
1.3 怎么写 HLSL 着色器
1.4 怎么用 HLSL 着色器
2.顶点着色器
2.1 可编程数据流模型
2.2 顶点声明
2.3 用顶点着色器实现渐变动画
3.像素着色器
3.1 多纹理化
3.2 多纹理效果的像素着色器
3.3 应用程序
4.HLSL Effect(效果框架)
4.1Effect 代码结构
4.2 用 Effect 实现多纹理化效果
结语
参考资料
前言
本教程针对 HLSL(High Level Shading Language)初学者,从应用的角度对
HLSL、顶点着色器、像素着色器和 Effect 效果框架进行了介绍,教程中去掉了
对 HLSL 语法等一些细节内容的讨论,力求帮助读者尽可能快地理解 HLSL 编程
的概念,掌握 HLSL 编程的方法。
教程中部分阐述直接引用了其他文档,这是因为这些文档表述之精要,已经
达到了不能更改的地步,这里表示感谢。
本文档版权为作者所有,非商业用途可免费使用,转载请注明出处。
1.HLSL 入门
1.1 什么是着色器
DirectX 使用管道技术(pipeline)进行图形渲染,其构架如下:

图 1.1 Direct3D Graphics Pipeline
之前我们使用管道的步骤如下:
1. 设定顶点、图元、纹理等数据信息;
2.
设定管道状态信息;
渲染状态
通过 SetRenderState 方法设定渲染状态;
另外,使用以下方法设置变换、材质和光照:
SetTransform
SetMaterial
SetLight
LightEnable
取样器状态
通过 SetSamplerState 方法设定取样器状态;
纹理层状态
通过 SetTextureStageState 设定纹理层状态;
3. 渲染;
这部分交由 D3D 管道按照之前的设定自行完成,这部分操作是 D3D 预
先固定的,所以这种管道技术被称为固定功能管道(fixed function pipeline);
固定功能管道给我们编程提供了一定的灵活性,但是仍有很多效果难以通过
这种方式实现,比如:
1.
在渲染过程中,我们要求 y 坐标值大于 10 的顶点要被绘制到坐标值(0,
0,0)的地方,在之前的固定功能管道中,顶点被绘制的位置是在第 1
步即被设定好的,不可能在渲染过程中进行改变,所以是不可行的;
2. 谋顶点在纹理贴图 1 上映射为点 A,在纹理贴图 2 上映射为点 B,我们
要求该顶点颜色由 A、B 共同决定,即:
定点颜色 = A 点色彩值*0.7 + B 点色彩值*0.3
这在固定管道编程中也是不可行的。
以上两个问题都可以由可编程管道(pragrammable pipeline)来解决。
可编程管线允许用户自定义一段可以在 GPU 上执行的程序,代替固定管道
技术中的 Vertex Processing 和 Pixel Processing 阶段(参照图 1.1),从而在使我
们在编程中达到更大的灵活性。其中替换 Vertex Processing 的部分叫做 Vertex
Shader(顶点着色器),替换 Pixel Proccessing 的部分叫做 Pixel Shader(像素着
色器),这就是我们所说的着色器 Shader。

1.2 什么是 HLSL
Direct8.x 中,着色器是通过低级着色汇编语言来编写的,这样的程序更像是
汇编式的指令集合,由于其效率低、可读性差、版本限制等缺点,迫切要求出现
一门更高级的着色语言。到了 Direct3D9,HLSL(High Level Shading Language,高级
渲染语言)应运而生了。
HLSL 的语法非常类似于 C 和 C++,学习起来是很方便的。
1.3 怎么写 HLSL 着色器
我们可以直接把 HLSL 着色器代码作为一长串字符串编写进我们的应用程序
源文件中,但是,更加方便和模块化的方法是把着色器的代码从应用程序代码中
分离出来。因此,我们将着色器代码单独保存为文本格式,然后在应用程序中使
用特定函数将其加载进来。
下面是一个完整的 HLSL 着色器程序代码,我们把它保存在 BasicHLSL.txt
中。该着色器完成顶点的世界变换、观察变换和投影变幻,并将顶点颜色设定为
指定的颜色。
//
// BasicHLSL.txt
//
//
// Global variable
//
matrix WVPMatrix;
vector color;
//
// Structures
//
struct VS_INPUT
{
vector position : POSITION;
};
struct VS_OUTPUT
{
vector position : POSITION;
vector color : COLOR;
};
//
// Functions

//
VS_OUTPUT SetColor(VS_INPUT input)
{
VS_OUTPUT output = (VS_OUTPUT)0;
output.position = mul(input.position, WVPMatrix);
output.color = color;
return output;
}
下面就针对上述代码讲解一下 HLSL 着色器程序的编写:
1.3.1 全局变量
代码中声明了两个全局变量:
matrix WVPMatrix;
vector color;
变量 WVPMatrix 是一个矩阵类型,它包含了世界、观察、投影的合矩阵,
用于对顶点进行坐标变换;
变量 color 是一个向量类型,它用于设定顶点颜色;
代码中并没有对全局变量进行初始化,这是因为我们对全局变量的初始化过
程将在应用程序中进行,全局变量在应用程序中赋值而在着色器程序中使用,这
是应用程序和着色器通信的关键所在。具体赋值过程将在后续部分讲述。
1.3.2 输入输出
输入输出结构
程序中定义了两个输入输出结构 VS_INPUT 和 VS_OUTPUT
struct VS_INPUT
{
vector position : POSITION;
};
struct VS_OUTPUT
{
vector position : POSITION;
vector color : COLOR;
};
自定义的结构可以采用任意名称,结构不过是一种组织数据的方式,并不是
强制的,你也可以不使用,而将本程序的输入改为:
vector position : POSITION;
标志符
用于输入输出的变量采用用一种特殊的声明方式:
Type VariableName : Semantic

这个特殊的冒号语法表示一个语义,冒号后面的标志符用来指定变量的用
途,如
vector position : POSITION;
其中,POSITION 标志符表明该变量表示顶点位置,另外还有诸如 COLOR、
NORMAL 等很多表示其他意义的标志符。
本节所说的输入输出其实是指着色器代码和编译器、GPU 之间的通信,和应
用程序是无关的,所以这些变量不需要在应用程序中进行赋值,标志符告诉
编译器各个输入输出变量的用途(顶点位置、法线、颜色等),这是着色器
代码和编译器、GPU 之间通信的关键。
1.3.3 入口函数
程序中还定义了一个函数 SetColor:
OUTPUT SetColor(INPUT input)
{
VS_OUTPUT output = (VS_OUTPUT)0;
output.position = mul(input.position, WVPMatrix);
output.color = color;
return output;
}
1. 该函数以 input 和 output 类型作为输入输出;
2. 使全局变量 WVPMatrix 和 input.position 相乘,以完成顶点的世界、观察、
投影变换,并把结果赋值到 output.position;
output.position = mul(input.position, WVPMatrix);
3. 将全局变量 color 的值赋给 output.color;
output.color = color;
4.
在同一个着色器代码文件中,可以有多个用户自定义函数,因此在应用
程序中需要指定一个入口函数,相当于 windows 程序的 WinMain 函数,
本程序只包含 SetColor 一个函数而且它将被做为入口函数使用。
1.3.4 总结
至此,一个 HLSL 着色器编写完毕,渲染过程中,当一个顶点被送到着色器
时:
1. 全局变量 WVPMatrix、color 将在应用程序中被赋值;
2. 入口函数 SetColor 被调用编译器根据标志符将顶点信息填充到
VS_INPUT 中的各个字段;
3. SetColor 函数中,首先定义一个 VS_OUTPUT 信息,之后根据
WVPMatrix 和 color 变量完成顶点的坐标变换和颜色设定操作,最后
函数返回 VS_OUTPUT 结构;
4. 编译器将会再次根据标志符把返回的 VS_OUTPUT 结构中的各字段
映射为顶点相应的信息。
5. 顶点被送往下一个流程接受进一步处理。
剩余36页未读,继续阅读
















安全验证
文档复制为VIP权益,开通VIP直接复制

评论2