본문 바로가기

Unreal Engine

Real Shading in Unreal Engine 4 (언리얼 엔진 4의 실사 셰이딩)

서론

1년 전,  우리는 셰이딩 모델을 향상시키는데 시간을 투자하고 물리 기반인 머티리얼 워크플로우를 받아들이기로 결정하였다. 이것은 더욱 사실적인 이미지를 렌더하려는 갈망에서 비롯되기도 하였으나, 머티리얼 제작에 있어서 물리 기반의 접근과 머티리얼 레이어링으로 우리가 무엇을 얻을 수 있는지에 대한 관심에서 비롯된 것이기도 했다. 아티스트들은 워크플로우와 퀄리티가 엄청나게 진보했다고 느꼈으며, 나 또한 이러한 이점을 이전 스튜디오에서 앞서 지켜보기도 하였다 - 우리는 여기에서 오프라인에서 컴포지팅된 머티리얼들을 머티리얼 레이어로 전환하였다. 에픽 게임즈의 테크 아티스트중 한명은 셰이더 내에서 레이어링 하는 것을 시도하였고 꽤 유망한 결과물을 도출해내었다- 이것은 추가적인 필수 조건이 되었다.

이 움직임을 지지하기 위해, 우리는 머티리얼 레이어링이 심플하고 효과적이어야 하는 것을 알았다. 아주 완벽한 타이밍에 Disney에서 주먹왕 랄프에서 사용된 그들의 물리 기반 셰이딩과 머티리얼 모델에 대한 프레젠테이션을 발표하였다. Brent Burley는 아주 적은 셋트의 머티리얼 파라미터들로도 오프라인 필름 렌더링에서 충분히 수준 높은 결과를 낼 수 있다는 것을 증명하였다. 또한, 그는 충분히 실용적인 셰이딩 모델은 거의 모든 샘플링된 재질에 맞추어질 수 있다는 것을 보여주었다. 그들의 업적은 우리에게 영감을 주는 한편 밑거름이 되었고, 그들의 "원칙(Principles)" 처럼, 우리의 시스템에도 목표를 설정하기로 하였다:

 

실시간 퍼포먼스(Real-time Performance)

  • 가장 첫째로(그리고 가장 중요하게), 한 번에 여러 개의 라이트와 함께 사용하기에 효율적이어야 한다.

간소화된 복잡도(Reduced Complexity)

  • 가능한 한 적은 수의 파라미터를 사용한다. 크기가 큰 파라미터 Array는 decision paralysis나 시행착오를 일으키거나, 하나의 결과를 유도해내기 위해 상호 연결된 프로퍼티들의 값을 많이 조정해야 하는 결과를 낳는다.
  • 우리는 이미지 기반 라이팅과 분석적인(Analytic) 광원들을 서로 바꿔가며 사용할 수 있어야 한다. 그러므로 파라미터들은 모든 라이트 유형에 대해 일관적으로 동적해야 한다.

직관적인 인터페이스(Intuitive Interface)

  • 우리는 이해하기 쉬운 값들을 선호한다. 이는 굴절률(Index of Refraction) 같은 물리적인 값들과 반대되는 것이다.

지각적인 선형성(Perceptually Linear)

  • 우리는 마스크를 통한 레이어링을 지원하려고 한다. 그러나 우리는 픽셀당 한 번만 셰이딩할 수 있다. 이는 파라미터로 블렌딩된 셰이딩이 셰이딩 된 결과물의 블렌딩과 최대한 가깝게 일치해야 한다는 것을 의미한다.

마스터하기 수월하여야 함(Easy to Master)

  • 우리는 절연체와 전도체에 대해 기술적으로 이해해야 할 필요를 최대한 피하고 싶다. 또한 물리적으로 합당한 머티리얼의 기본형을 짜기 위한 노력도 최소화하려고 한다.

견고함(Robust)

  • 실수로라도 물리적으로 합당하지 않은 재질을 만드는 일이 쉽지 않아야 한다.
  • 파라미터들의 모든 조합이 가능한 한 견고하고 타당해야 한다.

표현력 있는(Expressive)

  • 디퍼드 셰이딩은 우리가 가질 수 있는 셰이딩 모델의 갯수를 제한한다. 그러므로 우리의 베이스 셰이딩 모델은 현실 세계에 존재하는 재질의 99%를 표현하기에 충분하여야 한다.
  • 모든 레이어링 가능한 머티리얼은 같은 파라미터 세트를 가져 서로 블렌딩할 수 있어야 한다.

유연성(Flexible)

  • 다른 프로젝트들과 라이센스 사용자들은 포토리얼리즘이라는 목표를 공유하지 않을 수 있다. 그러므로 포토리얼리스틱하지 않은 렌더링에서도 사용 가능하게끔 충분히 유연해야 한다.

 

셰이딩 모델

 

Diffuse BRDF

우리는 Burley의 디퓨즈 모델을 사용해 보았으나 Lambert의 디퓨즈(아래)와 아주 적은 차이가 있음을 확인했다. 그러므로 추가적인 비용을 정당화할 수는 없었다. 게다가, 그 이상으로 복잡한 디퓨즈 모델은 이미지 기반 라이팅이나 구면조화 라이팅과 함께 효율적으로 사용되기는 어려울 것이었다. 결과적으로, 우리는 다른 선택에 대한 값을 구하는 데에 많은 노력을 들이지는 않았다.

 

 

여기에서 cdiff는 머티리얼의 디퓨즈 Albedo를 의미한다.

 

미세면(국소면..?) 스페큘러 BRDF

보편적인 Cook-Torrance 미세면 스페큘러 셰이딩 모델은 다음과 같다:

 

더 자세한 내용은 9번 참고자료를 보자... Background: Physics and Math of Shading

우리는 디즈니의 모델로부터 시작해서 각 항들을 더욱 효율적인 선택지들과 비교하했을 때의 각각의 중요도를 평가하였다. 이것은 보기보다 어려운 일이었다; 각 항의 발행된(Published) 방정식들은 항상 같은 입력값을 가지지는 않았기 때문이다(이는 제대로 된 비교에 필수적인 요소이다).

 

Specular D

Normal Distributio Function(NDF) 으로, 우리는 디즈니가 선택한 GGX/Trowbridge-Reitz 가 가장 비용을 들일 가치가 있다고 판단했다. Blinn-Phong 모델을 사용해서 발생하는 비용은 꽤 미미하고, 더욱 긴 "tail" 이 만드는 독보적이고 자연스러운 모습이 아티스트들의 호응을 얻었다. 디즈니의 a = Roughness2 의 재파라미터화도 채택하였다. 

 

Specular G

우리는 Specular geometry attenuation에 대해 다른 것들 보다도 많은 선택지들을 평가하였다. 마침내, 우리는 Schlick 모델을 사용하되, k = a/2 를 사용하여 GGX가 Smith의 모델에 더 가까워지도록 하였다. 이렇게 수정함으로, Schlick 모델은 a=1 일때 Smith의 모델과 정확하게 일치하게 되고, [0,1] 사이의 범위에서 꽤 근접한 근사값을 보여준다. 또한 디즈니가 Roughness를 제곱하기 전 (Roughness + 1) / 2 를 사용해 Roughness를 리맵핑해서 "Hotness"를 감소시키는 수정도 적용하였다. 이 수정은 analytic 광원에만 적용된다는 것을 기억하자; 이미지 기반 라이팅에 적용될 경우,  비스듬한 각도 부분의 결과가 너무 어두울 것이다.

 

Specular F

프레넬에 대해서는, Schilick 근사치라는 전형적인 선택을 하였으나, 작은 수정을 더했다: 우리는 제곱을 대체하기 위해 Spherical Gaussian 근사를 사용하였다. 이 쪽이 연산하기에 약간 더 효율적이고, 차이는 거의 보이지 않는다. 식은 아래와 같다:

 

F0은 노멀 각에서 빛이 들어올때의 스페큘러 반사이다.

 

이미지 기반 라이팅

 

이미지 기반 라이팅에서 셰이딩 모델을 사용하려면, 빛 적분을 풀어야 하는데, 주로 중요도 샘플링을 사용하는 것으로 해결된다. 아래의 식은 이 적분을 나타낸다.

 

 

아래의 HLSL코드는 셰이딩 모델로 이걸 어떻게 하는지를 보여준다.

 

float3 ImportanceSampleGGX( float2 Xi, float Roughness, float3 N )
{
    float a = Roughness * Roughness;
    float Phi = 2 * PI * Xi.x;
    float CosTheta = sqrt( (1 - Xi.y) / ( 1 + (a*- 1* Xi.y ) );
    float SinTheta = sqrt( 1 - CosTheta * CosTheta );
    
    float3 H;
    H.x = SinTheta * cos( Phi );
    H.y = SinTheta * sin( Phi );
    H.z = CosTheta;
    float3 UpVector = abs(N.z) < 0.999 ? float3(0,0,1) : float3(1,0,0);
    float3 TangentX = normalize( cross( UpVector, N ) );
    float3 TangentY = cross( N, TangentX );
    // Tangent to world space
    return TangentX * H.x + TangentY * H.y + N * H.z;
}
float3 SpecularIBL( float3 SpecularColor , float Roughness, float3 N, float3 V )
{
    float3 SpecularLighting = 0;
    const uint NumSamples = 1024;
    for( uint i = 0; i < NumSamples; i++ )
    {
        float2 Xi = Hammersley( i, NumSamples );
        float3 H = ImportanceSampleGGX( Xi, Roughness, N );
        float3 L = 2 * dot( V, H ) * H - V;
        float NoV = saturate( dot( N, V ) );
        float NoL = saturate( dot( N, L ) );
        float NoH = saturate( dot( N, H ) );
        float VoH = saturate( dot( V, H ) );
        if( NoL > 0 )
        {
            float3 SampleColor = EnvMap.SampleLevel( EnvMapSampler , L, 0 ).rgb;
            float G = G_Smith( Roughness, NoV, NoL );
            float Fc = pow( 1 - VoH, 5 );
            float3 F = (1 - Fc) * SpecularColor + Fc;
            // Incident light = SampleColor * NoL
            // Microfacet specular = D*G*F / (4*NoL*NoV)
            // pdf = D * NoH / (4 * VoH)
            SpecularLighting += SampleColor * F * G * VoH / (NoH * NoV);
        }
    }
    return SpecularLighting / NumSamples;
}
 

 

중요도 샘플링을 사용해도, 여전히 많은 샘플들이 필요하다. 이 샘플들 갯수는 밉맵을 사용함으로서 상당히 많이 줄어들 수 있지만, 충분한 퀄리티를 위해서는 16 이상이어야 한다. 왜냐하면 로컬 반사를 위해 픽셀당 많은 환경 맵을 블렌딩하므로, 실질적으로 각각 하나의 샘플만을 감당할 수 있기 때문이다.

 

분할 합계 근사 (Split sum approximation)

이것을 얻기 위해서, 위의 합계를 2개의 합계로 나누어 근사한다. 그러면 각각의 합계는 미리 계산될 수 있다. 이 근사는 상수 Li(l) 에 대해 정확하며, 보편적인 환경에서 꽤 정확하다.

 

 

미리 필터링된 환경 맵 (Pre-Calculated Environment Map)

우리는 첫 번째 합계를 각각 다른 roughness 값에 대해 미리 계산하고, 그 결과를 큐브맵의 밉맵 레벨에 저장해두었다. 이것은 게임 산업에서 자주 사용되는 전형적인 어프로치이다.  작은 차이가 있다면, 우리는 환경 맵을 중요도 분포를 사용해 우리의 셰이딩 모델의 GGX 분포에 컨벌브시켰다는 것이다. 미세면 분포 모델이므로, 분포의 모양은 표면에 대한 시점 각도에 기반하고, 이 시점 각도를 0도라고 가정한다 : 즉 , n = v = r 이다. 이 등방성의(isotropic) 가정은 근사값의 두 번째 원천이며, 이것은 불행히도 우리가 빛나는 각도(glazing angles) 에서는 긴(lengthy) 반사를 얻지 못한다는 것을 의미한다. 분할 합계 근사와 비교했을때, 이것은 우리의 이미지 기반 라이팅에 대한 해결책에 있어 더 큰 에러의 원천이었다. 아래의 코드에서 보듯이, 우리는 cosΘlk 로 웨이트를 줘서 더 좋은 결과를 얻었다.

float3 PrefilterEnvMap( float Roughness, float3 R )
{
    float3 N = R;
    float3 V = R;
    float3 PrefilteredColor = 0;
    const uint NumSamples = 1024;
    for( uint i = 0; i < NumSamples; i++ )
    {
        float2 Xi = Hammersley( i, NumSamples );
        float3 H = ImportanceSampleGGX( Xi, Roughness, N );
        float3 L = 2 * dot( V, H ) * H - V;
        float NoL = saturate( dot( N, L ) );
        if( NoL > 0 )
        {
            PrefilteredColor += EnvMap.SampleLevel( EnvMapSampler , L, 0 ).rgb * NoL;
            TotalWeight += NoL;
        }
    }
    return PrefilteredColor / TotalWeight;
}

 

환경 BRDF (Environment BRDF)

 

두 번째 합계는 나머지 모든 것을 포함한다. 이것은 스페큘러 BRDF를 흰 단색 환경과 병합하는 것과 같다. 즉, Li(lk) = 1이다. Schlick 프레넬 내에서  : 

 으로 치환하면, F0을 아래와 같이 적분할 수 있다는 것을 알 수 있다.

이것은 Roguhess와 cosΘv라는 두 개의 입려값과 두 개의 출력값(스케일과 F0에 대한 bias) 를 갖는데, 이것은 모드 [0,1] 범위 안의 값을 가진다. 우리는 이 함수에 대한 결과를 먼저 계싼하고 2D 룩업텍스처(LUT)에 저장하였다.

이 작업을 마친 후, 우리는 현존하는 동시대의 연구들이 우리와 거의 동일한 해결책을 갖는다는 것을 발견했다.  Whilst Gotanda는 3D LUT를 사용했고, Drobot은 이것을 우리와 같이 2D 텍스처로 최적화했다. 추가로 - 이 코스의 일부분으로 - Lazarov는 한걸음 더 나아가 몇 개의 분석적인 근사값들을 유사한 적분으로 나타내었다.

 

 

float2 IntegrateBRDF( float Roughness, float NoV )
{
    float3 V;
    V.x = sqrt( 1.0f - NoV * NoV ); // sin
    V.y = 0;
    V.z = NoV; // cos
    float A = 0;
    float B = 0;
    const uint NumSamples = 1024;
    for( uint i = 0; i < NumSamples; i++ )
    {
        float2 Xi = Hammersley( i, NumSamples );
        float3 H = ImportanceSampleGGX( Xi, Roughness, N );
        float3 L = 2 * dot( V, H ) * H - V;
        float NoL = saturate( L.z );
        float NoH = saturate( H.z );
        float VoH = saturate( dot( V, H ) );
        if( NoL > 0 )
        {
            float G = G_Smith( Roughness, NoV, NoL );
            float G_Vis = G * VoH / (NoH * NoV);
            float Fc = pow( 1 - VoH, 5 );
            A += (1 - Fc) * G_Vis;
            B += Fc * G_Vis;
        }
    }
    return float2( A, B ) / NumSamples;
}

마지막으로, 중요도 샘플링된 레퍼런스들을 근사하기 위해, 우리는 두 개의 미리 계산된 합계를 곱했다.

 

float3 ApproximateSpecularIBL( float3 SpecularColor , float Roughness, float3 N, float3 V )
{
    float NoV = saturate( dot( N, V ) );
    float3 R = 2 * dot( V, N ) * N - V;
    float3 PrefilteredColor = PrefilterEnvMap( Roughness, R );
    float2 EnvBRDF = IntegrateBRDF( Roughness, NoV );
    return PrefilteredColor * ( SpecularColor * EnvBRDF.x + EnvBRDF.y );
}

 

 

머티리얼 모델

 

우리의 머티리얼 모델은 디즈니의 모델을 료율성과 실시간 렌더링을 위해 단순화한 버전이었다. 파라미터의 갯수를 제한하는 것은 텍스처 저장과 접근을 줄여 G-버퍼 공간을 절약하고, 픽셀 셰이더에서 머티리얼 레이어들을 블렌딩하는 데 드는 비용을 최소화하는 것에 있어 극히 중요했다.

 

아래는 우리의 베이스 머티리얼 모델이다:

 

BaseColor : 단색 컬러. 이해하기 쉬운 개념이다.

Metalic : 절연체와 전도체의 반사에 대해 이해할 필요가 없다. 따라서 에러가 있을 여지가 적다.

Roughness : 의미가 명료하다. 반면 Gloss 는 항상 설명이 필요하다.

Cavity : 작은 규모의 섀도우에 사용된다.

 

BaseColor, Metailic, 그리고 Roughness는 모두 디즈니의 모델과 같다. 그러나 Cavity 파라미터는 없었으므로, 설명이 필요하다. Cavity는 우리의 런타임 섀도잉 시스템이 다룰 수 있는 것보다 작은, 기하적인 셰도우를 특정하는 데 사용되는데, 흔히 노말 맵에서만 존재하는 도형에 대해서이다. 이를테면 바닥 판 사이의 갈라진 틈이나, 옷의 이음매 부분 등이 있다.

Specular 파라미터가 없는 것이 가장 눈에 띈다. 우리는 Infilrator 데모가 완료될때까지만 해도 이것을 계속 사용하고 있었다. 그러나 최종적으로 우리는 그것이 마음에 들지 않았다. 첫번째로, "Specular" 라는 이름이 많은 혼란을 일으키는 파라미터 이름이며, 아티스트들이 스페큘러 강도(Specular intensity) 를 컨트롤하는 것에서 Roughness를 컨트롤하는 것으로 전환하는 것을 저해한다고 느꼈다. 아티스트와 그래픽 프로그래머들은 자주 그 파라미터의 범위를 잊어버리기 십상이었으며, 기본값이 0이라고 전제하였다 - 사실 실제 기본값은 Burley가 설정한 0.5 였다(이것은 반사율 4%에 해당한다). 스페큘러가 가장 효과적으로 사용된 것은 작은 규모의 셰도잉을 위한 용도 하나 뿐이었다. 우리는 반사율(IOR) 이 비금속 재질에는 딱히 중요치 않다는 것을 알아냈고, 최근 스페큘러를 더욱 이해하기 쉽도록 Cavity 파라미터로 바꾸었다. 비금속의 F0값은 이제 0.04의 상수이다.

 

아래는 디즈니 모델에서 우리가 베이스 머티리얼에 적용하지 않고, 특수한 케이스로 다루기로 결정한 파라미터들이다. 

Subsurface : 섀도우 맵을 다르게 샘플링한다.

Anisotropy : 많은 IBL 샘플들을 필요로 한다.

ClearCoat : 2배로 많은 IBL 샘플들이 필요하다.

Sheen : Burley의 노트에 잘 정의되어 있지 않다.

 

우리는 Elemental Demo에서 얼음을 표현하는 데에 사용한 Subsurface 말고는 이 특수한 케이스의 모델들을 프로덕션에 사용하지는 않았다. 게다가 우리는 피부를 위한 특수 셰이딩 모델을 가지고 있었다. 나중을 위해 우리는 디퍼드 / 포워드가 합성된 셰이딩 접근을 채택해볼 것을 고려하고 있다.  현재의 순수한 디퍼드 셰이딩 접근으로는 서로 다른 셰이딩 모델들이 G-버퍼에 저장된 셰이딩 모델 id로 구분되는 다이내믹 브랜치로 다루어진다.

 

경험

 

내가 여태까지 수많이 봐온 상황이 있다 - 아티스트들에게 러프니스를 사용하도록 바뀔 것이라고 알려준다. "스페큘러 컬러를 사용했던 것처럼 러프니스를 사용하세요." 그리고 조금 뒤에, 아티스트들이 흥분과 놀라움으로 "정말 되네요!" 라고 말하는 것을 듣게 된다. 그러나 그 이후 흥미로운 질문이 따라온다: "러프니스가 뒤집힌 것 같은데요." 아티스트들은 그들이 더 밝은 "텍셀" 로 작성한 텍스처가 더 밝은 스페큘러 하이라이트와 동일하기를 바라는 것이다. 이미지가 러프니트를 저장하면, 밝은 부분은 더 거칠어지고(Rougher), 덜 강한 하이라이트가 된다. 

내가 수없이 들은 질문은 "메탈릭이 바이너리인가요?" 인데, 나는 이것을 혼합되거나 레이어링된 머티리얼의 미묘함으로 설명하겠다. 나는 여기에 그냥 "네!" 라고 대답하는 것이 가장 좋다고 배우게 되었다. 그 이유는 아티스트들이 처음에 파라미터들을 절대값으로 설정하는 것을 망설이기 때문인데, 메탈릭 값이 0.8인 금속을 아주 쉽게 발견할 수 있다. 머티리얼 레이어들은- 나중에 설명할 것이지만- 메탈릭이 0이나 1이 아닌 케이스의 99%를 설명하는 방법이 되어야 한다. (즉 메탈릭 값은 레이어링된 머티리얼의 경우 0이나 1이 아닐 수 있다라는 뜻인듯).

전환 과정에서 있었던 문제는 더 이상 복제될 수 없는 형태의 머티리얼이었다. 이들 중 가장 중요한 것들은 에픽에서 낸 포트나이트로부터 온 것이었다. 포트나이트는 아트 디렉션이 포토리얼리스틱하지 않았고, 의도적으로 디퓨즈와 스페큘러 반사에 보색을 사용하고 있었고, 이것은 물리적으로 합당하지 않았고 우리의 새로운 머티리얼 모델에서 재현될 수 없었다.  긴 토론 끝에, 우리는 포트나이트의 퀄리티를 유지하기 위해 - 이미 많이 개발된 상태였으므로 - 이전의 디퓨즈컬러 / 스페큘러 컬러를 엔진 스위치로 계속 지원하기로 했다.  하지만 우리는 디즈니의 <주먹왕 랄프> 에서 보았듯 새로운 머티리얼 모델이 포토리얼리스틱하지 않은 렌더링을 배제시켰다고 생각하지는 않는다. 그래서 우리는 앞으로의 프로젝트들에도 이 머티리얼 모델을 계속 사용할 것이다.

 

머티리얼 레이어링

공유된 라이브러리에서 가져온 머티리얼 레이어들을 블렌딩하는 것은 예전의 접근보다도 많은 장점이 있다. 예전에는 머티리얼 파라미터를 각각의 모델을 위해 작성된 텍스처로부터 값을 확인해야 했다:

 

  • 많은 수의 에셋에 걸쳐 재사용이 가능하다.
  • 하나의 에셋 안에서 복잡도를 줄여준다.
  • 게임의 룩을 결정하는 머티리얼들을 통합하고 한데 모은다. 이는 아트와 테크 디렉션을 수월하게 해 준다.

 

이 새로운 워크플로우를 완전히 수용하기 위해서, 우리는 도구에 대해 재고해야 했다. 언리얼 엔진은 UE3 때부터 노드 그래프 기반의 머티리얼 에디터를 지원해왔다. 이 노드 그래프는 입력값(텍스처, 상수), 연산, 그리고 셰이더 코드에 컴파일되는 출력값들을 결정한다.

머티리얼 레이어링이 노동의 애초의 목적이었지만, 머티리얼 레이어를 작성하고 블렌딩하기 위해 툴 쪽에서 추가할 필요가 있었던 점들은 놀랍도록 적었다. UE4의 머티리얼 에디터 내의 노드 그래프 섹션은 펑션으로 그루핑되어 각기 다른 머티리얼들에서 사용될 수 있었다. 이 기능성은 머티리얼 레이어를 구현하기에 자연스레 맞아떨어졌다. 고정된 기능 시스템를 위에 덮는게 아닌, 노드 베이스의 에디터 안에 머티리얼 레이어를 가지고 있는 것은 레이어들이 프로그래머블한 방식으로 매핑되고 합쳐질 수 있도록 하였다.

워크플로우를 간소화하기 위해, 우리는 머티리얼 어트리뷰트라는 새로운 데이터 타입을 추가하였다. 이것은 모든 머티리얼 출력 데이터를 가진다. 이 새로운 타입의 데이터는, 다른 데이터 타입들과 마찬가지로 머티리얼 함수에 하나의 핀으로 입력 출력하고, 와이어를 통해 전달되어 직접 출력될 수 있다. 이 변화로 인해, 머티리얼 레이어들은 이전에 텍스처가 그러했듯이 입력값으로서 끌어다 쓰거나, 합성되거나 조정되어 출력될 수 있다.  사실, 대부분의 머티리얼 그래프는 레이어를 채택힌 이후로 단순해졌다. 특정 머티리얼에 대한 기본 맞춤식(custom)은 레이어가 매핑되고 혼합되는 방식이기 때문이다. 이것은 이전에 존재했던 파라미터 위주의 조작보다 훨씬 단순한 것이었다.

적은 셋트의 지각적으로 선형적인 파라미터들 덕분에, 셰이더 안에서 레이어를 전체 혼합하는 것이 사실 더 실용적이었다. 우리는 이 점이 순전히 오프라인에서 조합된 시스템보다 실질적인 퀄리티 향상을 낼 것이라고 생각했다. 텍스처 데이터의 분명한 해상도는, 데이터를 각기 다른 빈도로 매핑할 수 있으므로 극단적으로 높아질 수 있었다:버텍스 단위나 낮은 빈도의 텍스처 데이터는 또 다르고, 레이어 블렌드 미스크나, 노멀 맵과 캐비티 맵은 메쉬 단위로 결정되고, 머티리얼 레이어들은 메쉬의 표면을 따라 타일링된다.  더 나아간 경우는 더 높은 빈도일 수도 있다. 셰이더 비용 때문에 우리는 레이어 실 사용 갯수를 제한하였지만, 아티스트들은 여태 이 제한을 문제라고 느낀 적이 없다.

염려가 되는 부분은, 아티스트들은 셰이더 안에서의 레이어링 제한을 메쉬를 여러 섹션으로 나누는 것으로 해결했고,  이것은 더 많은 드로우 콜을 낳았다. CPU 쪽의 코드 최적화 때문에 UE4에서도 더 나은 드로우 콜 갯수를 기대하고 있지만, 이 부분은 나중에 문제의 근원이 될 소지가 있다. 한 레이어가 100%의 범위를 차지할때 다이내믹 브랜치를 사용해 셰이더 비용을 줄이는 것에 대해서는 아직 탐색해보지 않았다.

지금까지, 머티리얼 레이어들에 대한 우리의 경험은 지극히 긍정적이었다. 우리는 생산성 향상과 퀄리티의 큰 향상을 보았다. 우리는 머티리얼 레이어들을 찾고 미리보는 것을 더 쉽게 만들어서, 아티스트들이 사용하는 머티리얼 레이어 라이브러리 인터페이스를 더욱 향상시키고 싶다. 우리는 현재의 런타임 시스템에 더해 오프라인 합성, 베이킹 시스템에 대해서도 알아보고 있으며, 이것은 더 많은 수의 레이어를 지원하고 더욱 나은 확장성을 제공할 것이다.

녹과 레이어링된 머티리얼들

 

이 뒤부터는 라이팅 모델에 관한 내용... 차차 읽어볼 예정