LoginSignup
3
3

More than 5 years have passed since last update.

UnityのGLSLで半透明を扱う

Last updated at Posted at 2013-10-06

まだ細かい書式について把握しきれていませんが、とりあえず以下のようにすると半透明になります。
詳細についてはこちらの記事(GLSL Programming/Unity/Transparency)を参考に。

Shader "Custom/Transparency" {
    SubShader {
        Tags { "Queue" = "Transparent" }
        Pass {
            //最初のパスは背面のみレンダリング。つまり内側。
            Cull Front

            //他のオブジェクトをはじかないように深度バッファの書き込みをしない
            ZWrite Off

            //アルファブレンディングを使う
            Blend SrcAlpha OneMinusSrcAlpha         
            GLSLPROGRAM

            #ifdef VERTEX

            void main()
            {
                gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
            }

            #endif

            #ifdef FRAGMENT

            void main()
            {
                //4番目のアルファ成分が重要。
                //下記は半透明のグリーン。
                gl_FragColor = vec4(0.0, 1.0, 0.0, 0.3);
            }

            #endif

            ENDGLSL
        }

        Pass {
            //二回目のパスは表のみレンダリング
            Cull Back

            ZWrite Off

            Blend SrcAlpha OneMinusSrcAlpha

            GLSLPROGRAM

            #ifdef VERTEX

            void main()
            {
                gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
            }

            #endif

            #ifdef FRAGMENT

            void main()
            {
                gl_FragColor = vec4(0.0, 1.0, 0.0, 0.3);
            }

            #endif

            ENDGLSL
        }
    }
}

ポイントは3点。
冒頭のTags { "Queue" = "Transparent" }と、Blend SrcAlpha OneMinuesSrcAlphaの部分です。
Tagsの詳細についてはドキュメントを。

ここのTagsで指定しているQueueは、ドキュメントではレンダリングの順序を指定するもののようです。
つまり、Queue = Transparetとタグが付けられたシェーダを持つオブジェクトのレンダリング順(キュー)が最後の方に回される、ということでしょう。(そうしないと半透明にならない)

原文では

this render queue is rendered after Geometry and AlphaTest, in back-to-front order. Anything alpha-blended (i.e. shaders that don't write to depth buffer) should go here (glass, particle effects).

となっています。

Blendの方はフラグメントにある元の色と新しい色とをどう合成するかの指定です。
つまり、現在計算中のソースカラーと呼ばれる色と、フレームバッファに書き込まれているディスティネーションカラーとの合成比率を指定するものです。

ドキュメントの原文は

One of the operations is the blending stage, which combines the color of the fragment (as specified in gl_FragColor), which is called the “source color”, with the color of the corresponding pixel that is already in the framebuffer, which is called the “destination color” (because the “destination” of the resulting blended color is the framebuffer).

となっています。
ちなみにサンプルの合成方法を計算式にすると以下のようなものになります。

vec4 result = vec4(gl_FragColor.a) * gl_FragColor + vec4(1.0 - gl_FragColor.a) * pixel_color;

これで半透明を実現しているわけですね。(ソースカラーのアルファ値が1なら半透明にならなくなる)

さて、最後のポイントがPass { … }をふたつ書いている点です。
これは表のレンダリングと裏のレンダリングを分けている部分です。
普通、負荷軽減のために裏面のポリゴンは描かれません。
ゲームとかしてカメラが変な所に入るとポリゴンが消えたりするあれです。

しかし半透明ということは裏面もレンダリングされないとおかしなことになってしまいます。
そこでPassをふたつ設定し、それぞれ表と裏を両方レンダリングしている、というわけです。

ちなみに上記のシェーダを適用すると以下のように表と裏で違う色になるようになります。

front-back-facing.jpg

3
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
3