Unity 幾何着色器
shader
Geometry Shader
幾何着色器
Unity 幾何着色器
若是學習不能帶來價值,那將毫無心義html
簡介
在頂點和片斷着色器之間有一個可選的着色器,叫作幾何着色器(Geometry Shader)。幾何着色器以一個或多個表示爲一個單獨基本圖形(primitive)即圖元的頂點做爲輸入,好比能夠是一個點或者三角形。幾何着色器在將這些頂點發送到下一個着色階段以前,能夠將這些頂點轉變爲它認爲合適的內容。幾何着色器有意思的地方在於它能夠把(一個或多個)頂點轉變爲徹底不一樣的基本圖形(primitive),從而生成比原來多得多的頂點。編程
輸入
幾何着色器階段可將整個圖元做爲輸入,並可以在輸出上生成頂點。
必須首先指定單次調用幾何着色器輸出的頂點的最大數量(每一個圖元調用幾何着色器)。這能夠經過使用如下屬性語法在着色器定義以前設置最大頂點數:
[maxvertexcount(N)]
其中N是幾何着色器爲單個調用輸出的頂點的最大數量。幾何着色器能夠在每次調用時輸出的頂點數量是可變的,但不能超過定義的最大值。出於性能考慮,最大頂點數應儘量小; [NVIDIA08]指出,當GS輸出在1到20個標量之間時,能夠實現GS的性能峯值,若是GS輸出在27-40個標量之間,則性能降低50%。每次調用的標量輸出數是最大頂點輸出數和輸出頂點類型結構中的標量數的乘積。api
基本圖形 |
描述 |
point |
繪製GL_POINTS基本圖形的時候(1) |
line |
當繪製GL_LINES或GL_LINE_STRIP(2)時 |
lineadj |
輸入圖元具備鄰接線段(4) |
triangle |
GL_TRIANGLES, GL_TRIANGLE_STRIP或GL_TRIANGLE_FAN(3) |
triangleadj |
輸入圖元具備鄰接三角形(6) |
輸出
幾何着色器經過將頂點附加到輸出流對象來一次輸出一個頂點。 流的拓撲由固定聲明肯定,選擇 TriangleStream、LineStream 和 PointStream 做爲 GS 階段的輸出。app
聲明
-
- [maxvertexcount(3)]
- void geometry_shader(point VS_OUTPUT IN[1], inout TriangleStream<GS_
- OUTPUT> triStream) { }
示例
不作處理
幾何着色器位於頂點着色器和片元着色器之間,下面示例中幾何着色器沒作多餘的效果,僅僅至關於默認的數據傳遞。jsp
- Shader "ShaderCookbook/幾何着色器/SimplePoint"
- {
- Properties
- {
- _MainTex ("Texture", 2D) = "white" {}
- }
- SubShader
- {
- Tags { "RenderType"="Opaque" }
- LOD 100
-
- Pass
- {
- CGPROGRAM
- #pragma vertex vert
-
- #pragma geometry geom
- #pragma fragment frag
-
- #include "UnityCG.cginc"
-
- struct appdata
- {
- float4 vertex : POSITION;
- float2 uv : TEXCOORD0;
- };
-
-
- struct v2g{
- float4 vertex:SV_POSITION;
- float2 uv:TEXCOORD0;
- };
-
-
- struct g2f
- {
- float2 uv : TEXCOORD0;
- float4 vertex : SV_POSITION;
- };
-
- sampler2D _MainTex;
- float4 _MainTex_ST;
-
- v2g vert (appdata v)
- {
- v2g o;
- o.vertex = UnityObjectToClipPos(v.vertex);
- o.uv = TRANSFORM_TEX(v.uv, _MainTex);
- return o;
- }
-
-
- [maxvertexcount(3)]
- void geom(triangle v2g input[3],inout TriangleStream<g2f> outStream){
- for(int i=0;i<3;i++){
- g2f o=(g2f)0;
- o.vertex=input[i].vertex;
- o.uv=input[i].uv;
-
-
- outStream.Append(o);
- }
-
-
- outStream.RestartStrip();
- }
-
- fixed4 frag (g2f i) : SV_Target
- {
-
- fixed4 col = tex2D(_MainTex, i.uv);
- return col;
- }
- ENDCG
- }
- }
- }
-
點
示例一:單純的點
點
- Shader "ShaderCookbook/幾何着色器/OnlyPoint"
- {
- Properties
- {
- _MainTex ("Texture", 2D) = "white" {}
- }
- SubShader
- {
- Tags { "RenderType"="Opaque" }
- LOD 100
-
- Pass
- {
- CGPROGRAM
- #pragma vertex vert
-
- #pragma geometry geom
- #pragma fragment frag
-
- #include "UnityCG.cginc"
-
- struct appdata
- {
- float4 vertex : POSITION;
- float2 uv : TEXCOORD0;
- };
-
-
- struct v2g{
- float4 vertex:SV_POSITION;
- float2 uv:TEXCOORD0;
- };
-
-
- struct g2f
- {
- float2 uv : TEXCOORD0;
- float4 vertex : SV_POSITION;
- };
-
- sampler2D _MainTex;
- float4 _MainTex_ST;
-
- v2g vert (appdata v)
- {
- v2g o;
- o.vertex = UnityObjectToClipPos(v.vertex);
- o.uv = TRANSFORM_TEX(v.uv, _MainTex);
- return o;
- }
-
-
- [maxvertexcount(4)]
- void geom(point v2g input[1],inout PointStream<g2f> outStream){
- g2f o=(g2f)0;
- o.vertex=input[0].vertex;
- o.uv=input[0].uv;
-
- outStream.Append(o);
- }
-
- fixed4 frag (g2f i) : SV_Target
- {
-
- fixed4 col = tex2D(_MainTex, i.uv);
- return col;
- }
- ENDCG
- }
- }
- }
-
示例二:散裂
這裏須要注意的是咱們經過以v[0]爲原點構建兩個向量,經過這兩個向量咱們能夠自定義點。編輯器
由s,t構成的仿射座標系
炸裂
- Shader "ShaderCookbook/GeometryShader/分解" {
- Properties {
- _MainTex("Texture", 2 D) = "white" {}
- _Height("Length", float) = 0.5
- _Offset("Offset", float) = 0.1
-
- _StripColor("StripColor", Color) = (1, 1, 1, 1)
- _OutColor("OutColor", Color) = (1, 1, 1, 1)
- _InColor("InColor", Color) = (1, 1, 1, 1)
- }
- SubShader {
- Cull off
- Pass {
- Tags {
- "RenderType" = "Opaque"
- }
-
- CGPROGRAM# pragma vertex vert# pragma fragment frag#include "UnityCG.cginc"
-
- struct appdata {
- float4 vertex: POSITION;
- float2 uv: TEXCOORD0;
- };
-
- struct v2f {
- float4 vertex: SV_POSITION;
- float4 objPos: TEXCOORD1;
- float2 uv: TEXCOORD0;
- };
-
- sampler2D _MainTex;
- float4 _MainTex_ST;
- float _Height;
- float _Offset;
- fixed4 _StripColor;
-
- v2f vert(appdata v) {
- v2f o;
- o.vertex = UnityObjectToClipPos(v.vertex);
- o.objPos = v.vertex;
- o.uv = v.uv;
- return o;
- }
-
- fixed4 frag(v2f i): SV_Target {
- fixed4 col = tex2D(_MainTex, i.uv);
-
- clip(_Height + _Offset - i.objPos.y);
-
- if (i.objPos.y > _Height)
- col = _StripColor;
-
- return col;
- }
- ENDCG
- }
-
- pass {
- Tags {
- "RenderType" = "Opaque"
- }
-
- CGPROGRAM# pragma vertex vert# pragma geometry geome# pragma fragment frag#include "UnityCG.cginc"
-
- fixed4 _OutColor;
- fixed4 _InColor;
- float _Height;
- float _Offset;
-
- struct appdata {
- float4 vertex: POSITION;
- float2 uv: TEXCOORD0;
- float3 normal: NORMAL;
- };
-
- struct v2g {
- float4 objPos: TEXCOORD0;
- float3 normal: NORMAL;
- };
-
- struct g2f {
- float4 vertex: SV_POSITION;
- fixed4 col: TEXCOORD0;
- };
-
- void ADD_VERT(float4 v, g2f o, inout PointStream < g2f > outstream) {
- o.vertex = v;
- outstream.Append(o);
- }
-
- v2g vert(appdata v) {
- v2g o;
- o.objPos = v.vertex;
- o.normal = v.normal;
- return o;
- }
-
- [maxvertexcount(6)]
- void geome(triangle v2g input[3], inout PointStream < g2f > outStream) {
- g2f o;
-
-
- float4 vertex = (input[0].objPos + input[1].objPos + input[2].objPos) / 3.0;
- float3 normal = (input[0].normal + input[1].normal + input[2].normal) / 3.0;
-
- if (vertex.y < _Height + _Offset)
- return;
-
-
- float4 s = input[1].objPos - input[0].objPos;
- float4 t = input[2].objPos - input[0].objPos;
-
- o.col = _OutColor * 2;
- for (int i = 0; i < 3; i++) {
- input[i].objPos.xyz += input[i].normal * (vertex.y - _Height);
- input[i].objPos = UnityObjectToClipPos(input[i].objPos);
- ADD_VERT(input[i].objPos, o, outStream);
- }
-
- o.col = _InColor * 2;
-
-
- float4 v[3];
-
- v[0] = 0.2 * s + 0.2 * t;
- v[1] = 0.4 * s + 0.6 * t;
- v[2] = 0.6 * s + 0.4 * t;
-
- for (int i = 0; i < 3; i++) {
- v[i].xyz += normal * (vertex.y - _Height);
- v[i] = UnityObjectToClipPos(v[i]);
- ADD_VERT(v[i], o, outStream);
- }
- }
-
- fixed4 frag(g2f i): SV_Target {
- fixed4 col = i.col;
- return col;
- }
- ENDCG
-
- }
- }
- }
線
線
示例:wire frame
- Shader "ShaderCookbook/幾何着色器/TriangleLine"
- {
- Properties
- {
- _MainTex ("Texture", 2D) = "white" {}
- }
- SubShader
- {
- Tags { "RenderType"="Opaque" }
- LOD 100
-
- Pass
- {
- CGPROGRAM
- #pragma vertex vert
-
- #pragma geometry geom
- #pragma fragment frag
-
- #include "UnityCG.cginc"
-
- struct appdata
- {
- float4 vertex : POSITION;
- float2 uv : TEXCOORD0;
- };
-
-
- struct v2g{
- float4 vertex:SV_POSITION;
- float2 uv:TEXCOORD0;
- };
-
-
- struct g2f
- {
- float2 uv : TEXCOORD0;
- float4 vertex : SV_POSITION;
- };
-
- sampler2D _MainTex;
- float4 _MainTex_ST;
-
- v2g vert (appdata v)
- {
- v2g o;
- o.vertex = UnityObjectToClipPos(v.vertex);
- o.uv = TRANSFORM_TEX(v.uv, _MainTex);
- return o;
- }
-
-
- [maxvertexcount(3)]
-
- void geom(triangle v2g input[3],inout LineStream<g2f> outStream){
- g2f o=(g2f)0;
- o.vertex=input[0].vertex;
- o.uv=input[0].uv;
-
- outStream.Append(o);
-
-
- o.vertex=input[1].vertex;
- o.uv=input[1].uv;
-
- outStream.Append(o);
-
- o.vertex=input[2].vertex;
- o.uv=input[2].uv;
- outStream.Append(o);
-
- }
-
- fixed4 frag (g2f i) : SV_Target
- {
-
- fixed4 col = tex2D(_MainTex, i.uv);
- return col;
- }
- ENDCG
- }
- }
- }
-
面
enter description here
示例:尖刺
- Shader "ShaderCookbook/GeometryShader/尖刺" {
- Properties {
- _MainTex("Texture", 2D) = "white" {}
- _Length("Length", float) = 0.5
- }
- SubShader {
- Tags {
- "RenderType" = "Opaque"
- }
- LOD 100
-
- Pass {
- CGPROGRAM
- #pragma vertex vert
- #pragma geometry geom
- #pragma fragment frag
-
- #pragma multi_compile_fog
- #include "UnityCG.cginc"
-
- struct appdata {
- float4 vertex: POSITION;
- float2 uv: TEXCOORD0;
- };
-
- struct v2g {
- float4 pos: SV_POSITION;
- float2 uv: TEXCOORD0;
- };
-
- struct g2f {
- float2 uv: TEXCOORD0;
- float4 vertex: SV_POSITION;
- };
-
- sampler2D _MainTex;
- float4 _MainTex_ST;
- float _Length;
-
-
- void ADD_VERT(float3 v, g2f o, inout TriangleStream < g2f > tristream) {
- o.vertex = UnityObjectToClipPos(v);
- tristream.Append(o);
- }
-
-
- void ADD_TRI(float3 p0, float3 p1, float3 p2, g2f o, inout TriangleStream < g2f > tristream) {
- ADD_VERT(p0, o, tristream);
- ADD_VERT(p1, o, tristream);
- ADD_VERT(p2, o, tristream);
- tristream.RestartStrip();
- }
-
-
- v2g vert(appdata v) {
- v2g o = (v2g) 0;
- o.pos = v.vertex;
- o.uv = TRANSFORM_TEX(v.uv, _MainTex);
- return o;
- }
-
- [maxvertexcount(9)]
- void geom(triangle v2g input[3], inout TriangleStream < g2f > outStream) {
- g2f o;
-
-
- float3 s = (input[1].pos - input[0].pos).xyz;
- float3 t = (input[2].pos - input[0].pos).xyz;
-
- float3 normal = normalize(cross(s, t));
-
- float3 centerPos = (input[0].pos.xyz + input[1].pos.xyz + input[2].pos.xyz) / 3.0;
- float2 centerUv = (input[0].uv + input[1].uv + input[2].uv) / 3.0;
-
- o.uv = centerUv;
-
- centerPos += normal * _Length * abs(sin(_Time.y * 5));
-
- ADD_TRI(input[0].pos, centerPos, input[2].pos, o, outStream);
- ADD_TRI(input[2].pos, centerPos, input[1].pos, o, outStream);
- ADD_TRI(input[1].pos, centerPos, input[0].pos, o, outStream);
-
-
- }
- fixed4 frag(g2f i): SV_Target {
- fixed4 col = tex2D(_MainTex, i.uv);
- return col;
- }
- ENDCG
- }
- }
- }
Other
項目工程:連接: https://pan.baidu.com/s/1eGk6GHIfWzIFcAX6pxTGRA 提取碼: fv75工具
解壓密碼:https://fgk.pw/i/eqm2Bj23236性能
eqm2Bj23236
參考一
參考二
參考三
可視化shader編程工具學習
這裏推薦一款可視化shader編程工具,對美術同窗很是友好,就像建模工具中的材質編輯器同樣ui