Contoh pencahayaan Shader permukaan
Menulis naungan untuk API grafis yang berbeda

Permukaan Shader dengan DX11 / OpenGL Inti Tesselasi

Pada Render PipelineRangkaian operasi yang mengambil isi dari Adegan, dan menampilkannya di layar. Unity memungkinkan Anda memilih dari pipa render yang dibangun sebelumnya, atau menulis sendiri. More info
Lihat di Glossary
Built-in, Permukaan ShaderCara merampingkan naungan menulis untuk Pipeline Render Built-in. More info
Lihat di Glossary
memiliki beberapa dukungan untuk DirectX 11 / OpenGL Core GPU Tesselasi.

Kompatibilitas pipa Render

Feature name Built-in Render Pipeline Universal Render Pipeline (URP) High Definition Render Pipeline (HDRP) Custom SRP
Surface Shaders Yes No

Untuk cara merampingkan menciptakan benda-benda Shader di URP, lihat Shader Graph.
No

Untuk cara ramping menciptakan benda-benda Shader di HDRP, lihat Shader Graph.
No

Overview

  • Tesselasi ditunjukkan oleh pengubah tessellate:FunctionName. Fungsi yang mengimbangi tepi segitiga dan dalam faktor-faktor uji.
  • Ketika tesselilasi digunakan, “vertex modifier” (vertex:FunctionName) divoked after tesselilasi, untuk setiap simpul yang dihasilkan di domain shaderProgram yang berjalan di GPU. More info
    Lihat di Glossary
    . Di sini Anda biasanya beralih pemetaan.
  • Permukaan naungan dapat secara opsional menghitung phong tessellation ke permukaan model halus bahkan tanpa pemetaan perpindahan.

Batasan arus dukungan ujiselasi:

  • Hanya domain segitiga - tidak ada quadsObjek primitif yang menyerupai pesawat tetapi tepinya hanya satu unit panjang, hanya menggunakan 4 simpul, dan permukaan berorientasi pada pesawat XY ruang koordinat lokal. More info
    Lihat di Glossary
    , tidak ada tesselasi isoline.
  • Ketika Anda menggunakan tesselasi, naungan secara otomatis dikompilasi ke dalam Shader Model 4.6 target, yang mencegah dukungan untuk berjalan pada target grafis yang lebih tua.

Tidak ada tesselasi GPU, perpindahan dalam pengubah simpul

Contoh berikutnya menunjukkan naungan permukaan yang melakukan beberapa pemetaan perpindahan without menggunakan ujiselasi. Ini hanya bergerak vertices sepanjang normal mereka berdasarkan jumlah yang datang dari peta perpindahan:

    Shader "Tessellation Sample" {
        Properties {
            _MainTex ("Base (RGB)", 2D) = "white" {}
            _DispTex ("Disp Texture", 2D) = "gray" {}
            _NormalMap ("Normalmap", 2D) = "bump" {}
            _Displacement ("Displacement", Range(0, 1.0)) = 0.3
            _Color ("Color", color) = (1,1,1,0)
            _SpecColor ("Spec color", color) = (0.5,0.5,0.5,0.5)
        }
        SubShader {
            Tags { "RenderType"="Opaque" }
            LOD 300
            
            CGPROGRAM
            #pragma surface surf BlinnPhong addshadow fullforwardshadows vertex:disp nolightmap
            #pragma target 4.6

            struct appdata {
                float4 vertex : POSITION;
                float4 tangent : TANGENT;
                float3 normal : NORMAL;
                float2 texcoord : TEXCOORD0;
            };

            sampler2D _DispTex;
            float _Displacement;

            void disp (inout appdata v)
            {
                float d = tex2Dlod(_DispTex, float4(v.texcoord.xy,0,0)).r * _Displacement;
                v.vertex.xyz += v.normal * d;
            }

            struct Input {
                float2 uv_MainTex;
            };

            sampler2D _MainTex;
            sampler2D _NormalMap;
            fixed4 _Color;

            void surf (Input IN, inout SurfaceOutput o) {
                half4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color;
                o.Albedo = c.rgb;
                o.Specular = 0.2;
                o.Gloss = 1.0;
                o.Normal = UnpackNormal(tex2D(_NormalMap, IN.uv_MainTex));
            }
            ENDCG
        }
        FallBack "Diffuse"
    }

Shader di atas cukup standar:

  • Vertex modifier disp sampel peta perpindahan dan bergerak vertices sepanjang normal mereka.
  • Ini menggunakan struktur input data "vertex" kustom (appdata) bukan default appdata_full. Ini tidak diperlukan, tetapi lebih efisien untuk pengujianselasi untuk digunakan sebagai struktur kecil mungkin.
  • Karena data simpul kami tidak memiliki koordinat UV 2, kami menambahkan arahan nolightmap untuk mengecualikan lightmapsTekstur pra-render yang mengandung efek sumber cahaya pada objek statis di tempat kejadian. Lightmaps dilalui atas geometri adegan untuk menciptakan efek pencahayaan. More info
    Lihat di Glossary
    .

Gambar di bawah ini menampilkan beberapa GameObjectsObjek mendasar dalam adegan Unity, yang dapat mewakili karakter, props, pemandangan, kamera, waypoints, dan banyak lagi. Fungsi GameObject didefinisikan oleh Komponen yang melekat padanya. More info
Lihat di Glossary
sederhana dengan naungan ini diterapkan.


Jumlah tesselasi tetap

Jika wajah model Anda kira-kira ukuran yang sama di layar, tambahkan jumlah tetap dari tesselasi ke MeshGrafik utama primitif Unity. Mesh membuat sebagian besar dunia 3D Anda. Unity mendukung mesh poligon triangulat atau Quadrangulasi. Nurbs, Nurms, permukaan Subdiv harus dikonversi ke poligon. More info
Lihat di Glossary
(tingkat tesselasi yang sama di seluruh Mesh).

Script contoh berikut menerapkan jumlah tetap dari tesselasi.

    Shader "Tessellation Sample" {
        Properties {
            _Tess ("Tessellation", Range(1,32)) = 4
            _MainTex ("Base (RGB)", 2D) = "white" {}
            _DispTex ("Disp Texture", 2D) = "gray" {}
            _NormalMap ("Normalmap", 2D) = "bump" {}
            _Displacement ("Displacement", Range(0, 1.0)) = 0.3
            _Color ("Color", color) = (1,1,1,0)
            _SpecColor ("Spec color", color) = (0.5,0.5,0.5,0.5)
        }
        SubShader {
            Tags { "RenderType"="Opaque" }
            LOD 300
            
            CGPROGRAM
            #pragma surface surf BlinnPhong addshadow fullforwardshadows vertex:disp tessellate:tessFixed nolightmap
            #pragma target 4.6

            struct appdata {
                float4 vertex : POSITION;
                float4 tangent : TANGENT;
                float3 normal : NORMAL;
                float2 texcoord : TEXCOORD0;
            };

            float _Tess;

            float4 tessFixed()
            {
                return _Tess;
            }

            sampler2D _DispTex;
            float _Displacement;

            void disp (inout appdata v)
            {
                float d = tex2Dlod(_DispTex, float4(v.texcoord.xy,0,0)).r * _Displacement;
                v.vertex.xyz += v.normal * d;
            }

            struct Input {
                float2 uv_MainTex;
            };

            sampler2D _MainTex;
            sampler2D _NormalMap;
            fixed4 _Color;

            void surf (Input IN, inout SurfaceOutput o) {
                half4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color;
                o.Albedo = c.rgb;
                o.Specular = 0.2;
                o.Gloss = 1.0;
                o.Normal = UnpackNormal(tex2D(_NormalMap, IN.uv_MainTex));
            }
            ENDCG
        }
        FallBack "Diffuse"
    }

Dalam contoh di atas, fungsi ujiselasi tessFixed kembali empat faktor tesselasi sebagai nilai float4 tunggal: tiga faktor untuk setiap tepi segitiga, dan satu faktor untuk bagian dalam segitiga.

Contoh mengembalikan nilai konstan yang ditetapkan dalam sifat Material.


Tesselasi berbasis jarak

Anda juga dapat mengubah tingkat tesselasi berdasarkan jarak dari cameraKomponen yang menciptakan gambar sudut pandang tertentu di tempat kejadian Anda. Output ditarik ke layar atau ditangkap sebagai tekstur. More info
Lihat di Glossary
. Misalnya, Anda bisa mendefinisikan dua nilai jarak:

  • Jarak ketika tesselilasi maksimum (misalnya, 10 meter).
  • Jarak ketika tingkat pengujianselilasi berkurang secara bertahap (misalnya, 20 meter).
    Shader "Tessellation Sample" {
        Properties {
            _Tess ("Tessellation", Range(1,32)) = 4
            _MainTex ("Base (RGB)", 2D) = "white" {}
            _DispTex ("Disp Texture", 2D) = "gray" {}
            _NormalMap ("Normalmap", 2D) = "bump" {}
            _Displacement ("Displacement", Range(0, 1.0)) = 0.3
            _Color ("Color", color) = (1,1,1,0)
            _SpecColor ("Spec color", color) = (0.5,0.5,0.5,0.5)
        }
        SubShader {
            Tags { "RenderType"="Opaque" }
            LOD 300
            
            CGPROGRAM
            #pragma surface surf BlinnPhong addshadow fullforwardshadows vertex:disp tessellate:tessDistance nolightmap
            #pragma target 4.6
            #include "Tessellation.cginc"

            struct appdata {
                float4 vertex : POSITION;
                float4 tangent : TANGENT;
                float3 normal : NORMAL;
                float2 texcoord : TEXCOORD0;
            };

            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);
            }

            sampler2D _DispTex;
            float _Displacement;

            void disp (inout appdata v)
            {
                float d = tex2Dlod(_DispTex, float4(v.texcoord.xy,0,0)).r * _Displacement;
                v.vertex.xyz += v.normal * d;
            }

            struct Input {
                float2 uv_MainTex;
            };

            sampler2D _MainTex;
            sampler2D _NormalMap;
            fixed4 _Color;

            void surf (Input IN, inout SurfaceOutput o) {
                half4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color;
                o.Albedo = c.rgb;
                o.Specular = 0.2;
                o.Gloss = 1.0;
                o.Normal = UnpackNormal(tex2D(_NormalMap, IN.uv_MainTex));
            }
            ENDCG
        }
        FallBack "Diffuse"
    }

Di sini, fungsi tesselilasi mengambil data simpul dari tiga sudut segitiga sebelum pengujianselilasi sebagai tiga parameter.

Unity perlu ini untuk menghitung tingkat tesselasi, yang tergantung pada posisi simpul.

Contohnya termasuk file helper built-in, Tessellation.cginc, dan memanggil fungsi UnityDistanceBasedTess dari file untuk melakukan semua pekerjaan. Fungsi ini menghitung jarak setiap simpul ke kamera dan derives faktor ujiselasi akhir.


Panjang tepi berdasarkan tesselasi

Tesselasi berbasis jarak murni hanya efektif ketika ukuran segitiga cukup mirip. Dalam gambar di atas, GameObjects yang memiliki segitiga kecil disegulasi terlalu banyak, sementara GameObjects yang memiliki segitiga besar tidak cukup disegulasi.

Satu cara untuk meningkatkan ini adalah untuk menghitung tingkat tesselasi berdasarkan panjang tepi segitiga di layar. Unity harus menerapkan faktor ujiselasi yang lebih besar ke tepi yang lebih panjang.

    Shader "Tessellation Sample" {
        Properties {
            _EdgeLength ("Edge length", Range(2,50)) = 15
            _MainTex ("Base (RGB)", 2D) = "white" {}
            _DispTex ("Disp Texture", 2D) = "gray" {}
            _NormalMap ("Normalmap", 2D) = "bump" {}
            _Displacement ("Displacement", Range(0, 1.0)) = 0.3
            _Color ("Color", color) = (1,1,1,0)
            _SpecColor ("Spec color", color) = (0.5,0.5,0.5,0.5)
        }
        SubShader {
            Tags { "RenderType"="Opaque" }
            LOD 300
            
            CGPROGRAM
            #pragma surface surf BlinnPhong addshadow fullforwardshadows vertex:disp tessellate:tessEdge nolightmap
            #pragma target 4.6
            #include "Tessellation.cginc"

            struct appdata {
                float4 vertex : POSITION;
                float4 tangent : TANGENT;
                float3 normal : NORMAL;
                float2 texcoord : TEXCOORD0;
            };

            float _EdgeLength;

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

            sampler2D _DispTex;
            float _Displacement;

            void disp (inout appdata v)
            {
                float d = tex2Dlod(_DispTex, float4(v.texcoord.xy,0,0)).r * _Displacement;
                v.vertex.xyz += v.normal * d;
            }

            struct Input {
                float2 uv_MainTex;
            };

            sampler2D _MainTex;
            sampler2D _NormalMap;
            fixed4 _Color;

            void surf (Input IN, inout SurfaceOutput o) {
                half4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color;
                o.Albedo = c.rgb;
                o.Specular = 0.2;
                o.Gloss = 1.0;
                o.Normal = UnpackNormal(tex2D(_NormalMap, IN.uv_MainTex));
            }
            ENDCG
        }
        FallBack "Diffuse"
    }

Dalam contoh ini, Anda menyebut fungsi UnityEdgeLengthBasedTess dari WordPress.org untuk melakukan semua pekerjaan.

Untuk alasan kinerja, sebut fungsi UnityEdgeLongBasedTessCull, yang melakukan culling patch. Ini membuat naungan sedikit lebih mahal, tetapi menghemat banyak pekerjaan GPU untuk bagian jala yang berada di luar tampilan Kamera.


Phong Tessellation

Phong Tessellation mengubah posisi wajah yang dibagikan sehingga permukaan yang dihasilkan mengikuti mesh normal sedikit. Ini adalah cara yang efektif untuk membuat jala poli rendah menjadi lebih halus.

Naungan permukaan unity dapat mengimbangi Phong tessellation secara otomatis menggunakan directive kompilasi tessphong:VariableName. Berikut adalah contoh naungan:

    Shader "Phong Tessellation" {
        Properties {
            _EdgeLength ("Edge length", Range(2,50)) = 5
            _Phong ("Phong Strengh", Range(0,1)) = 0.5
            _MainTex ("Base (RGB)", 2D) = "white" {}
            _Color ("Color", color) = (1,1,1,0)
        }
        SubShader {
            Tags { "RenderType"="Opaque" }
            LOD 300
            
            CGPROGRAM
            #pragma surface surf Lambert vertex:dispNone tessellate:tessEdge tessphong:_Phong nolightmap
            #include "Tessellation.cginc"

            struct appdata {
                float4 vertex : POSITION;
                float3 normal : NORMAL;
                float2 texcoord : TEXCOORD0;
            };

            void dispNone (inout appdata v) { }

            float _Phong;
            float _EdgeLength;

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

            struct Input {
                float2 uv_MainTex;
            };

            fixed4 _Color;
            sampler2D _MainTex;

            void surf (Input IN, inout SurfaceOutput o) {
                half4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color;
                o.Albedo = c.rgb;
                o.Alpha = c.a;
            }

            ENDCG
        }
        FallBack "Diffuse"
    }

Berikut ini adalah perbandingan antara naungan biasa (dek atas) dan satu yang menggunakan Phong tessellation (deks bawah). Lihat bahwa bahkan tanpa pemetaan perpindahan, permukaan menjadi lebih bulat.


  • 2018–03–20 Login
  • Tessellation for Metal ditambahkan pada 2018.1
Contoh pencahayaan Shader permukaan
Menulis naungan untuk API grafis yang berbeda