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"
}
반응형
'산대특 > 게임 그래픽 프로그래밍' 카테고리의 다른 글
[LearnShader] Ramp Texture로 로봇 눈 깜박이게 만들기 (0) | 2024.02.23 |
---|---|
[LearnShader] 알파 블렌드(Alpha blend) (0) | 2024.02.23 |
[LearnShader] 프레넬을 사용해서 1Pass로 외곽선 만들기 (0) | 2024.02.21 |
[LearnShader] NPR 렌더링 - 외곽선의 두께와 색깔을 조절해보기 (0) | 2024.02.21 |
[LearnShader] NPR 렌더링 - 2Pass로 외곽선 그리기 (0) | 2024.02.21 |