(UnityShader) 16 URP Shader Graph
- Nobody
- 2020년 2월 18일
- 2분 분량
최종 수정일: 2020년 4월 3일
Refraction
이번 포스트에서는 물 아래 강 바닥 표면의 굴절을 표현 해보도록 하겠습니다.

노드 작성 이전에 준비해야 할 과정이 있습니다. Project settings - Graphics 에서 파이프라인 에셋을 클릭하여 세부정보를 변경합니다.

Opaque Texture에 체크 합니다.

쉐이더 그래프로 가서 Texture 2d asset 노드를 생성하고 Property로 변환합니다.

쉐이더 그래프로 굴절을 구현하는데 가장 중요한 부분입니다. 블랙보드에 가서 Reference를 _CameraOpaqueTexture 라고 써줍니다. 대소문자 구분합니다.

Sample Texture 2d에 위와 같이 연결하고 RGBA를 Unlit 마스터의 color에 연결합니다.

이렇게하면 카메라로 보는 스크린의 이미지를 Plane에 매핑되었다는걸 알 수 있습니다.
그리고 당연히 스크린 이미지에도 UV 좌표가 존재합니다.

스크린 UV라고 부릅니다. 쉐이더 그래프에서는 스크린 ‘포지션’ 노드입니다.

스크린 UV를 그대로 출력하면 어떻게 될까요?

위 아래로 화면을 움직였더니 Plane의 색이 변화합니다.

카메라를 좀 더 가까이 갔더니 이런 형태가 되었습니다.
OpenGL 방식과 똑같이 왼쪽 아래는 0,0 오른쪽 위는 1,1인 화면에 고정된 UV 라는 것입니다.

그렇다면 스크린 포지션을 텍스처의 UV에 연결하면?

매우 이상한 결과가 되어 버렸습니다. 이렇게 되버린 이유를 파헤쳐 봅시다.
이전에는 카메라가 보는 스크린 이미지를 Plane에 매핑하였습니다. 하지만 지금은 마치 거울을 마주보게 해놓은 것과 같습니다.
현재 상황은 카메라가 보는 스크린 이미지를 스크린 포지션에 맞춰 매핑하였지만 ‘Plane 자기 자신’도 카메라에 촬영이 되는 상황이라 무한히 자기 자신을 반복해서 그리는 것입니다.

이전에 프로퍼티의 Reference를 _CameraOpaqueTexture로 설정했습니다. 말 그대로 Opaque 만 텍스처로 그린다는 뜻입니다. 즉 Plane이 Opaque만 아니면 됩니다.

마스터 노드에서 표면을 Transparent로 바꿔주면 정상 작동합니다.


물 표면에 사용했던 노말맵을 굴절에도 똑같이 사용할 수 있습니다. 적당히 R,G 값의 강도를 조절한 후 스크린 포지션에 더해버리면 됩니다.


노말 맵의 UV 오프셋에 Time 함수를 더해주면 굴절도 흐르게 됩니다.
굴절을 얻었으니 이제 굴절과 반사를 더해주기만 하면 됩니다.
이전 포스트에서 프레넬 노드를 작성해서 큐브맵을 반사 하는 표면 아래로 땅바닥이 보이게 알파로 처리했다면
이제는 _CameraOpaqueTexture 를 이용하여 표면 아래 땅바닥에 대한 텍스처 자체를 저희가 가지고 있기 때문에 알파를 사용하지 않아도 됩니다.

큐브맵 반사 + 퐁 리플렉션과 _CameraOpaqueTexture를 프레넬 값을 이용하여 Lerp 함수로 섞어서 컬러로 반환합니다.

여기에 Depth 버퍼를 이용해서 물 표면이 다른 물체와 충돌할 때 파도와 거품이 생기도록 응용 할 수 있습니다.
물 쉐이더는 쉐이더 작성자의 실력과 요구하는 퀄리티에 따라 셀 수도 없을 만큼 많은 응용 방식들이 존재합니다. 쉐이더 그래프에서 다룰 수 있는 매우 기초적인 부분은 저희가 모두 살펴봤습니다.
더욱 공부하고 싶으신 분이라면 구글링을 해보면 관련 논문 자료들이 많이 있으니 시도해 보시길 바랍니다. 여기까지 잘 따라오셨다면 분명히 노드를 작성하는데 어려움이 없을 것입니다.




쓰니분의 쉐이더 포스팅이 원리를 이해하는데 큰 도움이 되었습니다. 다른 자료에서는 기술의 내용이 너무 전문적이어서 이해가 어렵거나 간소화된 과정으로 인해 중간중간 의문점이 드는 구간을 해소하지 못하는 경우가 많았는데 전에 학습했을때 구멍이 뚫려 있던 지식들이 다 채워지는 느낌이었습니다. 포스팅 감사합니다.