Version: Unity 6.0 (6000.0)
언어 : 한국어
빌트인 렌더 파이프라인의 반사 셰이더 예시
빌트인 렌더 파이프라인의 삼평면 텍스처링 셰이더 예시

빌트인 렌더 파이프라인의 노멀 맵 텍스처링 셰이더 예시

노멀 맵 은 추가 지오메트리를 생성하지 않고도 오브젝트에 추가 디테일을 생성하는 데 사용되는 경우가 많습니다. 노멀 맵 텍스처로 환경을 반사하는 셰이더를 생성하는 방법을 알아보겠습니다.

이제 수학이 정말 복잡해지기 시작하므로 몇 단계로 나누어 진행하겠습니다. 위 셰이더에서 반사 방향은 버텍스 셰이더에서 각 버텍스당 계산되었으며 프래그먼트 셰이더는 반사 프로브 큐브맵 룩업만 수행했습니다. 그러나 노멀 맵을 사용하기 시작하면 표면 노멀 자체가 픽셀당 기준으로 계산되어야 합니다. 즉 환경이 각 픽셀마다 어떻게 반사되는지도 계산해야 합니다.

이제 ‘탄젠트 공간’이라는새로운 내용도 알아야 합니다 노멀 맵 텍스처는 대개 모델의 ‘표면을 따라가는’ 좌표 공간으로 표현됩니다. 셰이더에서는 탄젠트 공간 기반 벡터를 알고 텍스처의 노멀 벡터를 읽고 월드 공간으로 변환한 후 위의 셰이더에서 모든 연산을 수행해야 합니다. 이제 시작해 보겠습니다.

Shader "Unlit/SkyReflection Per Pixel"
{
    Properties {
        // normal map texture on the material,
        // default to dummy "flat surface" normalmap
        _BumpMap("Normal Map", 2D) = "bump" {}
    }
    SubShader
    {
        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #include "UnityCG.cginc"

            struct v2f {
                float3 worldPos : TEXCOORD0;
                // these three vectors will hold a 3x3 rotation matrix
                // that transforms from tangent to world space
                half3 tspace0 : TEXCOORD1; // tangent.x, bitangent.x, normal.x
                half3 tspace1 : TEXCOORD2; // tangent.y, bitangent.y, normal.y
                half3 tspace2 : TEXCOORD3; // tangent.z, bitangent.z, normal.z
                // texture coordinate for the normal map
                float2 uv : TEXCOORD4;
                float4 pos : SV_POSITION;
            };

            // vertex shader now also needs a per-vertex tangent vector.
            // in Unity tangents are 4D vectors, with the .w component used to
            // indicate direction of the bitangent vector.
            // we also need the texture coordinate.
            v2f vert (float4 vertex : POSITION, float3 normal : NORMAL, float4 tangent : TANGENT, float2 uv : TEXCOORD0)
            {
                v2f o;
                o.pos = UnityObjectToClipPos(vertex);
                o.worldPos = mul(_Object2World, vertex).xyz;
                half3 wNormal = UnityObjectToWorldNormal(normal);
                half3 wTangent = UnityObjectToWorldDir(tangent.xyz);
                // compute bitangent from cross product of normal and tangent
                half tangentSign = tangent.w * unity_WorldTransformParams.w;
                half3 wBitangent = cross(wNormal, wTangent) * tangentSign;
                // output the tangent space matrix
                o.tspace0 = half3(wTangent.x, wBitangent.x, wNormal.x);
                o.tspace1 = half3(wTangent.y, wBitangent.y, wNormal.y);
                o.tspace2 = half3(wTangent.z, wBitangent.z, wNormal.z);
                o.uv = uv;
                return o;
            }

            // normal map texture from shader properties
            sampler2D _BumpMap;
        
            fixed4 frag (v2f i) : SV_Target
            {
                // sample the normal map, and decode from the Unity encoding
                half3 tnormal = UnpackNormal(tex2D(_BumpMap, i.uv));
                // transform normal from tangent to world space
                half3 worldNormal;
                worldNormal.x = dot(i.tspace0, tnormal);
                worldNormal.y = dot(i.tspace1, tnormal);
                worldNormal.z = dot(i.tspace2, tnormal);

                // rest the same as in previous shader
                half3 worldViewDir = normalize(UnityWorldSpaceViewDir(i.worldPos));
                half3 worldRefl = reflect(-worldViewDir, worldNormal);
                half4 skyData = UNITY_SAMPLE_TEXCUBE(unity_SpecCube0, worldRefl);
                half3 skyColor = DecodeHDR (skyData, unity_SpecCube0_HDR);
                fixed4 c = 0;
                c.rgb = skyColor;
                return c;
            }
            ENDCG
        }
    }
}

상당히 복잡한 내용이었습니다만 이를 통해 노멀 맵핑된 반사를 구현할 수 있습니다.

빌트인 렌더 파이프라인의 반사 셰이더 예시
빌트인 렌더 파이프라인의 삼평면 텍스처링 셰이더 예시