《Practical Rendering & Computation with Direct3D11》读书总结 Chapter-4-The Tessellation Pipeline

在前一章中有介绍到Tessellation的三个阶段:Hull Shader、Tessellation、Domain Shader,但是有一些细节是没有讲到的,这一章更加详细的讲述了跟Tessellation有关的内容。

Introduction

表示一个参数曲面的方式通常有两种:NURBS和SubDivisionSurfaces,前者是以数学的形式表达的曲面,具有很好的光滑性;而后者则通过不断增加模型中的三角形的数量,以更好地表达理想的曲面,它不需要数学理论基础。对于NURBS之类的基于数学的参数曲面来说,只需要存储一些表达式中的系数以及输入就足够表达曲面了,而对于曲面细分,就需要存储所有顶点的各项数据,它的存储需求是要高很多的。那么为什么曲面细分还是如此的有用呢?因为对于实时渲染应用来说,这些参数曲面没有办法预处理它的系数,因为它的采样点是需要实时获取的,如果参数曲面的阶数非常高,这个采样以及系数的计算就十分地复杂,非常耗费性能。而对于细分曲面来说,它的基本的网格都是可以提前定义好存储在文件中的,用的时候只需要读取就行了,而如果要进行细分操作,它的计算量也没有参数曲面那么大,因此使用细分曲面更加的简便高效。

Tessellation and the Direct3D Pipeline

Tessellation在流水线中是一个可选的阶段,那么如果要用到它,流水线中的每个阶段需要相应地做一些调整。

Input Assembler:回顾一下,IA阶段需要配置三个东西:InputLayout、Vertex/Index Buffer、Primitive Topology,由于曲面细分阶段用到的是控制点,因此IA的Primitive Topology应该指定为D3D11_PRIMITIVE_TOPOLOGY_n_CONTROL_POINT_PATCHLIST,其中n是1~32内的整数。

Vertex Shader:由于Vertex Shader不再直接与Rasterizer直接相连,它输出的结构体中并不需要包含SV_POSITION语义,并且它的其他成员可以是在任意空间下的,只要符合后续流水线操作的需求就行了。不过需要注意,在Vertex Shader之后,Vertex Buffer中的信息是再也没有办法被获取到的,Vertex Shader输出的信息一定要足够覆盖后续操作所需要的全部需求。

Hull Shader:前一章提到了,Hull Shader要完成两项任务:逐Patch地运行Constant Function以计算每个Patch的SV_TessFactor和SV_InsideTessFactor,Constant Function的输出大小被限制在128 Scalars以内(32个float4类型);逐控制点地运行Hull Shader Function来计算输出控制点,输出控制点的个数可以与输入控制点的个数不同,Hull Shader Function可以充分利用一个Patch中的所有输入控制点的信息来计算输出控制点,输出控制点的个数由HLSL代码中的参数指定,它的输出被限定在3968 Scalars以内,表示如果要输出32个控制点,那么每个控制点的成员数据的大小不能超过31个float4类型的大小。

Fixed-Function Tessellator:利用Hull Shader Constant Function计算的两个参数在Domain的范围内做细分,生成新的顶点的DomainLocation,这一阶段不会用到控制点的任何信息,即与Hull Shader Function无关。它所使用的Domain由HLSL中的参数指定。

Domain Shader:由Hull Shader提供的控制点以及Tesselation得到的Domain Location来计算生成的顶点的信息,生成的顶点必须要包含SV_Position语义(严格的来说这个语义也可以由Geometry Shader来完成,但是在Geometry Shader中做效率较低下)。

Geometry Shader:它的运行过程原则上是不变的,但是由于如果做了曲面细分的话,Primitive的数量是会变化的,而Geometry Shader是逐Primitive运行的,如果没有曲面细分,它的运行次数就由Application的Draw的参数决定,而如果用到了曲面细分,它的运行次数就与Hull Shader Constant Function的两个结果有关,更为复杂的,如果还用到了LOD技术,这个运行次数就会更加地难以知晓。因此如果用到了曲面细分,那么它的运行次数其实就是不好掌控的。

Rasterization和Pixel Shader:保持不变。

Parameters for Tessellation

Tessellation的参数是Hull Shader Constant Functino计算得到的两个结果,代表着细分生成的点到边和内部的一个距离,但是可以注意到,这两个参数的结果都是数组类型的,也就是说每个Patch的SV_TessFactor和SV_InsideTessFactor都有可能是多个的,那么具体要有多少个呢,这个多个又意味着什么呢?
它们的个数其实取决于Tessellation的Domain,Domain的取值有三种:Line、Triangle、Quad。
对于Line来说,它的SV_TessFactor需要2个,SV_InsideTessFactor没有意义,不需要。
对于Triangle来说,它的SV_TessFactor需要3个,SV_InsideTessFactor需要1个。
对于Quad来说,它的SV_TessFactor需要4个,SV_InsideTessFactor需要2个。
SV_TessFactor的个数就相当于边的个数,而对于Line来说有些特殊,因为它没有构成面,它的这SV_TessFactor可以认为是相对于它的两个端点而言。
SV_InsideTessFactor表示相对于内部的距离,Line不构成面就谈不上内部了,对于Triangle它的内部也很好理解,而对于Quad为什么需要两个SV_InsideTessFactor呢?这是因为如果说要靠近一个Quad的内部,其实是有两种方式的,假设一个相邻的两个Quad的边分别为a,b,那么靠近内部既有可能是沿着a靠近,也有可能是沿着b靠近,那么这两个SV_InsideTessFactor就分别对应这两种情况。
对于大多数情况来说,SV_TessFactor和SV_InsideTessFactor的具体的值是自行编程计算的,而Shader model 5.0提供了一些函数来帮助确定它们的值。
这里写图片描述

猜你喜欢

转载自blog.csdn.net/yjr3426619/article/details/81285933