LoginSignup
5
6

More than 5 years have passed since last update.

Unity でShaderの勉強 その5

Last updated at Posted at 2016-12-24

久しぶりにShaderを書いてみたらかなり忘れていました X(

とりあえず一番シンプルなShaderを書いてみる

失敗した。。。

失敗しているShader
Shader "Custom/Test1" {
    SubShader {
        Pass {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag

            float4 vert(float3 pos : POSITION ) : SV_POSITION  {
                return mul(UNITY_MATRIX_MVP,pos);
            }


            float4 frag() : SV_TARGET {
                return float4(1,1,1,1);
            }

            ENDCG
        }
    }
}

Test1マテリアルをCubeにつけてみたけど何も描画されない・・・。
スクリーンショット 2016-12-25 2.12.57.png

どうやらfloat4 vert(float3 pos : POSITION ) : SV_POSITIONが間違っているとのこと
float3 posだとだめでfloat4 posだと正常に描画された。

スクリーンショット 2016-12-25 2.14.29.png

色をプロパティで指定できるようにする

Propertiesタグを指定してみた。

Shader "Custom/Test1" {
    Properties {
        _Color("Output Color" , COLOR) = (1,1,1,1)
    }
    SubShader {
        Pass {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag

            float4 _Color;

            float4 vert(float4 pos : POSITION ) : SV_POSITION  {
                return mul(UNITY_MATRIX_MVP,pos);
            }


            float4 frag() : SV_TARGET {
                return _Color;
            }

            ENDCG
        }
    }
}

ちゃんと色が反映されてる :)
スクリーンショット 2016-12-25 2.18.38.png

常に手前に描画されるようにする

普通のCubeを用意
スクリーンショット 2016-12-25 2.19.39.png

常に手前に描画されるようにするためにTest1ShaderのZTestが常に勝つようにする。
ZTestとZWriteの設定をつけた。

Shader "Custom/Test1" {
    Properties {
        _Color("Output Color" , COLOR) = (1,1,1,1)
    }
    SubShader {
        ZTest Always
        ZWrite On
        Pass {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag

            float4 _Color;

            float4 vert(float4 pos : POSITION ) : SV_POSITION  {
                return mul(UNITY_MATRIX_MVP,pos);
            }


            float4 frag() : SV_TARGET {
                return _Color;
            }

            ENDCG
        }
    }
}

うまくいった。
スクリーンショット 2016-12-25 2.25.38.png

たぶんZTestをAlwaysにしなくても描画順序を遅らせるだけで常に手前に描画されるはず。

QueueをGeometry+1にして普通のCubeよりレンダリングを遅らせる。
```
Shader "Custom/Test1" {
Properties {
_Color("Output Color" , COLOR) = (1,1,1,1)
}
SubShader {
Tags { "Queue" = "Geometry+1"}

    Pass {
        CGPROGRAM
        #pragma vertex vert
        #pragma fragment frag

        float4 _Color;

        float4 vert(float4 pos : POSITION ) : SV_POSITION  {
            return mul(UNITY_MATRIX_MVP,pos);
        }


        float4 frag() : SV_TARGET {
            return _Color;
        }

        ENDCG
    }
}

}
```

結果は失敗
スクリーンショット 2016-12-25 2.41.38.png
ZTestとZWriteの指定をしなかったのでデフォルト値ZTest LEqual, ZWrite Onが使用され、
ZTestが行われて負けたのでそもそもレンダリングがされず普通のCubeの方が手前に描画された、
のだと思う。

ZTest処理はQueueで指定した順番で行われるんだっけ?

  • ZTest -> レンダリング可能か決まる -> Queueの順番にレンダリングされる
  • Queueの順番に各種処理が走る -> ZTest -> レンダリング可能か決まる -> ZBufferに残ったピクセルがレンダリングされる どっちだったか忘れてしまったので確認。

もし後者ならQueueを小さくしてZTest Alwaysにしたときに普通のCubeの方が手前に描画されるはず。

Shader "Custom/Test1" {
    Properties {
        _Color("Output Color" , COLOR) = (1,1,1,1)
    }
    SubShader {
        Tags { "Queue" = "Geometry-1"}
        ZTest Always
        ZWrite On
        Pass {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag

            float4 _Color;

            float4 vert(float4 pos : POSITION ) : SV_POSITION  {
                return mul(UNITY_MATRIX_MVP,pos);
            }


            float4 frag() : SV_TARGET {
                return _Color;
            }

            ENDCG
        }
    }
}

結果:普通のCubeの方が手前に描画された。
スクリーンショット 2016-12-25 2.51.55.png

処理の流れはこうだと思う。
- Queue=Geometry-1である赤Cubeの処理が最初に始まる。
- 赤CubeはZTest Alwaysなので常にZTestに勝ち、ZBufferに赤ピクセル情報が書き込まれる。
- Queue=Geometryである普通のCubeの処理が始まる。
- 普通のCubeのZTestはLEqualなので赤Cubeのピクセル情報が入ったZBufferに勝つ。
- ZBufferに普通のCubeのピクセル情報を書き込む。
- 最後にZBufferに残った赤Cubeと普通のCubeのピクセルを画面に映す。

半透明をやりたい

半透明は確かブレンドするんだったはず・・・!

Shader "Custom/Test1" {
    Properties {
        _Color("Output Color" , COLOR) = (1,1,1,1)
    }
    SubShader {
        Tags { "Queue" = "Transparent"}
        ZTest LEqual
        ZWrite Off
        Blend SrcAlpha OneMinusSrcAlpha
        Pass {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag

            float4 _Color;

            float4 vert(float4 pos : POSITION ) : SV_POSITION  {
                return mul(UNITY_MATRIX_MVP,pos);
            }


            float4 frag() : SV_TARGET {
                return _Color;
            }

            ENDCG
        }
    }
}

結果たぶんOK。透き通った。
スクリーンショット 2016-12-25 2.58.23.png

5
6
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
5
6