そろそろShaderをやるパート18 ジオメトリーシェーダーでポリゴンごとに色を変える

5 min read読了の目安(約4700字

そろそろShaderをやります

そろそろShaderをやります。そろそろShaderをやりたいからです。
パート100までダラダラ頑張ります。10年かかってもいいのでやります。
100記事分くらい学べば私レベルの初心者でもまあまあ理解できるかなと思っています。

という感じでやってます。

※初心者がメモレベルで記録するので
 技術記事としてはお力になれないかもしれません。

下準備

下記参考
そろそろShaderをやるパート1 Unite 2017の動画を見る(基礎知識~フラグメントシェーダーで色を変える)

デモ

ランダムなRGBを各ポリゴンに適用してます。

Shaderサンプル

Shader "Custom/GeometryColorful"
{
    SubShader
    {
        Tags
        {
            "RenderType"="Opaque"
        }

        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma geometry geom
            #pragma fragment frag

            #include "UnityCG.cginc"

            struct appdata
            {
                float4 vertex : POSITION;
            };

            appdata vert(appdata v)
            {
                return v;
            }

            struct g2f
            {
                float4 vertex : SV_POSITION;
                fixed4 color : COLOR;
            };

            //ランダムな値を返す
            float rand(float2 co)
            {
                return frac(sin(dot(co.xy, float2(12.9898, 78.233))) * 43758.5453);
            }

            // ジオメトリシェーダー
            [maxvertexcount(3)]
            void geom(triangle appdata input[3],inout TriangleStream<g2f> stream)
            {
                //1枚のポリゴンの中心
                float3 center = (input[0].vertex + input[1].vertex + input[2].vertex) / 3;
		//ランダムな値
                float r = rand(center.xy);
                float g = rand(center.xz);
                float b = rand(center.yz);

                [unroll]
                for (int i = 0; i < 3; i++)
                {
                    appdata v = input[i];
                    g2f o;
                    o.vertex = UnityObjectToClipPos(v.vertex);
                    o.color = fixed4(r,g,b,1);
                    stream.Append(o);
                }
            }

            fixed4 frag(g2f i) : SV_Target
            {
                return i.color;
            }
            ENDCG
        }
    }
}

[unroll]以前でRGB用にそれぞれランダムな値を定義しています。

これにより一枚のポリゴンを描画する際の色がランダムに適用されます。
次のポリゴンの描画処理の際にまたランダムな値が生成、適用されるので
各ポリゴンが最終的に異なる色となるという流れです。

デモ2

ランダムな値を生成する位置を変えてみました。
(ブラーに見えるのはGIFが荒いだけで本来はもっとぱっきりしてます)

Shaderサンプル

Shader "Custom/GeometryColorful"
{
    SubShader
    {
        Tags
        {
            "RenderType"="Opaque"
        }

        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma geometry geom
            #pragma fragment frag

            #include "UnityCG.cginc"

            struct appdata
            {
                float4 vertex : POSITION;
            };

            appdata vert(appdata v)
            {
                return v;
            }

            struct g2f
            {
                float4 vertex : SV_POSITION;
                fixed4 color : COLOR;
            };

            //ランダムな値を返す
            float rand(float2 co)
            {
                return frac(sin(dot(co.xy, float2(12.9898, 78.233))) * 43758.5453);
            }

            // ジオメトリシェーダー
            [maxvertexcount(3)]
            void geom(triangle appdata input[3],inout TriangleStream<g2f> stream)
            {
                [unroll]
                for (int i = 0; i < 3; i++)
                {
                    appdata v = input[i];
                    g2f o;
                    o.vertex = UnityObjectToClipPos(v.vertex);
		    //ランダムな値
                    float r = rand(v.vertex.xy);
                    float g = rand(v.vertex.xz);
                    float b = rand(v.vertex.yz);
                    o.color = fixed4(r,g,b,1);
                    stream.Append(o);
                }
            }

            fixed4 frag(g2f i) : SV_Target
            {
                return i.color;
            }
            ENDCG
        }
    }
}

何が変わったのかというとランダムな値を生成するタイミングです。

[unroll]以後はポリゴンの各頂点に対して行う処理を記述している箇所です。
その中でランダムな色を定義して各頂点に対して色を当てはめています。

全ての頂点にランダムな色を当てはめているので
頂点と頂点の間をラスタライズして
グラデーションのようになっているのがわかります。

【参考リンク】:そろそろShaderをやるパート3 Unite 2017の動画を見る(ラスタライズ)

参考リンク

ジオメトリシェーダ入門
HoloLens で使える Near Clip 表現について解説してみた
【Unity】Gemoetry Shaderで3Dモデルがさぁ〜って消えるソースを紹介【影あり】