原文:Directx11教程(59) tessellation学习(1)

      在D3D11管线中,新增加了3个stage, Hull shader, Tessellator, Domain shader,用来实现细分操作,就是在gpu中把低细节的表面细分成高细节的体元。在gpu中把低模通过tessellation转化为高模,在获得高细节模型的同时,可以有效降低把顶点数据从system memory传到 video memory的带宽消耗。

     下面我们看看这三个阶段到底做些什么,输入是什么,输出是什么?先画一张图。

1、Hull shader阶段

      Hull shader阶段可以分成两个独立的阶段,它们是并行执行的。

      第一个阶段是per control points执行的, 在这个阶段对patch中的每个控制点,输出对应的控制点。所谓patch,简单理解就是带控制点的体元,比如一个三角形,它的三个顶点是控制点,那么这个三角形就是有3个控制点的patch。当然,在Hull shader中,我们还可以对输入的控制点进行转化操作,生成新的控制点,比如输入的3个控制点,输出6个控制点。注意:输入或者输出的控制点数量是1~32。

     第二个阶段就是patch常量阶段,这时HullShader会调用一个const data函数,这个函数主要产生tessellation factor,这些factor决定在TS阶段如何细分当前的patch。

    另外,在Hullshader阶段还会指定一些TS阶段使用的Tessellation模式,比如细分的patch是三角形(拓扑模式),partition mode(选择什么细分算法)是HS_PARTITION等。

下面看一段Hull shader的代码:

struct HullInputType

{

float3 position : POSITION;

float4 color : COLOR;

};

struct ConstantOutputType

{

float edges[3] : SV_TessFactor;

float inside : SV_InsideTessFactor;

};

struct HullOutputType

{

float3 position : POSITION;

float4 color : COLOR;

};

// Patch 常量函数,决定tessellation因子,每个patch执行一次,所以是per patch的,不是per控制点的

ConstantOutputType ColorPatchConstantFunction(InputPatch<HullInputType, 3> inputPatch, uint patchId : SV_PrimitiveID)

{

ConstantOutputType output;

//设置三条边的细分因子

output.edges[0] = tessellationAmount;

output.edges[1] = tessellationAmount;

output.edges[2] = tessellationAmount;

//设置三角形内的细分因子

output.inside = tessellationAmount;

return output;

}

//注意输入控制点数量要和 IASetPrimitiveTopology()函数中一致

//本例子中,都为3 INPUT_PATCH_SIZE

// The hull shader is called once per output control point, which is specified with

// outputcontrolpoints. For this sample, we take the control points from the vertex

// shader and pass them directly off to the domain shader. In a more complex scene,

// you might perform a basis conversion from the input control points into a Bezier

// patch, such as the SubD11 Sample of DirectX SDK.

// The input to the hull shader comes from the vertex shader

// The output from the hull shader will go to the domain shader.

// The tessellation factor, topology, and partition mode will go to the fixed function

// tessellator stage to calculate the UVW and domain points

[domain("tri")] //Triangle domain for our shader

[partitioning("integer")] //Partitioning type according to the GUI

[outputtopology("triangle_cw")] //Where the generated triangles should face

[outputcontrolpoints(3)] //Number of times this part of the hull shader will be called for each patch

[patchconstantfunc("ColorPatchConstantFunction")] //The constant hull shader function

HullOutputType ColorHullShader(InputPatch<HullInputType, 3> patch, uint pointId : SV_OutputControlPointID, uint patchId : SV_PrimitiveID)

{

HullOutputType output;

//设置控制点

output.position = patch[pointId].position;

// 输出颜色为输入颜色

output.color = patch[pointId].color;

return output;

}

2. Tessellator阶段

       Tessellator是一个固定管线阶段,它的主要功能就是细分一个domain(三角形, 四边形或线),把它们细分成很多小的物体,比如三角形,四边形或者线。

       在细分时,tessellator会在一个归一化的坐标系统中处理patch,比如输入是一个quad(四边形),但这个quad先要映射到一个单位为1的正方形上,然后tessellator会对这个正方形进行细分操作。

      Tessellator是per patch操作的,Hull shader阶段传入的Tess Factor决定细分多少次,而Hull shader阶段传入的partitioning则决定选用何种细分算法。Tessellator输出为u,v, {w}坐标以及细分后domain的拓扑信息。

3. Domain Shader阶段

       Domain Shader 阶段会根据TS阶段生成的u,v , {w}坐标以及HS阶段传入的控制点在patch中生成细分后顶点的位置。

       Domain shader是per vertex的,对于TS中每个细分产生的顶点,它都要调用一次。它的输入参数除了u,v,{w}坐标及控制点以外,还有const data,比如Tess factor等。

下面是一段Domain shader的代码:

struct ConstantOutputType

{

float edges[3] : SV_TessFactor;

float inside : SV_InsideTessFactor;

};

struct HullOutputType

{

float3 position : POSITION;

float4 color : COLOR;

};

struct PixelInputType

{

float4 position : SV_POSITION;

float4 color : COLOR;

};

//每个细分后的顶点调用一次

[domain("tri")]

PixelInputType ColorDomainShader(ConstantOutputType input, float3 uvwCoord : SV_DomainLocation, const OutputPatch<HullOutputType, 3> patch)

{

float3 vertexPosition;

PixelInputType output;

//基于重心坐标的顶点生成

vertexPosition = uvwCoord.x * patch[0].position + uvwCoord.y * patch[1].position + uvwCoord.z * patch[2].position;

// 计算新的顶点在世界坐标系中的位置

output.position = mul(float4(vertexPosition, 1.0f), worldMatrix);

output.position = mul(output.position, viewMatrix);

output.position = mul(output.position, projectionMatrix);

//新生成顶点颜色也为各个控制点颜色组合

output.color = uvwCoord.x * patch[0].color + uvwCoord.y * patch[1].color + uvwCoord.z * patch[2].color;

return output;

}

Directx11教程(59) tessellation学习(1)的更多相关文章

  1. Directx11教程(64) tessellation学习(6)-PN Triangles

    原文:Directx11教程(64) tessellation学习(6)-PN Triangles       前面我们用tessellation细分三角形或者四边形,产生的细分点都是在三角形或四边形 ...

  2. Directx11教程(63) tessellation学习(5)

    原文:Directx11教程(63) tessellation学习(5)        TS中生成细分后顶点的u,v,{w}坐标,我们根据控制点和u,w,{w}坐标生成新的顶点位置,在前面四边形的细分 ...

  3. Directx11教程(62) tessellation学习(4)

    原文:Directx11教程(62) tessellation学习(4)       现在看看四边形在不同tess factor时,四边形细分的细节,下图是tess factor1-8时候的细分.te ...

  4. Directx11教程(61) tessellation学习(3)

    原文:Directx11教程(61) tessellation学习(3)       现在我们看看在不同tess factor的情况下,三角形是如何细分的?(这儿三条边和内部tess factor值是 ...

  5. Directx11教程(60) tessellation学习(2)

    原文:Directx11教程(60) tessellation学习(2)        本教程中,我们开始tessellation编程,共实现了2个程序,第一个tessellation程序,是对一个三 ...

  6. Directx11教程(16) D3D11管线(5)

    原文:Directx11教程(16) D3D11管线(5) 本章我们学习VS中具体做些什么事情? 首先再看看我们的VS shader代码: Clolor.vs - PixelInputType Col ...

  7. Directx11教程(15) D3D11管线(4)

    原文:Directx11教程(15) D3D11管线(4) 本章我们首先了解一下D3D11中的逻辑管线,认识一下管线中每个stage的含义. 参考资料:http://fgiesen.wordpress ...

  8. Directx11教程(66) D3D11屏幕文本输出(1)

    原文:Directx11教程(66) D3D11屏幕文本输出(1)      在D3D10中,通过ID3DX10Font接口对象,我们可以方便的在屏幕上输出文字信息,一个DrawText函数就能解决所 ...

  9. Directx11教程(56) 建立一个skydome

    原文:Directx11教程(56) 建立一个skydome       本章建立一个skydome(天空穹),主要学习如何使用cube mapping.      cube map就是把六张纹理当作 ...

随机推荐

  1. 微信小程序上传报错:以下文件没有被打包上传: · .gitignore

    简单粗暴的办法就是:找到gitignore文件,把该文件删除掉即可. 在使用Git的过程中,我们喜欢有的文件比如日志,临时文件,编译的中间文件等不要提交到代码仓库,这时就要设置相应的忽略规则,来忽略这 ...

  2. 深入浅出 Java Concurrency (11): 锁机制 part 6 CyclicBarrier[转]

    如果说CountDownLatch是一次性的,那么CyclicBarrier正好可以循环使用.它允许一组线程互相等待,直到到达某个公共屏障点 (common barrier point).所谓屏障点就 ...

  3. vector容量器的应用

    vector容器的应用,感觉最近做的题目还用的挺多 vector与常用数组大部分是相同的,可以进行插入,删除之类的,但是,有些题目,用普通的数组就很容易爆掉,而vector可以动态的根据你所需要的来调 ...

  4. 60行JavaScript代码俄罗斯方块

    教你看懂网上流传的60行JavaScript代码俄罗斯方块游戏   早就听说网上有人仅仅用60行JavaScript代码写出了一个俄罗斯方块游戏,最近看了看,今天在这篇文章里面我把我做的分析整理一下( ...

  5. 【DM642学习笔记五】FVID驱动模型 API函数

    1.FVID_control 作用:发送一个控制命令到mini_driver 语法: status = FVID_control(fvidChan, cmd, args); 参数: FVID_Hand ...

  6. CSS3画图

    众所周知,用CSS3的圆角.转换可以画出各种不同的形状,制作不同的图案,早些前先驱者已画出经典的叮当猫,iphone手机等展示CSS3的强大实力,趁最近有空我也对CSS3进行了一些实践,颇有收获. 用 ...

  7. hbase设计方案1

    好的方案应该挺多的,比如:可以将[日.周.月]以3,2,1来表示(拼接到ROW_KEY中){离线跑job时候,可以分为月job(每月末run一下,周job(每周末run一下),日job(每天run一下 ...

  8. Luogu P1948 [USACO08JAN]电话线Telephone Lines(最短路+dp)

    P1948 [USACO08JAN]电话线Telephone Lines 题意 题目描述 Farmer John wants to set up a telephone line at his far ...

  9. Leetcode116. Populating Next Right Pointers in Each Node填充同一层的兄弟节点

    给定一个二叉树 struct TreeLinkNode { TreeLinkNode *left; TreeLinkNode *right; TreeLinkNode *next; } 填充它的每个 ...

  10. div 无缝滚动

    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3c.org ...