본문 바로가기

TA공부는 제때제때/Unity Shader

유니티쉐이더 - 간단한 물 쉐이더

AOS프로젝트를 개발하는 도중, 


맵 중간에 강물을 표현해야 하는 일이 있었는데,


유튜브, 구글에서 찾아보며 찰랑거리는 쉐이더를 짰다.


인터넷에 나와있는 예시들중 가장 간단했던 예제의 원리는 간단했다


코사인 그래프에 버텍스의 y좌표, x좌표+시간(_Time)을 각각 대입한 수를 더한 뒤,


이 값을 버텍스의 y좌표에 대입하는것이었다


그렇게 짜게 된 코드


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
Shader "Custom/Water" {
    Properties {
        _MainTex("MainTex", 2D) = "white" {}
        _Color("Color", Color) = (1,1,1,1)
        _Strength("Strength", Range(0,2)) = 1.0
        _Speed("Speed", Range(-200200)) = 100
        _Opacity("Opacity", Range(01)) = 0.1
    }
    SubShader {
        //렌더링 타입을 투명성이 있는 타입으로 설정
        Tags { "RenderType" = "Transparent" }
        Pass
        {
            LOD 200
            
            Cull Off
            //깊이 버퍼 연산 X -> 뒤쪽 오브젝트가 있는 그대로 렌더링됨
            ZWrite Off
            //블렌딩 모드를 float4(1,1,1,1)- 알파 로 변경-> 투명 구현
            Blend SrcAlpha OneMinusSrcAlpha
            
            CGPROGRAM
            
            #pragma vertex vert
            #pragma fragment frag
            
            uniform sampler2D _MainTex;
            
            uniform float4 _Color;
            uniform float _Strength;
            uniform float _Speed;
            uniform float _Opacity;
            
            struct appdata
            {
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;
            };
            
            struct v2f
            {
                float4 vertex : SV_POSITION;
                float2 uv : TEXCOORD0;
            };
            
            v2f vert(appdata i)
            {
                v2f o;
                
                float4 worldPos = mul(unity_ObjectToWorld, i.vertex);
                
                float displacement = (cos(worldPos.y) + cos(worldPos.x + (_Speed * _Time.x * 0.5f)));
                worldPos.y = worldPos.y + (displacement * _Strength);
                
                o.vertex = mul(UNITY_MATRIX_VP, worldPos);
                o.uv = i.uv;
                
                return o;            
            }
            
            float4 frag(v2f i) : SV_Target
            {
                //메인 텍스*컬러로 아웃풋 설정
                float4 col = tex2D(_MainTex, i.uv) * _Color;
                
                //아웃풋.rgb+오퍼시티(알파) 리턴
                return float4(col.rgb , _Opacity);
            }
            
            ENDCG
            
        }
    }
    FallBack "Diffuse"
}
cs
웨 ShaderLab은 지원을 제대로 안해주는것인가....ㅠㅠ


우선 물이니까 투명하게 보이게 하기 위해 렌더링 타입을 Transparent로 설정한다(11번줄)


그 후 물의 뒤쪽(바닥)을 그대로 렌더링하기위해 깊이 버퍼 연산을 끄고(18번줄)


블렌딩 옵션을 변경했다(19번줄)


(소스보면 Color외에 Opacity를 따로 받는데,


투명구현이 안되서 애먹을때 이렇게 하면 될줄 알고 써놨다가 아직 지웠었다...)



다시 보니 고칠 부분이 너무 많은거 같다..