본문 바로가기
Shader

유니티 내장 셰이더 함수들

by 대마왕J 2019. 9. 13.

https://docs.unity3d.com/kr/current/Manual/SL-BuiltinFunctions.html

 

빌트인 셰이더 헬퍼 함수 - Unity 매뉴얼

Unity에는 셰이더를 더 간편하고 쉽게 작성하는 데 유용한 빌트인 유틸리티 기능이 있습니다.

docs.unity3d.com

에 있는 내용에 대한 해석입니다. 

저기에 내용이 다 있지만 좀 더 쉽게 쓰는거랄까. 

왜냐면 내가 보기 편하게 하려고

메뉴얼 쓰는 알바를 저에게! 

 

 

UnityCG.cginc의 버텍스 트랜스폼 함수

유니티 안에는 UnityCG.cginc 라고 하는, 셰이더를 위한 내장함수들이 존재합니다. 버텍스&프레그먼트 셰이더(이하 프레그먼트 셰이더) 에서  #include "UnityCG.cginc"   라고 선언하면 쓸 수 있는 명령어죠. 서피스 셰이더에서도 선언후에 버텍스 셰이더 영역에서 사용 가능합니다. 

 

 

float4 UnityObjectToClipPos(float3 pos)

오브젝트 공간의 한 점을 동질적인 좌표에 있는 카메라의 클립 공간으로 변환합니다. mul(UNITY_MATRIX_MVP, float4(pos, 1.0))과 같으며, 이를 대신하여 사용해야 합니다.

로컬 공간(오브젝트 공간) 의 버텍스를 클립공간으로 변환합니다. 기본적으로 공간변환은 로컬 - 월드 - 뷰 - 프러스텀인데, 이걸 모델-뷰-프러스텀이라고 부르면서 MVP라고 부릅니다. 그런데 프러스텀은 니어와 파로 잘라지죠? 그러면 절두체 모양이 됩니다. 일종의 찌그러진 큐브죠. 이 큐브 영역을 0~ 1사이로 변환한 것이 클립 포지션이라 합니다. 즉 최종 영역까지 한 번에 변환하는 함수입니다. 

float3 UnityObjectToViewPos(float3 pos)

오브젝트 공간의 한 점을 뷰 공간으로 변환합니다. __mul(UNITY_MATRIX_MV, float4(pos, 1.0)).xyz__와 같으며, 이를 대신하여 사용해야 합니다.

로컬 공간(오브젝트 공간) 의 버텍스를 뷰 공간으로 변환합니다. 예전엔 mul 명령으로 , 모델-뷰를 곱했던 것을 그냥 한 번에 처리하는 겁니다. 

 

UnityCG.cginc의 일반 헬퍼 함수

버텍스 전용이 아닌, 어디서나 쓸 수 있는 함수입니다. 

 

float3 WorldSpaceViewDir (float4 v)

월드 공간 방향(정규화되지 않음)을 주어진 오브젝트 공간 버텍스 포지션에서 카메라 쪽으로 되돌립니다.

월드 공간에 있는 것을 뷰 방향으로 변환합니다. 

float3 worldPos = mul(unity_ObjectToWorld, localPos).xyz;
    return UnityWorldSpaceViewDir(worldPos);

float3 ObjSpaceViewDir (float4 v)

오브젝트 공간 방향(정규화되지 않음)을 주어진 오브젝트 공간 버텍스 포지션에서 카메라 쪽으로 되돌립니다.

로컬 공간에 있는 것을 뷰 방향으로 변환합니다.

float3 objSpaceCameraPos = mul(unity_WorldToObject, float4(_WorldSpaceCameraPos.xyz, 1)).xyz;
    return objSpaceCameraPos - v.xyz; 

float2 ParallaxOffset (half h, half height, half3 viewDir)

패럴랙스 노멀 매핑의 UV 오프셋을 계산합니다.

패럴랙스 노멀을 위한 UV  계산 함수네요. 일종의 아이폰 입체 사진 같은 느낌을 말합니다. 보통 h 는 높이값이고, height는 흑백음영의 하이트맵이고 (둘이 바뀌었을지도 모르겠습니다) 뷰 디렉션을 넣어줍니다. 

https://chulin28ho.tistory.com/520

이 내용인데, 이 함수로 한 번 써서 해 봐야겠어요 

inline float2 ParallaxOffset( half h, half height, half3 viewDir )
{
    h = h * height - height/2.0;
    float3 v = normalize(viewDir);
    v.z += 0.42;
    return h * (v.xy / v.z);
}

fixed Luminance (fixed3 c)

컬러를 휘도(그레이스케일)로 변환합니다.

return dot(rgb, unity_ColorSpaceLuminance.rgb);

이렇게 되어 있는데요 

unity_ColorSpaceLuminance half4(0.0396819152, 0.458021790, 0.00609653955, 1.0)

인걸로 보아서 그레이 스케일 상수를 곱해서 더해주는 방식입니다. 

fixed3 DecodeLightmap (fixed4 color)

Unity 라이트맵에서 컬러를 디코딩합니다(플랫폼에 따라 RGBM 또는 dLDR).

모바일이냐 아니냐에 따라 달랐던걸로 기억합니다 

#if defined(UNITY_LIGHTMAP_DLDR_ENCODING)
    return DecodeLightmapDoubleLDR(color, decodeInstructions);
#elif defined(UNITY_LIGHTMAP_RGBM_ENCODING)
    return DecodeLightmapRGBM(color, decodeInstructions);

 

float4 EncodeFloatRGBA (float v)

정밀도가 낮은 렌더링 타겟에 저장하기 위해 [01) 범위 플로트를 RGBA 컬러로 인코딩합니다

 

8비트 체널로 인코딩합니다. 안써봐서 모르겠음. 

inline float4 EncodeFloatRGBA( float v )
{
    float4 kEncodeMul = float4(1.0, 255.0, 65025.0, 16581375.0);
    float kEncodeBit = 1.0/255.0;
    float4 enc = kEncodeMul * v;
    enc = frac (enc);
    enc -= enc.yzww * kEncodeBit;
    return enc;
}

 

float DecodeFloatRGBA (float4 enc)

RGBA 컬러를 플로트로 디코딩합니다.

위 것과 반대 작용을 하는 것 같은데, 재미있는건 xyzw가 플롯, 8비트, 16비트, 24비트 칼라라는 것이네요. 

inline float DecodeFloatRGBA( float4 enc )
{
    float4 kDecodeDot = float4(1.0, 1/255.0, 1/65025.0, 1/16581375.0);
    return dot( enc, kDecodeDot );
}

 

float2 EncodeFloatRG (float v)

[0–1) 범위 플로트를 float2로 인코딩합니다.

 

위의위의 것과 동일합니다. 단 여기는 플롯과 8비트만 연산하네요 

inline float2 EncodeFloatRG( float v )
{
    float2 kEncodeMul = float2(1.0, 255.0);
    float kEncodeBit = 1.0/255.0;
    float2 enc = kEncodeMul * v;
    enc = frac (enc);
    enc.x -= enc.y * kEncodeBit;
    return enc;
}

 

 

float DecodeFloatRG (float2 enc)

이전에 인코딩된 RG 플로트를 디코딩합니다.

 

설명생략

inline float DecodeFloatRG( float2 enc )
{
    float2 kDecodeDot = float2(1.0, 1/255.0);
    return dot( enc, kDecodeDot );
}

 

float2 EncodeViewNormalStereo (float3 n)

뷰 공간 노멀을 범위가 01인 숫자 2개로 인코딩합니다.

 

이 부분은 안써봐서 모르는 거군요 

inline float2 EncodeViewNormalStereo( float3 n )
{
    float kScale = 1.7777;
    float2 enc;
    enc = n.xy / (n.z+1);
    enc /= kScale;
    enc = enc*0.5+0.5;
    return enc;
}

 

float3 DecodeViewNormalStereo (float4 enc4)

뷰 공간 노멀을 enc4.xy에서 디코딩합니다.

 

inline float3 DecodeViewNormalStereo( float4 enc4 )
{
    float kScale = 1.7777;
    float3 nn = enc4.xyz*float3(2*kScale,2*kScale,0) + float3(-kScale,-kScale,1);
    float g = 2.0 / dot(nn.xyz,nn.xyz);
    float3 n;
    n.xy = g*nn.xy;
    n.z = g-1;
    return n;
}

 

 

UnityCG.cginc의 포워드 렌더링 헬퍼 함수

이 함수는 포워드 렌더링(ForwardBase 또는 ForwardAdd 패스 타입)을 사용하는 경우에만 유용합니다.

 

디퍼드 렌더링에서는 안되고 포워드에서만 된다는 말이겠군요. 주로 라이트에 관계된 부분이겠지요. 

 

float3 WorldSpaceLightDir (float4 v)

광원을 향한 월드 공간 방향(정규화되지 않음)을 주어진 오브젝트 공간 버텍스 포지션에 대해 계산합니다.

 

오브젝트(로컬) 좌표계의 버텍스 위치를 집어 넣으면, 월드 좌표계 에서의 라이트 디렉션이 나옵니다. ForwardBase 인 경우에는 디렉셔널 라이트 또는 가장 밝은 라이트가 선택될테고, 라이트가 추가되면 ForwardAdd가 실행되니 그때에는 다음 라이트가 이걸 실행하겠죠 

inline float3 WorldSpaceLightDir( in float4 localPos )
{
    float3 worldPos = mul(unity_ObjectToWorld, localPos).xyz;
    return UnityWorldSpaceLightDir(worldPos);
}

 

float3 ObjSpaceLightDir (float4 v)

광원을 향한 오브젝트 공간 방향(정규화되지 않음)을 주어진 오브젝트 공간 버텍스 포지션에 대해 계산합니다.

 

위와 같습니다만, 리턴이 오브젝트(로컬) 좌표계입니다. 

inline float3 ObjSpaceLightDir( in float4 v )
{
    float3 objSpaceLightPos = mul(unity_WorldToObject, _WorldSpaceLightPos0).xyz;
    #ifndef USING_LIGHT_MULTI_COMPILE
        return objSpaceLightPos.xyz - v.xyz * _WorldSpaceLightPos0.w;
    #else
        #ifndef USING_DIRECTIONAL_LIGHT
        return objSpaceLightPos.xyz - v.xyz;
        #else
        return objSpaceLightPos.xyz;
        #endif
    #endif
}

 

float3 Shade4PointLights (...)

벡터에 조밀하게 채워진 광원 데이터를 사용해 점 광원 4개의 조명을 연산합니다. 포워드 렌더링에서 버텍스당 조명을 연산하는 데 사용됩니다.

 

이쪽은 코드가 좀 기네요. 4개까지 연산되는 포인트 라이트 연산입니다. 사용 예를 좀 찾아보고 싶군요 

 

 

 

UnityCG.cginc의 스크린 공간 헬퍼 함수

다음은 스크린 공간 텍스처 샘플링에 사용되는 좌표를 계산하는 헬퍼 함수입니다. 텍스처를 샘플링할 최종 좌표를 원근 나누기(예: xy/w)를 통해 계산할 수 있는float4를 반환합니다.

함수는 렌더 텍스처 좌표의 플랫폼 차이도 처리합니다.

 

댑스값에 관련된 부분에 사용할때 많이 쓰는 녀석들입니다. 스크린 스페이스에서의 좌표계부분입니다. 

 

float4 ComputeScreenPos (float4 clipPos)

Screenspace 매핑된 텍스처 샘플링을 수행하기 위한 텍스처 좌표를 계산합니다. 입력은 클립 공간 포지션입니다.

 

그다지 설명할게 없습니다. 클립 스페이스를 집어 넣으면 스크린 좌표계에서의 텍스쳐 좌표계 값이 나옵니다. 

inline float4 ComputeScreenPos(float4 pos) {
    float4 o = ComputeNonStereoScreenPos(pos);
#if defined(UNITY_SINGLE_PASS_STEREO)
    o.xy = TransformStereoScreenSpaceTex(o.xy, pos.w);
#endif
    return o;
}

 

 

float4 ComputeGrabScreenPos (float4 clipPos)

GrabPass 텍스처를 샘플링하는 텍스처 좌표를 계산합니다. 입력은 클립 공간 포지션입니다.

 

마찬가지 연산을 합니다. OpenGl이냐 DirectX냐에 따라 위아래가 바뀌는 연산이 들어가 있습니다. 

 

 

UnityCG.cginc의 버텍스 릿 헬퍼 함수

함수는 버텍스당 릿 셰이더(“Vertex” 패스 타입)를 사용하는 경우에만 유용합니다.

 

간단하게 버텍스 라이트 연산을 위한 함수입니다. 픽셀라이트에서는 이루어지지 않는 연산임을 주의

 

float3 ShadeVertexLights (float4 vertex, float3 normal)

버텍스당 광원 및 앰비언트 4개의 조명을 주어진 오브젝트 공간 포지션 및 노멀에 대해 계산합니다.

버텍스 라이트 연산을 하는 함수입니다. 당연히 픽셀라이트 연산으로 작동되지 않습니다. 

 

 

 

 

 

반응형

댓글