Unity Shader 实现简单的宝石渲染

入职实习的第一周过去了,感觉还是相当不错的,找到工作了也就不用再顶着高压去学习了,快乐。
闲话少说,先上效果图啦。
Unity Shader 实现简单的宝石渲染_第1张图片
效果还是很棒的,但这不是我写的,哈哈,这个代码可以完全说就是抄Unity的案例。Assset Store搜Gem Shader就可以找到了。
我主要还是分析它的原理,虽然原理我也是不太懂,但是渲染出的效果可以说很不错了。
原理上基本都是参考这一篇演示的(Phat Lewt: Drawing a Diamond),来头貌似还是挺大,国内不知道找没找得到这篇演示,我上传到百度云了Phat Lewt: Drawing a Diamond觉得有需要的可以看一下。
我就基于Phat Lewt: Drawing a Diamond的谷歌翻译说下原理吧。
Unity Shader 实现简单的宝石渲染_第2张图片
1.渲染背面的折射颜色到颜色缓冲。
2.将背面的折射颜色与正面进行混合.(正面的有折射和反射以及高光)
3.绘制耀斑。
大功告成!是不是很简单…个屁…还有各种射来射去的光线是用一个立方体贴图来模拟的,Gem Shader里就有这个立方体贴图。
以下是代码,虽然Unity的案例和演示有些出入但我感觉总体相差不大,还有一点就是Unity用菲涅尔效应实现了类似于高光的效果。

Shader "MyShader/Diamond"
{
    Properties
    {
        _Color("Color",Color)=(1,1,1,1)
        _ReflectionStrength("Reflection Strength",Range(0.0,2.0))=1.0
        _EnvironmentLight ("Environment Light", Range(0.0,2.0)) = 1.0
        _Emission ("Emission", Range(0.0,2.0)) = 0.0
        [NoScaleOffset] _RefractTex ("Refraction Texture", Cube) = "" {}
    }
    SubShader
    {
        Tags { "Queue" = "Transparent" }
        LOD 100

        Pass
        {
            Cull  Front
            ZWrite Off 

            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag

            #include "UnityCG.cginc"

            struct v2f
            {
                float4 pos:SV_POSITION ;
                float3 uv:TEXCOORD0  ; 
            };

            fixed4 _Color;
            samplerCUBE _RefractTex;
            half _EnvironmentLight;
            half _Emission;

            v2f vert ( appdata_base  v)
            {
                v2f o;
                o.pos = UnityObjectToClipPos(v.vertex);
                float3 viewDir=normalize(ObjSpaceViewDir(v.vertex));
                o.uv = -reflect(viewDir,v.normal);
                o.uv=mul(unity_ObjectToWorld,float4(o.uv,0));
                return o;
            }

            fixed4 frag (v2f i) : SV_Target
            {
                half3 refraction=texCUBE(_RefractTex,i.uv).rgb*_Color.rgb;
                half4 reflection=UNITY_SAMPLE_TEXCUBE(unity_SpecCube0,i.uv);
                reflection.rgb=DecodeHDR(reflection,unity_SpecCube0_HDR);
                half3 multiplier=reflection.rgb*_EnvironmentLight+_Emission;
                return half4(refraction.rgb*multiplier.rgb,1.0f);
            }
            ENDCG
        }

        Pass
        {
            ZWrite On
            Blend One One

            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag

            #include "UnityCG.cginc"

            struct v2f
            {
                float4 pos:SV_POSITION ;
                float3 uv:TEXCOORD0  ; 
                half fresnel:TEXCOORD1  ;
            };

            fixed4 _Color;
            samplerCUBE _RefractTex;
            half _ReflectionStrength;
            half _EnvironmentLight;
            half _Emission;

            v2f vert ( appdata_base  v)
            {
                v2f o;
                o.pos = UnityObjectToClipPos(v.vertex);
                float3 viewDir=normalize(ObjSpaceViewDir(v.vertex));
                o.uv = -reflect(viewDir,v.normal);
                o.uv=mul(unity_ObjectToWorld,float4(o.uv,0));
                o.fresnel=1-saturate(dot(v.normal,viewDir));
                return o;
            }

            fixed4 frag (v2f i) : SV_Target
            {
               /* unity_SpecCube0保存了环境的立体贴图(天空盒和反射探针形成的立体贴图)
                UNITY_SAMPLE_TEXCUBE 用于采样立体贴图
                DecodeHDR将高动态贴图转为正常RGB,如果导入的不是HDR贴图,就没有变化*/
                
                half3 refraction=texCUBE(_RefractTex,i.uv).rgb*_Color.rgb;
                half4 reflection=UNITY_SAMPLE_TEXCUBE(unity_SpecCube0,i.uv);
                reflection.rgb=DecodeHDR(reflection,unity_SpecCube0_HDR);
                half3 reflection2=reflection*_ReflectionStrength*i.fresnel;
                half3 multiplier=reflection.rgb*_EnvironmentLight+_Emission;
                return half4(reflection2+refraction.rgb*multiplier.rgb,1.0f);
            }
            ENDCG 
        }

        UsePass "VertexLit/SHADOWCASTER"
    }
}

耀斑效果是用屏幕后处理实现的,参考的是Unity3D-实现屏幕特效十字耀斑不得不说这个效果真的是杠杠的,以后我可能回单独写一篇耀斑的效果实现过程以及我自己的理解。以下是加上耀斑的效果图(左边的最明显,而且好像有点错位,尴尬):
Unity Shader 实现简单的宝石渲染_第3张图片

好了,本篇博客到此结束,感谢你的阅读,如有错误欢迎指正。

你可能感兴趣的:(Unity,Shader,Unity,Shader,宝石渲染,屏幕后处理,耀斑)