曲面细分着色器学习记录

前言:
今天终于走通了Catlike大佬的曲面细分着色器教程,感慨一番,自己的学习之路还很漫长呢
今天的博客内容只是简单的记录一下Catlike大佬的教程
先上个链接:Catlike的曲面细分教程

什么是曲面细分

学习过建模的朋友们都一定知道曲面细分,在Blender中也有曲面细分修改器工具,用来细分图元,帮助我们获得更细腻的模型表面

闫令琪在Games101中的Geometry章节中也降到了曲面细分的原理(Loop细分和Catmull-Clark细分,我回顾了一下感觉和今天的原理不太一样)


渲染管线中的曲面细分着色器

1. 渲染流水线

乐乐女神在《入门精要》中说明,曲面细分着色器处于几何阶段,并且可编程控制,同时这是一个可以选的shader

2. 输入与输出:
  • 输入:patch以及三角形索引,patch就是多个顶点的集合,可以指定一个patch包含几个顶点
  • 输出:细分之后的顶点
3. shader组成

在曲面细分着色器中,包含三个部分:
Hull shader
Tessellation
Domain shader
这三者中,Tessellation操作是计算机进行的,我们不可以操作,因此,我们需要配置的就是Hull shaderDomain shader
Hull shader:准备曲面细分的方法等基础数据,传递给Tessellation后进行细分操作
Dmain shader:对细分后的点进行处理,将其从重心坐标转到相应的空间(可以转到模型空间、投影空间等等)


Hull shader

Hull shader的结构与vert 或 frag shader的结构明显不同,除了一个主要的方法外,还需要在前定义5个属性,用来说明Hull应如何准备数据。
属性说明:
1.[UNITY_domain("tri")]:这个属性可以指定patch的类型,除了tri(三角形)之外,还包括quad、isoline。
2.[UNITY_outputcontrolpoints(3)]:输出的控制点的数量,不一定与输入数量相同,也可以新增控制点。
3.[UNITY_outputtopology("triangle_cw")]:输出拓扑结构。有三种:triangle_cw(顺时针)、trianglle_ccw(逆时针)、line(线段)。
4.[UNITY_partitioning("fractional_odd")]:分割模式。有三种:integer、fractional_even、fractional_odd。说白了就是integer只可以整数分割,剩余两者可以小数分割,一般都用odd,分割更自然。
5.[UNITY_patchconstantfunc("patchEdgeFunction")]:一个函数,patchEgdeFunction是教程里的函数名,这个函数需要在前面自行定义,用来说明细分中,边和图元里面的点内的细分数量。
6.[maxtessfactor(64.0f)]:上面的代码里没写,但是有一位知乎大佬说明了,在这里补充以下。最大细分度,告知驱动程序shader用到的最大细分度,硬件可能会针对这个做出优化。Direct3D 11和OpenGL Core都至少支持64。

Patch Constant Function
这个函数指定了一个patch如何细分,每个patch只调用一次这个函数,而不是每个控制点调用一次。Patch Constant FunctionHull shader并行运行。

为了确定如何细分三角形,GPU使用四个细分因子,三角形的每条边都有一个因子,三角形内部也有一个因子,这两种细分因子都具有相应的语义。
因此,需要为这个细分因子创建一个结构体:

struct TessellationFactors
{float edge[3] : SV_TessFactor;float inside : SV_InsideTessFactor;
};

现在,我们可以定义Patch Constant Function函数了:

TessellationFactors MyPatchConstantFunction (InputPatch<VertexData, 3> patch) {TessellationFactors f;f.edge[0] = 1;f.edge[1] = 1;f.edge[2] = 1;f.inside = 1;return f;
}

上述的代码中,MyPatchConstantFunction是函数的名称,传入的数据是patch,在函数中定义了每条边以及三角形内部的细分因子,最后输出TessellationFactors。这里的细分因子的参数只是暂时的,可以根据不同需求更改:
不同的Tessellation Factors计算:
1 . _Tessellation:使用_Tessellation变量要求我们在shader中定义相应的Properties。此时,MyPatchConstantFunction 应如下:

TessellationFactors MyPatchConstantFunction (InputPatch<VertexData, 3> patch) {TessellationFactors f;f.edge[0] = _Tessellation;f.edge[1] = _Tessellation;f.edge[2] = _Tessellation;f.inside = _Tessellation;return f;
}

在这里,edge与inside上的细分因子是相同的,他们不同的时候,有着不同的效果,具体可以参照原文。
2 .使用观察空间中的距离设置相应的因子。因此,还需要定义一个设置edge上细分因子的函数,这个函数需要根据每个三角形点的参数进行设置(因为需要计算顶点与相机之间的距离)。因此,代码应该包含两部分:

float TessellationEdgeFactor(TessellationControlPoint cp0, TessellationControlPoint cp1){float3 p0 = mul(unity_ObjectToWorld, float4(cp0.vertex.xyz, 1)).xyz;float3 p1 = mul(unity_ObjectToWorld, float4(cp1.vertex.xyz, 1)).xyz;float edgeLength = distance(p0, p1);float3 edgeCenter = (p0 + p1) * 0.5;float viewDistance = distance(edgeCenter, _WorldSpaceCameraPos);return edgeLength * _ScreenParams.y / (_TessellationEdgeLength * viewDistance);
}
TessellationFactors patchEdgeFunction (InputPatch<TessellationControlPoint, 3> patch){TessellationFactors f;f.edge[0] = TessellationEdgeFactor(patch[1], patch[2]);f.edge[1] = TessellationEdgeFactor(patch[2], patch[0]);f.edge[2] = TessellationEdgeFactor(patch[0], patch[1]);f.inside = (f.edge[0] + f.edge[1] + f.edge[2]) / 3;return f;
}

由于上述的距离是在世界坐标中进行计算的,所以需要进行一个缩放,才能在屏幕中看到正确的效果。这里只乘以一个_ScreenParams.y进行一个简化的缩放。
至此,一个完整的Hull shader应包含以下部分:

// 曲面细分因素
struct TessellationFactors
{float edge[3] : SV_TessFactor;float inside : SV_InsideTessFactor;
};struct TessellationControlPoint{float4 vertex : POSITION;float3 normal : NORMAL;float4 tangent : TANGENT;
};vertexOutput TessellationVertex (MyTessVertex v){return v;
}float TessellationEdgeFactor(TessellationControlPoint cp0, TessellationControlPoint cp1){float3 p0 = mul(unity_ObjectToWorld, float4(cp0.vertex.xyz, 1)).xyz;float3 p1 = mul(unity_ObjectToWorld, float4(cp1.vertex.xyz, 1)).xyz;float edgeLength = distance(p0, p1);float3 edgeCenter = (p0 + p1) * 0.5;float viewDistance = distance(edgeCenter, _WorldSpaceCameraPos);return edgeLength * _ScreenParams.y / (_TessellationEdgeLength * viewDistance);
}
TessellationFactors patchEdgeFunction (InputPatch<TessellationControlPoint, 3> patch){TessellationFactors f;f.edge[0] = TessellationEdgeFactor(patch[1], patch[2]);f.edge[1] = TessellationEdgeFactor(patch[2], patch[0]);f.edge[2] = TessellationEdgeFactor(patch[0], patch[1]);f.inside = (f.edge[0] + f.edge[1] + f.edge[2]) / 3;return f;
}[UNITY_domain("tri")]
[UNITY_outputcontrolpoints(3)]
[UNITY_outputtopology("triangle_cw")]
[UNITY_partitioning("fractional_odd")]
[UNITY_patchconstantfunc("patchEdgeFunction")]
TessellationControlPoint myHullProgram (InputPatch<TessellationControlPoint, 3> patch, uint id : SV_OutputControlPointID)
{return patch[id];
}

上述的代码中,有一个TessellationControlPoint 结构体,在原作者中的描述是说可能会产生语义上的错误,专门为曲面细分过程中的顶点进行一个INTERNALTESSPOS语义的定义:

TessellationControlPoint MyTessellationVertexProgram (VertexData v) {TessellationControlPoint p;p.vertex = v.vertex;p.normal = v.normal;p.tangent = v.tangent;return p;
}

但是不知道为什么,我按照作者的意思却一直不能显示正确的结果,所以我还是使用原始的顶点的结构体。估计是平台兼容的问题?


Domain shader

已经完成了Hull shader,接下来就是定义Domain shader。
Tessellation阶段为我们提供了重心坐标,我们需要在Domain shader中将其转换导出正确空间下的顶点。

[UNITY_domain("tri")]
vertexOutput myDomainProgram(TessellationFactors factors,
OutputPatch<TessellationControlPoint, 3> patch,
float3 barycentricCoordinates : SV_DomainLocation)
{vertexOutput v;#define MY_DOMAIN_PROGRAM_INTERPOLATE(fieldName) v.fieldName = \patch[0].fieldName * barycentricCoordinates.x + \patch[1].fieldName * barycentricCoordinates.y + \patch[2].fieldName * barycentricCoordinates.z;MY_DOMAIN_PROGRAM_INTERPOLATE(vertex)MY_DOMAIN_PROGRAM_INTERPOLATE(normal)MY_DOMAIN_PROGRAM_INTERPOLATE(tangent)return TessellationVert(v);
}

完整代码如上,还是有几点需要注意:

  • Domain shader前面仍然需要添加[UNITY_domain(“tri”)]
  • Domain shader的输入包括:细分因子、patch数据、重心坐标
  • shader内部的重心计算可以设置为一个宏,方便我们计算其他的信息,如顶点、法线、切线等
  • 目前位置,我们没有进行任何将顶点转换到裁剪空间中的操作,原作者是将domain shader的计算结果返回到一个将顶点转换到裁剪空间中的shader,再进行空间变换。知乎大佬也是直接在domain shader中将顶点变换至裁剪空间,这里面在哪里变换选择很多。
  • 还有一点是Hull shader的返回,似乎Hull shader已经计算好了所有的数据,各位大佬返回什么的都有。这里只返回了patch的id

参考:

1 . https://zhuanlan.zhihu.com/p/42550699
2 . https://catlikecoding.com/unity/tutorials/advanced-rendering/tessellation/

曲面细分着色器学习记录相关推荐

  1. Shader学习_曲面细分着色器

    曲面细分 详细介绍 当然除了细分与简化之外,还有另外一种同属一类的操作叫做==曲面规则化(Mesh Regularization)==其所作的便是将三角面都变的尽可能相同,从而也达到提升模型效果的目的 ...

  2. 曲面细分着色器---细分二维四边形

    openGL系列文章目录 文章目录 openGL系列文章目录 前言 一.曲面细分 二.细分二维四边形 参考 前言 术语Tessellation(镶嵌)是指一大类设计活动,通常是指在平坦的表面上,用各种 ...

  3. Shader入门---曲面细分着色器和几何着色器

    Shader入门-曲面细分着色器和几何着色器 前记:学不可以停止-------------------------------mx 基础知识: 曲面细分着色器:可以将一个几何体细化为一个球体也能将一根 ...

  4. 曲面细分着色器与几何着色器

    着色器执行顺序 顶点着色器->曲面细分着色器->几何着色器->片元着色器 曲面细分着色器细分后的顶点属于重心空间. 曲面细分着色器 应用:海浪.雪地等 与置换贴图结合:只使用法线贴图 ...

  5. UnityShader 曲面细分着色器 生成地形 高度贴图

    什么是曲面细分着色器 如下图 ​ 曲面细分着色器比较官方定义:可以将一个几何体细化为一个球体也能将一根直线无限向曲线逼近 曲面细分着色器将复杂的曲面转换为简单的点,线,三角形等.它分为三部分:曲面细分 ...

  6. 曲面细分(subdivision)曲面细分着色器GPU的LOD

    曲面细分是指将一个模型的面合理的分成更多小的面,从而提升模型精度,提高渲染效果 曲面简化是指将一个模型的面合理的合成更少的面,从而降低模型精度,为特定情形下提供使用(如LOD技术) .这一过程是可以在 ...

  7. unity曲面细分着色器详解

     前言:本文翻译自catlikecoding上一篇十分详细的英文blog并修改了几处错误,逐行解释了如何在自己的shader中添加曲面细分支持,并给出了多种计算细分因子的方案以及它们的优缺点. 原文链 ...

  8. DirectX 12 曲面细分着色器笔记

    曲面细分着色器 1. 背景 2. 曲面细分工作机制 2.1 Hull Shader(外壳着色器) 2.2 Tessellator(曲面细分器) 2.3 Domain Shader(域细分器) 3. 编 ...

  9. Unity初学Shadergraph创建着色器学习教程

    MP4 |视频:h264,1280×720 |音频:AAC,44.1 KHz,2 Ch 语言:英语+中英文字幕(根据原英文字幕机译更准确) |时长:51节课(4h 44m) |大小解压后:2.55 G ...

最新文章

  1. HDFS数据定时采集demo 简单
  2. 数据解析系统中需改进的几点
  3. activemq的使用场景
  4. java状态模式和策略模式_Java状态和策略设计模式之间的差异
  5. 虚拟同步发电机_一种光储型虚拟同步机介绍
  6. 56 - II. 数组中数字出现的次数 II
  7. 美团算法 SP | NLP 三面复盘
  8. 02-Go语言数据类型与变量
  9. win10-ubuntu-软件配置-开机root无密码-风扇转速调节
  10. MP3格式音频数据文件解析
  11. 今日头条信息流广告怎么做?(今日头条信息流广告费用解析)
  12. vue 项目实践 -ele 表单验证
  13. zblog mysql修改_手把手教修正zblog默认阅读量
  14. Microsoft自家的虚拟光驱 Virtual CD-ROM Control Panel for Wind
  15. trs 同步模版 栏目修改(高级)
  16. 网关是什么,一文带你快速入门腾讯技术工程
  17. 微信小程序助力社区便利店利润破百万
  18. 2006年安全软件全球纵览(转
  19. 十条网站盈利模式分析总结 1
  20. 如何快速查看将C反汇编的代码

热门文章

  1. 渣渣辉来给大家拜年啦,影帝夫人、TVB当家花旦关咏荷一起出镜!
  2. games101学习笔记_Cameras, Lenses and Light Fields
  3. 【实测有效】一键生成微信对话视频,微信聊天记录生成器,
  4. 检测是否安装nginx
  5. 银行科技 | 招行CIO陈昆德:客户和科技是招行未来的两大核心主题
  6. 第十七届全国大学生智能汽车竞赛全国总决赛成绩公告
  7. 小米9售价揭晓!可能是最后一次了
  8. 淘宝UWP中的100个为什么
  9. 基于Springboot的仿天猫电商系统
  10. HTML----CSS