효과 그래프의 정밀도 및 숫자 클리핑

Direct2D를 사용하여 효과를 렌더링하는 애플리케이션은 숫자 정밀도와 관련하여 원하는 수준의 품질 및 예측 가능성을 달성하기 위해 주의해야 합니다. 이 항목에서는 다음과 같은 경우에 유용한 Direct2D의 모범 사례 및 관련 설정에 대해 설명합니다.

  • 효과 그래프는 [0, 1] 범위를 벗어나는 높은 숫자 정밀도 또는 색을 사용하며 항상 사용할 수 있는지 확인하려고 합니다.
  • 또는 효과 그래프는 렌더링 구현을 사용하여 중간 색을 [0, 1] 범위로 고정하고 이 클램핑이 항상 발생하도록 합니다.

Direct2D는 종종 효과 그래프를 섹션으로 나누고 각 섹션을 별도의 단계로 렌더링합니다. 일부 단계의 출력은 기본적으로 제한된 숫자 범위와 정밀도를 갖는 중간 Direct3D 텍스처에 저장될 수 있습니다. Direct2D는 이러한 중간 텍스처가 사용되는지 또는 어디에 사용되는지 보장하지 않습니다. 이 동작은 GPU 기능과 Windows 버전에 따라 달라질 수 있습니다.

Windows 10 Direct2D는 셰이더 연결 사용으로 인해 더 적은 중간 텍스처를 사용합니다. 따라서 Direct2D는 이전 Windows 릴리스와 기본 설정을 사용하여 다른 결과를 생성할 수 있습니다. 이는 주로 효과 그래프에서 셰이더 연결이 가능하고 해당 그래프에 확장 범위 출력 색을 생성하는 효과도 포함된 시나리오에 영향을 줍니다.

효과 렌더링 및 중간의 개요

효과 그래프를 렌더링하기 위해 Direct2D는 먼저 "transforms"의 기본 그래프를 찾습니다. 여기서 변환은 효과 내에서 사용되는 그래프 노드입니다. Direct2D에서 사용할 Direct3D 셰이더를 제공하는 변환을 포함하여 다양한 유형의 변환이 있습니다.

예를 들어 Direct2D는 다음과 같이 효과 그래프를 렌더링할 수 있습니다.

중간 텍스처가 있는 효과 그래프

Direct2D는 효과 그래프를 렌더링하는 데 사용되는 중간 텍스처 수를 줄일 기회를 찾습니다. 이 논리는 애플리케이션에 불투명합니다. 예를 들어 Direct2D는 하나의 Direct3D 그리기 호출과 중간 텍스처를 사용하지 않고 다음 그래프를 렌더링할 수 있습니다.

중간 텍스처가 없는 효과 그래프

Windows 10 전에 Direct2D는 동일한 효과 그래프 내에서 여러 픽셀 셰이더를 사용하는 경우 항상 중간 텍스처를 사용합니다. 색상 값을 단순히 조정하는 대부분의 기본 제공 효과(예: 밝기 또는 채도)는 픽셀 셰이더를 사용하여 적용됩니다.

Windows 10 Direct2D는 이러한 경우 중간 텍스처를 사용하지 않을 수 있습니다. 이 작업은 인접한 픽셀 셰이더를 내부적으로 연결하여 수행합니다. 예:

여러 픽셀 셰이더가 있고 중간 텍스처가 없는 windows 10 효과 그래프

그래프의 인접한 모든 픽셀 셰이더가 함께 연결될 수 있는 것은 아니므로 특정 그래프만 Windows 10 다른 출력을 생성합니다. 자세한 내용은 효과 셰이더 연결을 참조하세요. 주요 제한 사항은 다음과 같습니다.

  • 첫 번째 효과가 여러 효과에 대한 입력으로 연결된 경우 효과는 출력을 사용하는 효과와 연결되지 않습니다.
  • 첫 번째 효과가 출력과 다른 논리적 위치에서 입력을 샘플하는 경우 효과는 해당 입력으로 설정된 효과와 연결되지 않습니다. 예를 들어 색 행렬 효과는 해당 입력과 연결될 수 있지만 컨볼루션 효과는 연결되지 않습니다.

기본 제공 효과 동작

대부분의 기본 제공 효과는 입력 색이 해당 범위 내에 있는 경우에도 설명되지 않은 색 공간에서 [0, 1] 범위 외부의 색을 생성할 수 있습니다. 이 경우 이러한 색은 숫자 클리핑의 영향을 받을 수 있습니다. 기본 제공 효과가 일반적으로 미리 곱한 공간에서 색을 생성하더라도 미리 설명되지 않은 공간에서 색 범위를 고려하는 것이 중요합니다. 이렇게 하면 다른 효과가 이후에 더 이상 설명되지 않더라도 색이 범위 내에 유지됩니다.

이러한 범위를 벗어난 색을 내보낼 수 있는 효과 중 일부는 "ClampOutput" 속성을 제공합니다. 여기에는 다음이 포함됩니다.

이러한 효과에 대해 ClampOutput 속성을 TRUE로 설정하면 셰이더 연결과 같은 요인에 관계없이 일관된 결과가 달성됩니다. 클램핑은 설명되지 않은 공간에서 발생합니다.

다른 기본 제공 효과는 해당 색 픽셀(및 "Color" 속성이 있는 경우)이 해당 범위 내에 있는 경우에도 설명되지 않은 공간에서 [0, 1] 범위를 초과하는 출력 색을 생성할 수 있습니다. 여기에는 다음이 포함됩니다.

효과 그래프 내에서 숫자 클리핑 강제 적용

ClampOutput 속성이 없는 위에 나열된 효과를 사용하는 동안 애플리케이션은 숫자 클램핑을 강제 적용하는 것을 고려해야 합니다. 이 작업은 해당 픽셀을 고정하는 그래프에 추가 효과를 삽입하여 수행할 수 있습니다. 색 행렬 효과를 사용할 수 있습니다. 이 속성은 'ClampOutput' 속성이 TRUE로 설정되고 'ColorMatrix' 속성을 기본값(통과) 값으로 그대로 둡니다.

일관된 결과를 얻기 위한 두 번째 옵션은 Direct2D가 정밀도가 더 높은 중간 텍스처를 사용하도록 요청하는 것입니다. 이 작업이 아래에 설명되어 있습니다.

중간 텍스처의 정밀도 제어

Direct2D는 그래프의 정밀도를 제어하는 몇 가지 방법을 제공합니다. Direct2D에서 높은 정밀도 형식을 사용하기 전에 애플리케이션은 GPU에서 충분히 지원되는지 확인해야 합니다. 이를 검사 ID2D1DeviceContext::IsBufferPrecisionSupported를 사용합니다.

애플리케이션은 WARP(소프트웨어 에뮬레이션)를 사용하여 Direct3D 디바이스를 만들어 모든 버퍼 정밀도가 디바이스의 실제 GPU 하드웨어와 독립적으로 지원되도록 보장할 수 있습니다. 디스크에 저장하는 동안 사진에 효과를 적용하는 등의 시나리오에서 권장됩니다. Direct2D가 GPU에서 높은 정밀도 버퍼 형식을 지원하는 경우에도 일부 저전력 모바일 GPU에서 셰이더 산술 및 샘플링의 제한된 정밀도로 인해 기능 수준 9.X GPU에서 이 시나리오에서 WARP를 사용하는 것이 좋습니다.

아래의 각 경우에서 요청된 정밀도는 실제로 Direct2D에서 사용할 최소 정밀도입니다. 중간이 필요하지 않은 경우 더 높은 정밀도를 사용할 수 있습니다. Direct2D는 동일한 그래프 또는 다른 그래프의 여러 부분에 대해 중간 텍스처를 완전히 공유할 수도 있습니다. 이 경우 Direct2D는 관련된 모든 작업에 대해 요청된 최대 정밀도를 사용합니다.

ID2D1DeviceContext::SetRenderingControls의 전체 자릿수 선택

Direct2D 중간 텍스처의 정밀도를 제어하는 가장 간단한 방법은 ID2D1DeviceContext::SetRenderingControls를 사용하는 것입니다. 이렇게 하면 전체 자릿수가 효과 또는 변환에 대해 수동으로 설정되지 않는 한 모든 중간 텍스처의 정밀도를 제어합니다.

if (Device->IsBufferPrecisionSupported(D2D1_BUFFER_PRECISION_32BPC_FLOAT))
{
  // Get the current rendering controls
  D2D1_RENDERING_CONTROLS renderingControls = {};
  Context->GetRenderingControls(&renderingControls);

  // Switch the precision within the rendering controls and set it
  renderingControls.bufferPrecision = D2D1_BUFFER_PRECISION_32BPC_FLOAT;
  Context->SetRenderingControls(&renderingControls);
}
              

입력 및 렌더링 대상에서 정밀도 선택

또한 애플리케이션은 중간 텍스처의 정밀도를 제어하기 위해 효과 그래프에 대한 입력의 정밀도에 의존할 수 있습니다. 이는 ID2D1DeviceContext::SetRenderingControls를 사용하여 버퍼 정밀도를 지정하지 않고 효과 및 변환에 대해 수동으로 설정되지 않는 한 마찬가지입니다.

효과에 대한 입력의 정밀도는 그래프를 통해 전파되어 다운스트림 중급자의 정밀도를 선택합니다. 효과 그래프의 여러 분기가 충족되는 경우 입력의 전체 자릿수가 가장 높습니다.

Direct2D 비트맵을 기반으로 선택한 전체 자릿수는 픽셀 형식에서 결정됩니다. ID2D1ImageSource에 대해 선택된 전체 자릿수는 ID2D1ImageSource를 만드는 데 사용되는 기본 IWICBitmapSource의 WIC 픽셀 형식에서 결정됩니다. Direct2D는 Direct2D 및 GPU에서 지원하지 않는 정밀도를 사용하여 WIC 원본으로 이미지 원본을 만들 수 없습니다.

Direct2D는 입력에 따라 효과 정밀도를 할당할 수 없습니다. 이 문제는 효과에 입력이 없거나 특정 정밀도 없이 ID2D1CommandList 가 사용될 때 발생합니다. 이 경우 중간 텍스처의 정밀도는 컨텍스트의 현재 렌더링 대상으로 설정된 비트맵에서 결정됩니다.

효과 및 변환에 직접 정밀도 선택

중간 텍스처의 최소 정밀도는 효과 그래프 내의 명시적 위치에서 설정할 수도 있습니다. 고급 시나리오에만 권장됩니다.

다음과 같이 효과에 대한 속성을 사용하여 최소 정밀도를 설정할 수 있습니다.

if (Device->IsBufferPrecisionSupported(D2D1_BUFFER_PRECISION_32BPC_FLOAT))
{
  hr = Effect->SetValue(D2D1_PROPERTY_PRECISION, D2D1_BUFFER_PRECISION_32BPC_FLOAT);
}
              

효과 구현 내에서 다음과 같이 ID2D1RenderInfo::SetOutputPrecision을 사용하여 최소 정밀도를 설정할 수 있습니다.

if (EffectContext->IsBufferPrecisionSupported(D2D1_BUFFER_PRECISION_32BPC_FLOAT))
{
  hr = RenderInfo->SetOutputBuffer(
  D2D1_BUFFER_PRECISION_32BPC_FLOAT,
  D2D1_CHANNEL_DEPTH_4);
}
              

효과에 설정된 정밀도는 해당 다운스트림 효과에 대해 다른 정밀도를 설정하지 않는 한 동일한 효과 그래프의 다운스트림 효과로 전파됩니다. 효과 내의 변환에 설정된 정밀도는 다운스트림 변환 노드의 정밀도에 영향을 주지 않습니다.

다음은 지정된 변환 노드의 출력을 저장하는 중간 버퍼의 최소 정밀도를 결정하는 데 사용되는 전체 재귀 논리입니다.

중간 버퍼 최소 정밀도 논리