个人学习笔记 ——【技术美术百人计划】图形 3.3 曲面细分与几何着色器 大规模草渲染

这篇博客详细介绍了曲面细分与几何着色器在图形渲染中的应用,包括曲面细分着色器(Tessellation shader)的输入输出、流程和参数解析,以及几何着色器的输入输出和Demo演示。重点讨论了如何使用这两种着色器进行大规模草渲染,通过示例演示了细分和置换贴图的结合以及基于三角形构建草地的方法。
摘要由CSDN通过智能技术生成

个人学习笔记 ——【技术美术百人计划】图形 3.3 曲面细分与几何着色器 大规模草渲染



B站:

【技术美术百人计划】图形 3.3 曲面细分与几何着色器 大规模草渲染

PPT:

图形 3.3 曲面细分与几何着色器


一 、曲面细分与几何着色器的应用

1.1 曲面细分着色器的应用

在这里插入图片描述

1.2 几何着色器的应用

在这里插入图片描述

二、着色器执行顺序

在这里插入图片描述

  • 整体顺序:顶点 → 曲面细分 → 几何 → 片元;
  • 曲面细分又分为:Hull shader 、Tessellation Primitive Generator 、 Domain shade;

Hull shader:定义一些细分的参数(如:每条边上如何细分,内部三角形如何细分);
Tessellation Primitive Generator:不可编程的,不需要我们做啥;
Domain shader:经过曲面细分着色器细分后的点是位于重心空间的,这部分的作用就是把它转化到我们要用的空间。

  • 在OpenGL中HullShader 和DomainShader分别被简称:TCS和TES

三、曲面细分着色器-Tessellation shader(TESS)

1.TESS的输入和输出

在这里插入图片描述

2. TESS流程

在这里插入图片描述

3. HULL Shader各参数解析

在这里插入图片描述

3.1 Tessellation Factor

决定如何将一条边分成几部分

3.1.1 equal_Spacing

在这里插入图片描述

将一条边等分

3.1.2 fractional_even_spacing

在这里插入图片描述

even最小值是2,向上取最近的偶数

3.1.3 fractional_odd_spacing

在这里插入图片描述

odd最小值是1,向上取最近的奇数

3.2 Inner Tessellation Factor

作延长线,作交点

在这里插入图片描述

4. 曲面细分 Demo 演示

4.1 Quad细分

在这里插入图片描述

体现具体的使用方法,通过一个quad可以看出不同数值对细分的 影响(之后可以使用在草地中),基于shader再回顾一遍各个参数的作用

//曲面细分Demo1
Shader "Unlit/TessShader"
{
   
    Properties
    {
   
        _TessellationUniform("TessellationUniform",Range(1,64)) = 1
    }
    SubShader
    {
   
        Tags {
    "RenderType"="Opaque" }
        LOD 100
        Pass
        {
   
            CGPROGRAM
            //定义2个函数 hull domain
            #pragma hull hullProgram
            #pragma domain ds
           
            #pragma vertex tessvert
            #pragma fragment frag

            #include "UnityCG.cginc"
            //引入曲面细分的头文件
            #include "Tessellation.cginc" 

            #pragma target 5.0
            
            struct VertexInput
            {
   
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;
                float3 normal : NORMAL;
                float4 tangent : TANGENT;
            };

            struct VertexOutput
            {
   
                float2 uv : TEXCOORD0;
                float4 vertex : SV_POSITION;
                float3 normal : NORMAL;
                float4 tangent : TANGENT;
            };

            VertexOutput vert (VertexInput v)
            //这个函数应用在domain函数中,用来空间转换的函数
            {
   
                VertexOutput o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.uv = v.uv;
                o.tangent = v.tangent;
                o.normal = v.normal;
                return o;
            }

            //有些硬件不支持曲面细分着色器,定义了该宏就能够在不支持的硬件上不会变粉,也不会报错
            #ifdef UNITY_CAN_COMPILE_TESSELLATION
                //顶点着色器结构的定义
                struct TessVertex{
   
                    float4 vertex : INTERNALTESSPOS;
                    float3 normal : NORMAL;
                    float4 tangent : TANGENT;
                    float2 uv : TEXCOORD0;
                };

                struct OutputPatchConstant {
    
                    //不同的图元,该结构会有所不同
                    //该部分用于Hull Shader里面
                    //定义了patch的属性
                    //Tessellation Factor和Inner Tessellation Factor
                    float edge[3] : SV_TESSFACTOR;
                    float inside  : SV_INSIDETESSFACTOR;
                };

                TessVertex tessvert (VertexInput v){
   
                    //顶点着色器函数
                    TessVertex o;
                    o.vertex  = v.vertex;
                    o.normal  = v.normal;
                    o.tangent = v.tangent;
                    o.uv      = v.uv;
                    return o;
                }

                float _TessellationUniform;
                OutputPatchConstant hsconst (InputPatch<TessVertex,3> patch){
   
                    //定义曲面细分的参数
                    OutputPatchConstant o;
                    o.edge[0] = _TessellationUniform;
                    o.edge[1] = _TessellationUniform;
                    o.edge[2] = _TessellationUniform;
                    o.inside  = _TessellationUniform;
                    return o;
                }

                [UNITY_domain("tri")]//确定图元,quad,triangle等
                [UNITY_partitioning("fractional_odd")]//拆分edge的规则,equal_spacing,fractional_odd,fractional_even
                [UNITY_outputtopology("triangle_cw")]
                [UNITY_patchconstantfunc("hsconst")]//一个patch一共有三个点,但是这三个点都共用这个函数
                [UNITY_outputcontrolpoints(3)]      //不同的图元会对应不同的控制点
              
                TessVertex hullProgram (InputPatch<TessVertex,3> patch,uint id : SV_OutputControlPointID){
   
                    //定义hullshaderV函数
                    return patch[id];
                }

                [UNITY_domain("tri")]//同样需要定义图元
                VertexOutput ds (OutputPatchConstant tessFactors, const OutputPatch<TessVertex,3>patch,float3 bary :SV_DOMAINLOCATION)
                //bary:重心坐标
                {
   
                    VertexInput v;
                    v.vertex = patch[0].vertex*bary.x + patch[1].vertex*bary.y + patch[2].vertex*bary.z;
			        v.tangent = patch[0].tangent*bary.x + patch[1].tangent*bary.y + patch[2].tangent*bary.z;
			        v.normal = patch[0].normal*bary.x + patch[1].normal*bary.y + patch[2].normal*bary.z;
			        v.uv = patch[0].uv*bary.x + patch[1].uv*bary.y + patch[2].uv*bary.z;

                    VertexOutput o = vert (v);
                    return o;
                }
            #endif

            float4 frag (VertexOutput i) : SV_Target
            {
   

                return float4(1.0,1.0,1.0,1.0);
            }
            ENDCG
        }
    }
    Fallback "Diffuse"
}

4.2 细分和置换贴图结合

在这里插入图片描述

简单的展示一下模型的形变,不打算过多讲解细节,包括法线的计算(直接使用了一张能够匹配的法线图),阴影的添加等(感觉可能时间不够)

//曲面细分Demo2:与置换贴图结合使用
Shader "Unlit/Tess_Diss_Shader"
{
   
    Properties
    {
   
        _MainTex("MainTex",2D) = "white"{
   }
        _DisplacementMap("_DisplacementMap",2D)="gray"{
   }
        _DisplacementStrength("DisplacementStrength"
  • 4
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值