본문으로 바로가기

Unity Normal defined function

category Technical Report/Unity Shader 2017. 7. 4. 22:53
반응형


일단 노멀의 정의에 대해서는 좋은 포스팅이 있어 일단 링크 공유

 Normal, Tangent, BiTagent Vector 그리고 Unity Normal Map


Unity UnpackNormal


UnityCG.cginc

inline fixed3 UnpackNormalDXT5nm (fixed4 packednormal)
{
    fixed3 normal;

    normal.xy = packednormal.wy * 2 - 1;

    normal.z = sqrt(1 - saturate(dot(normal.xy, normal.xy)));

    return normal;
}

DXT5nm에서의 노멀 처리.

위는 DXTnm나 BC5의 노멀 텍스쳐의 RGB 색상에 1개의 채널을 더해 RGBA로 바꾸고 소스 R은 G로, 소스G는 A로 변경해 R과 B는 공백으로 둔다.(이렇게 됨으로 아티팩트를 줄일수 있음) 따라서 packednormal.xy는 packednormal.ag와 동일하다.

이는 DXT5  R:5 G:6 B:5 A:8로 변환(RGB16bit를 24bit RGBA로 변환)할때 G와A채널 값이 가장 크기 때문

https://knowledge.autodesk.com/ko/support/3ds-max/learn-explore/caas/CloudHelp/cloudhelp/2016/KOR/3DSMax/files/GUID-2F15E3CD-E234-411F-B086-3E3970D98D69-htm.html

X.Y값으로 Z값을 추출해내는데, 이는 X^2 + Y^2 + Z^2 = 1 이라는 공식에서 유도된다.(모든 벡터는 길이가 1인 단위벡터이므로) 이를 Z = sqrt( 1 - (X^2 + Y^2))로 유도된다.


UE 노드 파라메터의 DeriveNormalZ가 이와 같은 역할을 한다.


https://docs.unrealengine.com/latest/KOR/Engine/Rendering/Materials/ExpressionReference/VectorOps/index.html


Append로 3채널 벡터로 변환해서 DeriveNormalZ로 XY값으로 Z값을 더해 출력하고 있다.



DX5nm이 아닐경우에는

inline fixed3 UnpackNormal(fixed4 packednormal)
{
#if defined(UNITY_NO_DXT5nm)
    return packednormal.xyz * 2 - 1;
#else
    return UnpackNormalDXT5nm(packednormal);
#endif
}

로 추가연산없이 좌표계만 변환해 그대로 사용하는것을 볼 수 있다.

GLSL코드에서 이를 활용한 코드를 살펴볼 수 있다. : https://en.wikibooks.org/wiki/GLSL_Programming/Unity/Lighting_of_Bumpy_Surfaces#Normal_Mapping_in_Unity




UnityStandardUtils.cginc


UnpackScaleNormal

Normal의 Intensity를 조절할때 fixed3(Property.x, Property.y, Property.z)처럼 각각의 RGB값에 값을 곱해서 노멀값을 조절할 수도 있겠지만 이 명령어로 쉽게 조절할 수도 있다.


half3 UnpackScaleNormal(half4 packednormal, half bumpScale)
{
    #if defined(UNITY_NO_DXT5nm)
        return packednormal.xyz * 2 - 1;  

   //모바일에서는 그냥 동작안한다.. ㅡㅡ;;; 그냥 x,y,z 값이나 y값만 곱해주면 될듯.


   #else

        half3 normal;
        normal.xy = (packednormal.wy * 2 - 1);

        #if (SHADER_TARGET >= 30)
            // SM2.0: instruction count limitation
            // SM2.0: normal scaler is not supported
            normal.xy *= bumpScale;


        // 역시 SM 2.0에서도 지원안함 shader model 2.0이면.. 대충 레이디언 9000대... 지포스 FX정도... 자세한건 링크 참조 : http://illu.tistory.com/1209


        #endif
           normal.z = sqrt(1.0 - saturate(dot(normal.xy, normal.xy)));

        return normal;

    #endif
}       


BlendNormals

노멀 블렌드 처리

half3 BlendNormals(half3 n1, half3 n2)

{
    return normalize(half3(n1.xy + n2.xy, n1.z*n2.z));
}


노멀 블렌드 기법에 대한건 다음 포스팅 참조 : http://illu.tistory.com/1132








반응형