简述

曲面细分是渲染管线的一个可配置的阶段,在opengl和direct3d里都有实现,Unity的表面着色器对曲面细分有一定的支持,不过必须运行在Shader Model 4.6以上。
曲面细分说白了就是可以实时生成更多的顶点,我们知道在顶点着色器里是不能生成新的顶点的,如果没有曲面细分阶段的话想实时生成新的顶点只能在cpu里生成然后再传输到gpu里,因此为了提升实时生成顶点的速度就多了曲面细分这样一个渲染阶段。
曲面细分阶段是配置式的,不能像顶点着色器和片元着色器一样自己写shader来完全的控制,但是可以配置生成新顶点的方式,数量等等。
曲面细分阶段主要是为了提升渲染的质量和性能,可以对重要的模型生成更多的顶点,对远处或者不重要的模型生成更少的顶点,而更多的顶点就代表更好的渲染质量。虽然有很多类似法线贴图视差贴图之类优化在低模上的渲染效果的方法,但是这些方法的效果都比不过直接提升顶点数量来的直接,这也是曲面细分的强大之处。
我们以曲面细分配合位移贴图(displacement map)来描述一下unity中曲面细分的配置方法,曲面细分配合位移贴图也是一种常见的用法。

位移贴图

位移贴图是一种和法线贴图,视差贴图同类型的技术,都是为了提升低模的显示效果。
如果说法线贴图是将高模的法线覆盖到低模上,视差贴图是为了解决法线贴图部分顶点不会互相遮挡的问题。
那么位移贴图就是更近一步,直接用一张贴图来对顶点进行位移,彻底解决了法线贴图和视差贴图解决不了的问题。
说起来还是挺简单的,位移贴图就是一张灰度图,然后用顶点对图片进行采样,根据采样得到的灰度将该顶点朝法线方向进行移动相应的距离,这个灰度图一般由高模生成。
有的人可能会觉得,那直接用高模不就行了吗?先用低模然后又用一张贴图生成更多的顶点然后又进行位移,最后不是又和高模一样了吗?
其实是不一样的,这主要是因为曲面细分是可以配置的,虽然我们理论上可以生成超过高模的顶点数,但是一般是根据性能指标来进行配置的,想要效果更好就生成更多的顶点,依次类推。而且还可以根据模型的重要性来对曲面细分进行不同的配置,或者是根据距离来确定曲面细分的配置,因此使用曲面细分从低模生成更多的顶点比起直接使用高模还是要更加灵活的。

先写一个简单的表面着色器来使用位移贴图,这个着色器就是简单采样了主纹理,然后再用顶点采样位移贴图来位移顶点。

Shader "LX/tessellation"
{Properties{_Color ("Color", Color) = (1,1,1,1)_MainTex ("Albedo (RGB)", 2D) = "white" {}_Glossiness ("Smoothness", Range(0,1)) = 0.5_Metallic ("Metallic", Range(0,1)) = 0.0_DispTex ("DispTex", 2D) = "white" {}_Displacement ("Displacement", float) = 1_Tess ("Tess", float) =1_Power ("Power", range(1,8)) =1_Phong ("Phong Strengh", Range(0,1)) = 0.5_EdgeLength ("Edge length", Range(2,50)) = 5}SubShader{Tags{"RenderType"="Opaque"}LOD 200CGPROGRAM#pragma surface surf Standard fullforwardshadows vertex:disp#pragma target 3.0#include "Tessellation.cginc"sampler2D _MainTex;sampler2D _DispTex;float _Phong;struct Input{float2 uv_MainTex;float3 worldNormal;};half _Glossiness;half _Metallic;fixed4 _Color;float _Displacement;float _Tess;float _Power;float _EdgeLength;void disp(inout appdata_base v){float d = pow(Luminance(tex2Dlod(_DispTex, float4(v.texcoord.xy, 0, 0))), _Power) * _Displacement;v.vertex.xyz += v.normal * d;}void surf(Input IN, inout SurfaceOutputStandard o){fixed4 c = tex2D(_MainTex, IN.uv_MainTex) * _Color;o.Albedo = c.rgb;o.Metallic = _Metallic;o.Smoothness = _Glossiness;o.Alpha = c.a;}ENDCG}FallBack "Diffuse"
}

至于位移贴图我们这边简单使用了一个中间凸出一块渐变白色圆形的贴图来做示范,理想情况下这个贴图可以把该平面中间凸出一个比较完美的半球。

创建一个quad来使用这个着色器,发现根本没有任何反应,因为我们上面的代码还没有加入曲面细分配置,而quad只有四个顶点,想象一下就知道根本无从采样,对于采样位移贴图来说实在太少了。位移贴图是比较要有足够多的顶点才可以看出效果的,顶点越多效果就越平滑。

因为曲面细分是直接配置的一个阶段,所以我们并不用写太多代码, 在表面着色器的第一行配置后面追加tessellate:tessFixed 来使用固定值的曲面细分

#pragma surface surf Standard fullforwardshadows vertex:disp tessellate:tessFixed

再在CGPROGRAM里加入对应名字的函数,然后返回一个曲面细分值,这个值越大曲面细分的程度越大。

            float _Tess;float4 tessFixed(){return _Tess;}

设置一下参数之后可以看到

切换到scene 的渲染模式到wireframe之后可以看到曲面细分生成了新的顶点
tess=1(原始状态,只有四个顶点)

tess=20,生成了非常多的新顶点,而且我们也可以看到,和法线贴图那种通过控制明暗程度来表现’虚假’的凸出效果不同,曲面细分是实实在在的生成了新的顶点。

固定值的曲面细分就是这么配置,那么如果想要使用基于距离的曲面细分,unity也有写好的内置函数
同样先在上面配置曲面细分函数的名称

#pragma surface surf Standard fullforwardshadows vertex:disp tessellate:tessFixed

然后使用unity内置的UnityDistanceBasedTess函数来实现基于距离的曲面细分,tessDistance 的三个参数分别是三角形的三个顶点,这个不用管直接依次传入UnityDistanceBasedTess函数,然后minDist和maxDist就是距离的起始值和结束值,_Tess就是曲面细分程度。
这个函数的话需要包含Tessellation.cginc文件

            float _Tess;float4 tessDistance (appdata v0, appdata v1, appdata v2) {float minDist = 10.0;float maxDist = 25.0;return UnityDistanceBasedTess(v0.vertex, v1.vertex, v2.vertex, minDist, maxDist, _Tess);}

unity还支持基于线段长度的曲面细分,可以防止一些很小的三角形的曲面细分程度过高

            float _EdgeLength;float4 tessEdge (appdata v0, appdata v1, appdata v2){return UnityEdgeLengthBasedTess (v0.vertex, v1.vertex, v2.vertex, _EdgeLength);}

还有一个tessphong配置可以和tessellate配置一起用,tessphong可以使生成出来的顶点位置更加平滑,_Phong的话就是一个参数,越大越平滑。

 #pragma surface surf Standard fullforwardshadows vertex:disp tessellate:tessEdge tessphong:_Phong

有兴趣的话也可以研究一下这几个函数的内部实现,其实最后还是根据距离之类的条件返回一个曲面细分值。

最后的参数面板

完整代码

Shader "LX/tessellation"
{Properties{_Color ("Color", Color) = (1,1,1,1)_MainTex ("Albedo (RGB)", 2D) = "white" {}_Glossiness ("Smoothness", Range(0,1)) = 0.5_Metallic ("Metallic", Range(0,1)) = 0.0_DispTex ("DispTex", 2D) = "white" {}_Displacement ("Displacement", float) = 1_Tess ("Tess", float) =1_Power ("Power", range(1,8)) =1_Phong ("Phong Strengh", Range(0,1)) = 0.5_EdgeLength ("Edge length", Range(2,50)) = 5}SubShader{Tags{"RenderType"="Opaque"}LOD 200CGPROGRAM#pragma surface surf Standard fullforwardshadows vertex:disp tessellate:tessEdge tessphong:_Phong#pragma target 3.0#include "Tessellation.cginc"sampler2D _MainTex;sampler2D _DispTex;float _Phong;struct Input{float2 uv_MainTex;float3 worldNormal;};half _Glossiness;half _Metallic;fixed4 _Color;float _Displacement;float _Tess;float _Power;float _EdgeLength;// float4 tessFixed()// {//     return _Tess;// }float4 tessEdge(appdata_base v0, appdata_base v1, appdata_base v2){return UnityEdgeLengthBasedTess(v0.vertex, v1.vertex, v2.vertex, _EdgeLength);}void disp(inout appdata_base v){float d = pow(Luminance(tex2Dlod(_DispTex, float4(v.texcoord.xy, 0, 0))), _Power) * _Displacement;v.vertex.xyz += v.normal * d;}void surf(Input IN, inout SurfaceOutputStandard o){fixed4 c = tex2D(_MainTex, IN.uv_MainTex) * _Color;o.Albedo = c.rgb;o.Metallic = _Metallic;o.Smoothness = _Glossiness;o.Alpha = c.a;}ENDCG}FallBack "Diffuse"
}

另外代码也传到github仓库里了,大家也可以关注一下哦~
我的github

Unity3D Tessellation曲面细分相关推荐

  1. Tessellation (曲面细分) Displacement Mapping (贴图置换)

    DirectX 11 Tessellation (曲面细分)-什么是 Tessellation (曲面细分) ? 它为什么可以起到如此关键的数据? 随着近期人们对 DirectX 11 的议论纷纷,你 ...

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

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

  3. Surface Shaders with DX11 / OpenGL Core Tessellation 表面着色的曲面细分 - Unity Shader Reference 系列5

    Surface Shaders with DX11 / OpenGL Core Tessellation DX11/OpenGL核心下表面着色器的曲面细分 本文档主要是对Unity官方手册的个人理解与 ...

  4. c++生成nurbs曲面文件_使用曲面细分丰富原始多边形

    曲面细分 光栅化图形渲染管线下,还有一部分需要我们进行详细的说明.曲面细分不单可以细分图元(简单的Flat Tessellation),还可以生成曲面(PN-Triangles),这是流水线中其它阶段 ...

  5. openGL曲面细分

    openGL系列文章目录 文章目录 openGL系列文章目录 前言 一.OpenGL 中的曲面细分 二.代码 1.主程序c++ 效果 前言 术语Tessellation(镶嵌)是指一大类设计活动,通常 ...

  6. 使用曲面细分渲染毛发

    使用曲面细分渲染毛发 original link 几周前,我无意间找到了一篇让很有趣的论文,主要讲述的是使用曲面细分技术去渲染头发,并且是在Direct3D 11类型的GPU上.这是我多年前在曲面细分 ...

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

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

  8. Unity URP 曲面细分

    Unity URP 曲面细分 我终于变得不像我 文章目录 Unity URP 曲面细分 1 曲面细分与镶嵌 1.1 外壳着色器 Hull Shader 1.2 镶嵌器阶段 Tessellator 1. ...

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

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

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

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

最新文章

  1. 布尔定理及证明(完整版)
  2. notepad php必用功能,Notepad中值得一提的特性
  3. LINUX内核下跑单片机按键,S3C2440下linux按键驱动编写及测试程序
  4. 深入jar包:从jar包中读取资源文件
  5. mysql publishedtime_MySQL数据库中的Date,DateTime,TimeStamp和Time类型
  6. 【软件测试】软件测试的基本流程(一般步骤)
  7. redmine backlogs的tracker使用
  8. 电商后台管理系统订单列表模块
  9. BZOJ 2563 阿狸和桃子的游戏 (贪心)
  10. android中倒计时动画,简单实现Android倒计时效果
  11. Android 通过adb禁止某个应用上网
  12. [SHOI2008]小约翰的游戏John(博弈+SJ定理)
  13. 苹果cms数据.php,苹果cms数据库常用sql语句对照及使用方法
  14. Fastjson解析复杂json数据
  15. Linux下mpstat命令下,linux mpstat命令详解
  16. 基于python的随机森林回归实现_从零实现回归随机森林
  17. 重磅!骂了 10 年,微信这功能终于要来了!
  18. 三菱PLC 状态继电器
  19. Qt水平布局,垂直布局和嵌套布局 layout
  20. 2023年最新大厂开发面试题(滴滴,华为,京东,腾讯,头条)

热门文章

  1. js 文件下载请求两种方式
  2. Keil 保护视力背景颜色设置和代码的颜色设置
  3. 江苏自考计算机专业,2021年江苏自考本科专业选择:计算机类专业前景如何?有哪些科目?...
  4. java山海经之轩辕_山海经之情剑轩辕 炼化任务详细攻略
  5. OSChina 周六乱弹 —— 我都想和他们组成一个家庭了
  6. Android自定义消息推送
  7. 多个安卓设备投屏到电脑_安卓手机怎么投屏到电脑上?这样做,在电脑上就能操控手机...
  8. 苹果手机无法解析html,苹果手机故障全解析
  9. hulk入门使用——ddos攻击
  10. T检验、F检验、Z检验、卡方检验