// ============================================================ // 2-Pass 셰이더: Standard 조명 + XRay 실루엣 // Pass 1: 일반 렌더링 (조명, 그림자, 텍스처 전부 적용) // Pass 2: 벽 뒤에서만 실루엣 색상으로 표시 // ============================================================ Shader "Custom/StandardWithXRay" // 셰이더를 선언할거에요 -> Custom/StandardWithXRay 이름으로 { Properties // 머티리얼 인스펙터에 노출할 속성들을 정의할거에요 { // === 메인 텍스처 === _Color ("메인 색상", Color) = (1,1,1,1) // 속성을 정의할거에요 -> 메인 색상 틴트를 _MainTex ("텍스처 (Albedo)", 2D) = "white" {} // 속성을 정의할거에요 -> 메인 텍스처를 // === Standard 셰이더 속성 === _Glossiness ("Smoothness", Range(0,1)) = 0.3 // 속성을 정의할거에요 -> 표면 매끄러움을 _Metallic ("Metallic", Range(0,1)) = 0.0 // 속성을 정의할거에요 -> 금속성을 _BumpMap ("노멀맵", 2D) = "bump" {} // 속성을 정의할거에요 -> 노멀맵 텍스처를 _BumpScale ("노멀 강도", Float) = 1.0 // 속성을 정의할거에요 -> 노멀맵 강도를 // === XRay 실루엣 속성 === _SilhouetteColor ("실루엣 색상", Color) = (0.0, 0.5, 1.0, 0.3) // 속성을 정의할거에요 -> 벽 뒤 실루엣 색상을 _SilhouetteInflation ("실루엣 팽창", Float) = 0.0001 // 속성을 정의할거에요 -> 실루엣 메시 팽창량을 } SubShader // 서브셰이더를 시작할거에요 -> 렌더링 패스들을 묶는 { Tags { "RenderType"="Opaque" "Queue"="Geometry" } // 태그를 설정할거에요 -> 불투명 지오메트리로 LOD 200 // LOD를 설정할거에요 -> 200 레벨로 // ================================================ // PASS 1: XRay 실루엣 (먼저 그려서 벽 뒤에서만 보임) // ================================================ Pass // 패스를 시작할거에요 -> 실루엣 렌더링 패스를 { Name "XRaySilhouette" // 이름을 설정할거에요 -> 패스 이름을 Tags { "LightMode"="Always" } // 태그를 설정할거에요 -> 항상 렌더링으로 // 핵심: ZTest Greater = 다른 오브젝트에 가려진 부분만 그림 ZTest Greater // 깊이 테스트를 설정할거에요 -> 가려진 부분만 통과하게 ZWrite Off // 깊이 쓰기를 끌거에요 -> 실루엣이 다른 렌더링에 영향 안 주게 Blend SrcAlpha OneMinusSrcAlpha // 블렌딩을 설정할거에요 -> 알파 블렌딩으로 반투명 처리 CGPROGRAM // CG 프로그램을 시작할거에요 #pragma vertex vert // 버텍스 셰이더를 지정할거에요 -> vert 함수를 #pragma fragment frag // 프래그먼트 셰이더를 지정할거에요 -> frag 함수를 #include "UnityCG.cginc" // 유니티 셰이더 유틸을 포함할거에요 fixed4 _SilhouetteColor; // 변수를 선언할거에요 -> 실루엣 색상을 float _SilhouetteInflation; // 변수를 선언할거에요 -> 메시 팽창량을 struct appdata // 구조체를 정의할거에요 -> 입력 버텍스 데이터를 { float4 vertex : POSITION; // 변수를 선언할거에요 -> 버텍스 위치를 float3 normal : NORMAL; // 변수를 선언할거에요 -> 버텍스 노멀을 }; struct v2f // 구조체를 정의할거에요 -> 버텍스에서 프래그먼트로 전달할 데이터를 { float4 pos : SV_POSITION; // 변수를 선언할거에요 -> 클립 공간 위치를 }; v2f vert(appdata v) // 버텍스 셰이더를 정의할거에요 { v2f o; // 출력 구조체를 선언할거에요 // 노멀 방향으로 살짝 팽창 (Z-fighting 방지) float3 inflated = v.vertex.xyz + v.normal * _SilhouetteInflation; // 위치를 팽창할거에요 -> 노멀 방향으로 o.pos = UnityObjectToClipPos(float4(inflated, 1.0)); // 변환할거에요 -> 클립 공간으로 return o; // 반환할거에요 -> 결과를 } fixed4 frag(v2f i) : SV_Target // 프래그먼트 셰이더를 정의할거에요 { return _SilhouetteColor; // 반환할거에요 -> 실루엣 색상을 } ENDCG // CG 프로그램을 끝낼거에요 } // ================================================ // PASS 2: Standard 조명 렌더링 (Surface Shader) // ================================================ CGPROGRAM // CG 프로그램을 시작할거에요 -> Surface Shader용 // Surface Shader 선언: Lambert 대신 Standard (PBR) 사용 #pragma surface surf Standard fullforwardshadows // 서피스 셰이더를 선언할거에요 -> Standard 조명 모델로 #pragma target 3.0 // 셰이더 모델을 지정할거에요 -> 3.0으로 sampler2D _MainTex; // 변수를 선언할거에요 -> 메인 텍스처 샘플러를 sampler2D _BumpMap; // 변수를 선언할거에요 -> 노멀맵 샘플러를 half _Glossiness; // 변수를 선언할거에요 -> 매끄러움 값을 half _Metallic; // 변수를 선언할거에요 -> 금속성 값을 half _BumpScale; // 변수를 선언할거에요 -> 노멀 강도를 fixed4 _Color; // 변수를 선언할거에요 -> 메인 색상을 struct Input // 구조체를 정의할거에요 -> 서피스 셰이더 입력 데이터를 { float2 uv_MainTex; // 변수를 선언할거에요 -> 메인 텍스처 UV를 float2 uv_BumpMap; // 변수를 선언할거에요 -> 노멀맵 UV를 }; void surf(Input IN, inout SurfaceOutputStandard o) // 서피스 함수를 정의할거에요 -> 픽셀별 재질 속성을 설정하는 { // 텍스처 색상 * 틴트 색상 fixed4 c = tex2D(_MainTex, IN.uv_MainTex) * _Color; // 색상을 계산할거에요 -> 텍스처 × 메인 색상으로 o.Albedo = c.rgb; // 값을 설정할거에요 -> 표면 색상을 o.Alpha = c.a; // 값을 설정할거에요 -> 투명도를 // PBR 속성 o.Metallic = _Metallic; // 값을 설정할거에요 -> 금속성을 o.Smoothness = _Glossiness; // 값을 설정할거에요 -> 매끄러움을 // 노멀맵 (설정된 경우) o.Normal = UnpackScaleNormal(tex2D(_BumpMap, IN.uv_BumpMap), _BumpScale); // 값을 설정할거에요 -> 노멀맵을 언팩해서 } ENDCG // CG 프로그램을 끝낼거에요 } // Standard 셰이더의 그림자 캐스터 등 대체 패스 사용 FallBack "Standard" // 폴백을 설정할거에요 -> Standard 셰이더로 }