
Shader "Holistic/Glass"
{
Properties
{
_MainTex("Texture", 2D) = "white" {}
_BumpMap("Normalmap", 2D) = "bump" {}
_ScaleUV("Scale", Range(1,1000)) = 1
}
SubShader
{
Tags{"Queue" = "Transparent"}
GrabPass{}
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct appdata
{
float4 vertex : POSITION;
float4 uv : TEXCOORD0;
};
struct v2f
{
float2 uv : TEXCOORD0;
float4 uvgrab : TEXCOORD1;
float2 uvbump : TEXCOORD2;
float4 vertex : SV_POSITION;
};
sampler2D _GrabTexture;
float4 _GrabTexture_TexelSize;
sampler2D _MainTex;
float4 _MainTex_ST;
sampler2D _BumpMap;
float4 _BumpMap_ST;
float _ScaleUV;
v2f vert (appdata v)
{
v2f o;
// vertex의 좌표를 클립 공간으로 변환
o.vertex = UnityObjectToClipPos(v.vertex);
// 그래픽 API별 Y축 방향 차이를 보정
#if UNITY_UV_STARTS_AT_TOP
float scale = -1.0;
#else
float scale = 1.0;
#endif
// 투영 좌표 : z(깊이)가 커질수록 → x/w, y/w 값이 작아지게 하여 원근감 표현
// 클립 공간의 x, y를 변환하여 투영 텍스쳐 좌표 생성
o.uvgrab.xy = (float2(o.vertex.x, o.vertex.y*scale) + o.vertex.w) * 0.5;
// tex2Dproj 호출에 필요한 z/w 보간과 w 값 보존을 위해 그대로 전달
o.uvgrab.zw = o.vertex.zw;
// 텍스쳐 uv에 타일링과 오프셋 적용
o.uv = TRANSFORM_TEX(v.uv, _MainTex);
o.uvbump = TRANSFORM_TEX(v.uv, _BumpMap);
return o;
}
// SV_Target: 픽셀 셰이더의 반환값이 최종 화면(또는 렌더 타겟)의 픽셀 색상임을 명시
fixed4 frag (v2f i) : SV_Target
{
half2 bump = UnpackNormal(tex2D(_BumpMap, i.uvbump)).rg;
// _GrabTexture_TexelSize.xy는 UV 기준으로 "1픽셀"이 얼마인지를 알려주는 값이며,
// 이걸 곱해야 왜곡 효과가 해상도에 관계없이 자연스럽게 작동
float2 offset = bump * _ScaleUV * _GrabTexture_TexelSize.xy;
i.uvgrab.xy = offset * i.uvgrab.z + i.uvgrab.xy;
// tex2Dproj : 투영 텍스쳐 좌표를 이용해 샘플링
fixed4 col = tex2Dproj(_GrabTexture, i.uvgrab);
float4 tint = tex2D(_MainTex, i.uv);
col *= tint;
return col;
}
ENDCG
}
}
}
tex2D와 tex2DProj의 차이
| 항목 | tex2D | tex2Dproj |
|---|---|---|
| 입력 타입 | float2 (UV) | float4 (투영 좌표) |
| 내부 동작 | 그대로 사용 | (x / w, y / w)로 계산 |
| 보간 방식 | 선형 보간 (float2 기준) | 투영 보간 (정점 간의 w 보정 포함) |
| 사용 목적 | 일반적인 UV 샘플링 | GrabPass, Projector, ShadowMap 등 투영 필요 시 |
| 필요 조건 | 일반 텍스처 좌표만 있으면 됨 | 클립 공간 또는 투영 좌표 필요 |
| 예시 사용 | 일반 메시 텍스처, 라이트맵 등 | 화면 왜곡, 그림자 투사, 스크린 공간 이펙트 등 |
시스템 예약 시맨틱(System Semantic)
: 각 셰이더 단계에서 "이 값이 어떤 용도로 쓰이는지" GPU에게 알려준다.
| 시맨틱 | 의미 |
|---|---|
SV_Position | 정점 셰이더의 출력 위치 (클립 공간) |
SV_Target | 픽셀 셰이더의 출력 색상 |
SV_Depth | 픽셀 셰이더가 직접 깊이값을 쓸 때 |
SV_VertexID | 정점 인덱스 |
SV_InstanceID | 인스턴싱된 개체의 ID |