실행 이미지

 

Shader "Custom/Water"
{
    Properties
    {
        _NormalMap("NormalMap", 2D) = "bump"{} // 노멀 맵, 물의 표면 질감을 더 리얼하게 표현
        _CubeMap("CubeMap", Cube) = ""{} // 큐브 맵, 반사와 굴절 효과를 위해 사용
    }
        SubShader
    {
        // 이 쉐이더가 투명한 렌더링 타입에 속하며, 렌더링 큐에서의 순서가 "Transparent"임을 명시
        Tags { "RenderType" = "Transparent" "Queue" = "Transparent" }

        // 현재 화면을 텍스처로 캡처  (후처리 효과에 주로 사용)
        GrabPass {}

        CGPROGRAM
        // surface 쉐이더 함수를 사용하여 _Water 표면 속성을 정의하고, alpha:fade를 통해 투명도를 처리. vertex 함수로 vert를 사용
        #pragma surface surf _Water alpha:fade vertex:vert
        #pragma target 3.0

        // 사용될 샘플러를 선언
        samplerCUBE _CubeMap;
        sampler2D _NormalMap;
        sampler2D _GrabTexture; // GrabPass에 의해 생성된 텍스처

        // 버텍스 쉐이더 함수: 정점의 위치를 조정하여 물결 효과
        void vert(inout appdata_full v)
        {
            // v.texcoord를 기반으로 정점의 y 위치를 조정하여 물결을 생성
            float movementX = sin(abs(v.texcoord.x * 2 - 1) * 12 + _Time.y) * 0.1;
            float movementY = sin(abs(v.texcoord.y * 2 - 1) * 12 + _Time.y) * 0.1;
            v.vertex.y += (movementX + movementY) / 2;
        }

        // SurfaceOutput 구조체를 정의하여 쉐이더에 필요한 입력을 정의
        struct Input
        {
            float2 uv_NormalMap;
            float3 worldNormal;
            float3 viewDir;
            float4 screenPos;
            INTERNAL_DATA
        };

        // 표면 쉐이더 함수: 물의 표면 속성을 계산
        void surf(Input IN, inout SurfaceOutput o)
        {
            // 노멀 맵에서 노멀을 가져와서 변형을 주어 물의 표면을 더욱 다이나믹하게 표현
            float3 n1 = UnpackNormal(tex2D(_NormalMap,IN.uv_NormalMap + _Time.x * 0.1));
            float3 n2 = UnpackNormal(tex2D(_NormalMap,IN.uv_NormalMap - _Time.x * 0.1));

            // 최종 노멀을 계산
            o.Normal = (n1 + n2) / 2;

            // 큐브맵을 사용하여 반사 색상을 계산
            //float3 refColor = texCUBE(_CubeMap, WorldNormalVector(IN, o.Normal));

            // 화면 좌표를 사용하여 굴절 효과를 구현
            float2 screenUV = IN.screenPos.rgb / IN.screenPos.w;
            
            // 0.1 = 굴절률, 0.7 = 밝기
            float3 refraction = tex2D(_GrabTexture, screenUV + o.Normal.xy * 0.1) * 0.7; 

            // Rim 광효과를 계산하여 물의 가장자리에 밝기를 추가
            float rim = saturate(dot(o.Normal, IN.viewDir));
            rim = pow(1 - rim, 1.5);

            // 최종 색상과 알파 값을 계산
            //o.Emission = (refColor * rim + refraction) * 0.5;
            //o.Alpha = rim + 0.2;
            o.Emission = refraction;
            o.Alpha = 1;
          
        }

        // 사용자 정의 조명 모델 함수: 물의 반사 및 굴절 효과에 대한 조명을 계산
        float4 Lighting_Water(SurfaceOutput s, float3 lightDir, float3 viewDir, float atten)
        {
            float4 final;

            // 스페큘러(highlight) 효과를 계산
            float3 h = normalize(lightDir + viewDir);
            float3 spec = saturate(dot(s.Normal, h));
            spec = pow(spec, 3);

            // 최종 색상과 알파 값을 설정
            final.rgb = spec;
            final.a = s.Alpha;

            return final;
        }
        ENDCG
    }
        // 이 쉐이더가 지원되지 않는 경우 사용할 대체 쉐이더를 지정
            FallBack "Legacy Shaders/Transparent/VertexLit"
}
반응형

+ Recent posts