前言
dx12的渲染流水线如下,基本上起一个流水线的输出等于下一个流水线的输入
阶段名字 | 可编程内容 |
---|---|
输入装配器阶段 IA | 输入顶点、索引、拓扑结构 |
顶点着色器阶段 VS | 修改顶点数据,例如坐标转换 |
(可选)外壳着色器阶段 HS | 常量外壳着色器:输出曲面细分因子 |
(可选)外壳着色器阶段 HS | 控制点外壳着色器:设置曲面细分的参数 |
(可选)镶嵌化阶段 | 不可编程 |
(可选)域着色器阶段 DS | 和没有开曲面细分的VS一样 |
(可选)几何着色器阶段 GS | 顶点的修改,可以添加删除 |
光栅化阶段 RS | 通过流水线的参数控制部分行为,背面剔除 |
像素着色器阶段 PS | 像素点的颜色控制 |
输出合并阶段 OM | 写入后台缓冲去,深度/模板测试,混合 |
曲面细分就包含3个阶段
- 外壳着色器
- 镶嵌化
- 域着色器
搞清楚这3个着色器的作用,就可以了。其他的就是一些流水线设置、IA的拓扑设置改下就可以了
常量外壳着色器
本着色器,必须输出的就是曲面细分因子,可以根据需要自己调整
// VS输出的顶点结构
struct VS_CONTROL_POINT_OUTPUT
{
float3 vPosition : POSITION; // 面片的顶点(模型坐标系顶点)
};
// 常量外壳着色器的输出结构,曲面细分因子
struct HS_CONSTANT_DATA_OUTPUT
{
float EdgeTessFactor[4] : SV_TessFactor; // 例如,对于四象限域,将为 [4]
float InsideTessFactor[2] : SV_InsideTessFactor; // 例如,对于四象限域,将为 Inside[2]
};
// 4个控制点的面片,也就是VS输出了4个顶点
#define NUM_CONTROL_POINTS 4
// 修补程序常量函数
HS_CONSTANT_DATA_OUTPUT CalcHSPatchConstants(
InputPatch<VS_CONTROL_POINT_OUTPUT, NUM_CONTROL_POINTS> ip, // VS输出的顶点数组
uint PatchID : SV_PrimitiveID) // 面片ID
{
HS_CONSTANT_DATA_OUTPUT Output;
// 在此处插入代码以计算输出
Output.EdgeTessFactor[0] =
Output.EdgeTessFactor[1] =
Output.EdgeTessFactor[2] =
Output.EdgeTessFactor[3] =
Output.InsideTessFactor[0] =
Output.InsideTessFactor[1] = 25; // 例如,可改为计算动态分割因子
return Output;
}
控制点外壳着色器
[domain("quad")] // 四边形面片
[partitioning("integer")] // 细分模式 fractional_even fractional_odd
[outputtopology("triangle_cw")] // 通过细分创建的三角形顶点序
[outputcontrolpoints(16)] // 输出16个顶点
[patchconstantfunc("CalcHSPatchConstants")] // 常量外壳着色器函数名
HS_CONTROL_POINT_OUTPUT main(
InputPatch<VS_CONTROL_POINT_OUTPUT, NUM_CONTROL_POINTS> ip, // VS输出的顶点数组
uint i : SV_OutputControlPointID, // 向外输出的点的ID
uint PatchID : SV_PrimitiveID ) // 面片ID
{
HS_CONTROL_POINT_OUTPUT Output;
// 可以根据需要修改顶点的坐标,每个输出点都会调用一次。
Output.vPosition = ip[i].vPosition;
return Output;
}
域着色器
[domain("quad")]
DS_OUTPUT main(
HS_CONSTANT_DATA_OUTPUT input, // 曲面细分因子
float2 domain : SV_DomainLocation, // 新插入顶点的uv坐标(基于面片内部)
const OutputPatch<HS_CONTROL_POINT_OUTPUT, NUM_CONTROL_POINTS> patch) // 原始面片的N个点
{
DS_OUTPUT Output;
...
return Output;
}
对于曲面细分之后的每一个顶点都会执行一次域着色器。其中那个uv坐标是基于面片内部的。
patch包含所有细分之后的顶点。
操作起来就跟VS一样。可以修改顶点的位置,法向量等等。
看下龙书的结果
本章内容还是比较简单的,渲染对象什么的,自行添加就好。注意PSO以及IA阶段设置拓扑结构为面片。
直接来看下本章的内容: