Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
17
Help us understand the problem. What is going on with this article?
@aa_debdeb

【Unity】GrabPassを用いた屈折(Refraction)シェーダー

More than 1 year has passed since last update.

Unityのシェーダーで、GrabPassを用いてガラスのような物体を疑似的に表現する方法です。

fast.gif

まず、"Queue"="Transparent"でGrabPassを行うことで、不透明なオブジェクトやスカイボックスをレンダリングした背面をテクスチャ_BackgroundTextureに書き込んでおきます。
フラグメントシェーダーでは組込関数refractを用いて計算した屈折方向に適当にレイを進めてから、_BackgroundTextureからサンプリングすることで屈折を再現しています。

シェーダー内ではSchlickの近似式を用いてフレネル反射係数を計算し、反射光と屈折光をブレンドしていますが、これは屈折係数が小さい場合見た目にあまり影響がないので必要ないかもしれません。

Refraction.Shader
Shader "Refraction"
{
    Properties
    {
        _RefractionIndex("Refraction Index", Range(1.0, 3.0)) = 1.33
        _Distance("Distance", Float) = 10.0
        _Tint("Tint", Color) = (0.8, 0.5, 0.5)
        _SpecularColor ("Specular Color", Color) = (1, 1, 1)
        _Shiness ("Shiness", Float) = 10.0
    }
    SubShader
    {
        Tags {
            "RenderType" = "Transparent"
            "Queue" = "Transparent"
        }

        GrabPass
        {
            "_BackgroundTexture"
        }

        Pass
        {
            Tags {"LightMode" = "ForwardBase"}

            ZWrite Off

            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag

            #include "UnityCG.cginc"
            #include "Lighting.cginc"

            struct appdata
            {
                float4 pos : POSITION;
                float3 normal : NORMAL;
            };

            struct v2f
            {
                float4 pos : SV_POSITION;
                float3 worldPos : TEXCOORD0;
                float3 normal : TEXCOORD1;
            };

            float _RefractionIndex;
            float _Distance;
            float3 _Tint;
            float3 _SpecularColor;
            float _Shiness;
            sampler2D _BackgroundTexture;

            v2f vert (appdata v)
            {
                v2f o;
                o.pos = UnityObjectToClipPos(v.pos);
                o.worldPos = mul(unity_ObjectToWorld, v.pos).xyz;
                o.normal = UnityObjectToWorldNormal(v.normal);
                return o;
            }

            float schlickFresnel(float cosine) {
                float r0 = (1 - _RefractionIndex) / (1 + _RefractionIndex);
                r0 = r0 * r0;
                return r0 + (1 - r0) * pow(1 - cosine, 5);
            }

            fixed4 frag (v2f i) : SV_Target
            {
                float3 normal = normalize(i.normal);
                float3 viewDir = normalize(i.worldPos - _WorldSpaceCameraPos.xyz);

                float3 reflectDir = reflect(viewDir, normal);
                float3 reflectCol = UNITY_SAMPLE_TEXCUBE(unity_SpecCube0, reflectDir);

                float3 refractDir = refract(viewDir, normal, 1.0 / _RefractionIndex);
                float3 refractPos = i.worldPos + refractDir * _Distance;
                float4 refractScreenPos = mul(UNITY_MATRIX_VP, float4(refractPos, 1.0));
                float2 screenUv = (refractScreenPos.xy / refractScreenPos.w) * 0.5 + 0.5;
                #if UNITY_UV_STARTS_AT_TOP
                screenUv.y = 1.0 - screenUv.y;
                #endif

                float3 refractCol = tex2D(_BackgroundTexture, screenUv).xyz;
                float3 spec = pow(max(0.0, dot(normalize(_WorldSpaceLightPos0.xyz), reflectDir)), _Shiness) * _SpecularColor * _LightColor0;

                float f = schlickFresnel(max(0.0, dot(-viewDir, normal)));

                float3 c = (1.0 - f) * refractCol * _Tint + f * (reflectCol + spec);

                return float4(c, 1.0);
            }
            ENDCG
        }
    }
}
17
Help us understand the problem. What is going on with this article?
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
aa_debdeb
Engineer, Creative Coder。Dentsu Craft Tokyo所属。

Comments

No comments
Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account Login
17
Help us understand the problem. What is going on with this article?