"건축은 근사한 형태를 만드는 작업이 아니라 사람들의 삶을 섬세하게 조직하는 일이다." – 정기용

2017/10/29

비 효과 셰이더

하라는 일은 안 하고 멍 때리고 김도님 방송 보다가 보라는 게임은 안 보고 직업병인지 배경의 비 때문에 빛이 굴절되어 보이는 효과는 어떻게 만들었을까 혼자 막 생각하다가 비슷하게 만들어보고 싶어서 생각나는 데로 만들기 시작했습니다.

The End Is Nigh (2017)

처음에는 배경만 저런 줄 알았는데 캐릭터와 적(이 맞는지 모르겠지만)들 스프라이트도 저렇게 울렁거리는 걸 보니 필요한 레이어만 따로 떼서 전체 화면을 후처리를 하는 것 같네요. 단순히 효과만 보려는 거라 저렇게까지 할 생각은 없으니 그냥 텍스처 몇 개로 해보기로 합니다. 영상이 계속 움직여서 알아보기 힘든데 한 프레임씩 보면 내리고 있는 비와 울렁거리고 있는 부분은 따로 움직이고 있습니다. 그렇게까지 디테일하게 만들 필요는 없어서 그런 것 같네요. 먼저 울렁이는 효과를 만들어 보기로 합니다.

먼저 쿼드를 하나 만들고 텍스처를 하나 띄우는 간단한 셰이더를 만들었습니다. 영상을 보면 화면을 세로로 잘게 잘라서 살짝 올리고 내리고 이걸 계속하고 있는데 노이즈를 쓴 건지 그래프를 쓴 건지 뭔지는 모르겠는데 귀찮으니(사실 할 줄 몰라서) 그냥 룩업 텍스처로 해서 먼저 화면을 잘라서 올리고 내리고를 해보기로 합니다.

전체가 기본 중간 회색인 이미지를 잘게 부분을 나눈 뒤 밝기를 약간 올리고 내린 텍스처를 만들고 이 색상 값을 기본 텍스처의 uv의 y 값에 더해 줍니다. 일단 원하는 대로 잘려서 나오는군요. 이걸 이제 혼자 움직이게 해보면 되겠네요.

무식하게 그냥 sin 그래프로 흔들었더니 계속 보고 있으니 너무 어지럽네요. 원본 영상을 찬찬히 보니 무식하게 계속 흔드는 게 아니고 흔들릴 때도 있고 아닐 때도 있고 그렇군요. sin 그래프는 빼고 시간 값하고 룩업 텍스처를 하나 더 추가해서 다시 고쳐 봅니다.

아직 비 텍스처가 없어서 조금 어설퍼 보이기는 하는데 아까보다는 괜찮아졌네요. 이제 비 텍스처를 추가하고 스크롤 시키면 될 것 같습니다.

원본은 바닥에 물이 튀는 파티클도 있고 한데 거기까지는 할 필요가 없을 거 같고 아주 똑같지는 않지만, 간단히 보려고 한 거니 이 정도면 된 것 같네요.


(응용편)

(스승님 이 힘은 대체 무엇인가요?! 끼요요요욧! / 몰라… 뭐야 그거… 무서워…)
(비디오 빨리감기)
(수면)

셰이더 전체 코드

shader "newbieCAT/test" {
  properties{
    _MainTex("main texture", 2d) = "white" {}
    _RainTex("rain texture", 2d) = "white" {}
    _ShiftTex("shift texture", 2d) = "white" {}
    _NoiseTex("noise texture", 2d) = "white" {}

    _RainColour("rain colour", Color) = (0.25, 0.25, 0.25, 1)

    _RainSpeed("rain speed", float) = 1.0
    _ShiftWidth("shift width", float) = 2.0
    _ShiftStrength("shift strength", float) = 0.015
    _NoisePickSpeedX("noise pick speed x", float) = 5.0
    _NoisePickSpeedY("noise pick speed y", float) = 0.5
  }

  subShader{
    tags { "RenderType" = "Transparent" "Queue" = "Geometry" "IgnoreProjector" = "True" }

    pass {
      CGPROGRAM

      #include "UnityCG.cginc"

      #pragma vertex vs
      #pragma fragment fs

      sampler2D _MainTex;
      sampler2D _RainTex;
      sampler2D _ShiftTex;
      sampler2D _NoiseTex;

      float4 _RainColour;

      float _RainSpeed;
      float _ShiftWidth;
      float _ShiftStrength;
      float _NoisePickSpeedX;
      float _NoisePickSpeedY;

      struct appdata {
        float4 vertex : POSITION;
        float2 texcoord : TEXCOORD0;
      };

      struct v2f {
        float4 vertex : SV_POSITION;
        float2 texcoord : TEXCOORD0;
      };

      v2f vs(appdata i)
      {
        v2f o;

        o.vertex = UnityObjectToClipPos(i.vertex);
        o.texcoord = i.texcoord;

        return o;
      }

      fixed4 fs(v2f i) : SV_TARGET
      {
        float shift = tex2D(_ShiftTex, i.texcoord * _ShiftWidth).r;
        float noise = tex2D(_NoiseTex, float2(shift + _Time.x * _NoisePickSpeedX, _Time.x * _NoisePickSpeedY)).r * _ShiftStrength;

        fixed4 rain = tex2D(_RainTex, float2(i.texcoord.x + sin(_Time.x), i.texcoord.y * 0.5 + _Time.y * _RainSpeed)) * _RainColour;
        fixed4 main = tex2D(_MainTex, float2(i.texcoord.x, i.texcoord.y + noise));

        return main + rain;
      }

      ENDCG
    }
  }

  fallBack "Diffuse"
}

댓글 남기기 | cat > 타닥타닥 | tag > , ,

댓글 남기기

* 표시된 곳은 반드시 입력해주세요