美文网首页
天空球+云+山

天空球+云+山

作者: 星易乾川 | 来源:发表于2018-07-10 11:30 被阅读0次

    我们平时做天空球的uv接缝贴图不好处理,看了官方shader的源码,结合借鉴了candycat美女的动态噪波云效果,做了一个天空球

    Unity中Lighting里的天空盒的UV是纯圆形的

    image

    官方shader中是用CUBEMap实现的,我也在这基础上修改

    image

    分为几大块:背景上下渐变色+一层云半透cubemap+中景山脉半透cubemap+前景动态噪波云

    image
    Properties {
        _SkyColor0 ("Sky Color Up", Color) = (0, 0, 1, 1)
        _SkyColor1 ("Sky Color Down", Color) = (0.5, 0.5, 1, 1)
        [Space(50)]
        [NoScaleOffset] _Tex ("BackCloudCubemap   (HDR)", Cube) = "grey" {}
        _Tint ("Tint Color", Color) = (1, 1, 1, 1)
        [Gamma] _Exposure ("Exposure", Range(0, 8)) = 1.0
        _RotationSpeed ("RotationSpeed", Range(0, 10)) = 2.51
        [Space(50)]
        [NoScaleOffset] _Tex2 ("MiddleTex", Cube) = "grey" {}
        _UVY ("UVY", Range(-1, 3.0)) = 0
        [Space(50)]
        [NoScaleOffset] _Octave0 ("Octave 0", 2D) = "white" {}
        [NoScaleOffset] _Octave1("Octave 1", 2D) = "white" {}
        [NoScaleOffset] _Octave2 ("Octave 2", 2D) = "white" {}
        [NoScaleOffset] _Octave3 ("Octave 3", 2D) = "white" {}
        _CloudColor ("Cloud Color", Color) = (1, 1, 1, 0.7)
        _Speed ("Speed", Range(-1.0, 1.0)) = -0.49
        _Emptiness ("Emptiness", Range(0.0, 1.0)) = 0.441
        _Sharpness ("Sharpness", Range(0.0, 1.0)) = 0.711
    }
    SubShader {
        Tags { "Queue"="Background" "RenderType"="Background" "PreviewType"="Skybox" }
        Cull Off ZWrite Off
      //渐变背景色pass
                Pass { 
                CGPROGRAM
                #pragma vertex vert
                #pragma fragment frag
                
                #include "UnityCG.cginc"
                fixed _BackTexSpeed;
                fixed4 _SkyColor0;
                fixed4 _SkyColor1;
                sampler2D _Octave0;
                sampler2D _Octave3;
                float _UVY;
                struct appdata {
                    float4 vertex : POSITION;
                    float2 texcoord : TEXCOORD0;        
                };
                struct v2f {
                    float4 pos : SV_POSITION;
                    half2 uv : TEXCOORD0;
                    float2 texcoord1 : TEXCOORD1;
                };
    
                v2f vert (appdata v) {
                    v2f o;
                    o.pos = UnityObjectToClipPos(v.vertex);
                    o.uv = v.texcoord;
                    o.uv = half2(o.uv.x+_Time.y*_BackTexSpeed,o.uv.y);
                    o.texcoord1 = v.texcoord;
                o.texcoord1 = half2(o.texcoord1.x,o.texcoord1.y + _UVY);
                    return o;
                }
                
                fixed4 frag (v2f i) : SV_Target {
                    fixed4 col;
                    col.rgb = lerp(_SkyColor1.rgb, _SkyColor0.rgb, pow(i.uv.y, 1));                 
                    col.a = 1.0;                     
                    return  col;
                }
                ENDCG
            }
    //背景云pass
        Pass {
                Blend SrcAlpha OneMinusSrcAlpha 
                CGPROGRAM
                #pragma vertex vert
                #pragma fragment frag       
                #include "UnityCG.cginc"
                half4 _Tint;
                 half4 _Tex_HDR;
                half4 _Tint1;
                samplerCUBE _Tex;
                float _Rotation;    
                fixed _Emptiness;
                fixed _Sharpness;
                sampler2D _Main_Textures;
                float4 _Main_Textures_ST;       
                float _RotationSpeed;
                struct appdata {
                    float4 vertex : POSITION;
                    float3 texcoord : TEXCOORD0;
                     UNITY_VERTEX_INPUT_INSTANCE_ID
                };
                struct v2f {
                    float4 pos : SV_POSITION;       
                    half4 uv0 : TEXCOORD0;
                    half4 uv1 : TEXCOORD1;
                    half2 uv2 : TEXCOORD2;
                    float3 texcoord : TEXCOORD3;
                    float3 texcoord1 : TEXCOORD4;
                     UNITY_VERTEX_OUTPUT_STEREO
                };
                //旋转矩阵
             float3 RotateAroundYInDegrees (float3 vertex, float degrees)
            {
                float alpha = degrees * UNITY_PI / 180.0;
                float sina, cosa;
                sincos(alpha, sina, cosa);
                float2x2 m = float2x2(cosa, -sina, sina, cosa);
                return float3(mul(m, vertex.xz), vertex.y).xzy;
            }
    
                v2f vert (appdata v) {
                    v2f o;
                UNITY_SETUP_INSTANCE_ID(v);
                            UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
                        
                float3 rotated = RotateAroundYInDegrees(v.vertex, _Rotation+_Time.y*_RotationSpeed);
                o.pos = UnityObjectToClipPos(rotated);
                o.texcoord = v.vertex.xyz;
        
                    return o;
                }
                fixed4 frag (v2f i) : SV_Target {
                                half4 tex = texCUBE (_Tex, i.texcoord) ;
                    half3 c = DecodeHDR (tex, _Tex_HDR) ;
                    c = c * _Tint.rgb * unity_ColorSpaceDouble.rgb ;
                    return half4(c,tex.a);
                }
                ENDCG
            }   
           //动态云和中景山
            Pass {
                Blend SrcAlpha OneMinusSrcAlpha 
                
                CGPROGRAM
                #pragma vertex vert
                #pragma fragment frag       
                #include "UnityCG.cginc"
                half4 _Tint;
                half4 _Tint1;
                float _Rotation;
                fixed4 _CloudColor;
                sampler2D _Octave0;
                sampler2D _Octave1;
                sampler2D _Octave2;
                sampler2D _Octave3;
                float4 _Octave0_ST;
                float4 _Octave1_ST;
                float4 _Octave2_ST;
                float4 _Octave3_ST;
                float _Speed;
                fixed _Emptiness;
                fixed _Sharpness;       
                samplerCUBE _Tex2;
                float _UVY;
                struct appdata {
                    float4 vertex : POSITION;
                    float3 texcoord : TEXCOORD0;
                     UNITY_VERTEX_INPUT_INSTANCE_ID
                };
                struct v2f {
                    float4 pos : SV_POSITION;       
                    half4 uv0 : TEXCOORD0;
                    half4 uv1 : TEXCOORD1;
                    half2 uv2 : TEXCOORD2;
                    float3 texcoord : TEXCOORD3;
                    float3 texcoord1 : TEXCOORD4;
                     UNITY_VERTEX_OUTPUT_STEREO
                };
                 float3 RotateAroundYInDegrees (float3 vertex, float degrees)
            {
                float alpha = degrees * UNITY_PI / 180.0;
                float sina, cosa;
                sincos(alpha, sina, cosa);
                float2x2 m = float2x2(cosa, -sina, sina, cosa);
                return float3(mul(m, vertex.xz), vertex.y).xzy;
            }
                v2f vert (appdata v) {
                    v2f o;
                    UNITY_SETUP_INSTANCE_ID(v);
                                    UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
                    o.pos = UnityObjectToClipPos(v.vertex);
                    o.texcoord1 = v.vertex.xyz;
                        o.texcoord1 = half3(o.texcoord1.x,o.texcoord1.y + _UVY,o.texcoord1.z);  
                    o.uv0.xy = TRANSFORM_TEX(v.texcoord, _Octave0) + _Time.x * 1.0 * _Speed * half2(-1.0, 0.5);
                    o.uv0.zw = TRANSFORM_TEX(v.texcoord, _Octave1) + _Time.x * 1.5 * _Speed * half2(-1.0, 1.0);
                    o.uv1.xy = TRANSFORM_TEX(v.texcoord, _Octave2) + _Time.x * 2.0 * _Speed * half2(-1.0, -1.0);
                    o.uv1.zw = TRANSFORM_TEX(v.texcoord, _Octave3) + _Time.x * 2.5 * _Speed * half2(-1.0, -0.5);        
                    return o;
                }   
                fixed4 frag (v2f i) : SV_Target {
                    fixed4 col = 0;
                    float4 n0 = tex2D(_Octave0, i.uv0.xy);
                    float4 n1 = tex2D(_Octave1, i.uv0.zw);
                    float4 n2 = tex2D(_Octave2, i.uv1.xy);
                    float4 n3 = tex2D(_Octave3, i.uv1.zw);
                          //分型布朗函数计算
                    float4 fbm = 0.5 * n0 + 0.25 * n1+ 0.125 * n2 + 0.0625 * n3;
                    fbm = (clamp(fbm, _Emptiness, _Sharpness) -  _Emptiness)/(_Sharpness - _Emptiness);
                          //光线穿透云层半透
                    fixed4 ray = fixed4(0.0, 0.2, 0.4, 0.6);
                    fixed amount = dot(max(fbm - ray, 0), fixed4(0.25, 0.25, 0.25, 0.25));
                    col.rgb = amount  +  2.0 * (1.0 - amount) * 0.4;
                    col.a = amount * 1.5;   
                    half4 tex2 = texCUBE (_Tex2, i.texcoord1);                              
                return  tex2*(1-col.a) + col*col.a * _CloudColor;
                }
                ENDCG
            }   
    }
    Fallback Off
    }
    

    相关文章

      网友评论

          本文标题:天空球+云+山

          本文链接:https://www.haomeiwen.com/subject/lejfpftx.html