다음을 통해 공유


질감 리소스 만들기(Direct3D 10)

텍스처 리소스는 구조화된 데이터 컬렉션입니다. 일반적으로 색 값은 텍스처에 저장되며, 렌더링 중 파이프라인의 다양한 단계에서 입력과 출력을 위해에 접근됩니다. 텍스처를 만들고 사용 방법을 정의하는 것은 Direct3D 10에서 흥미로운 장면을 렌더링하는 데 중요한 부분입니다.

텍스처는 일반적으로 색 정보를 포함하지만 다른 DXGI_FORMAT 사용하여 텍스처를 만들면 다양한 종류의 데이터를 저장할 수 있습니다. 그런 다음 Direct3D 10 파이프라인에서 이 데이터를 기존의 방식이 아닌 방식으로 활용할 수 있습니다.

모든 텍스처에는 사용하는 메모리 양과 포함된 텍셀 수에 제한이 있습니다. 이러한 제한은 리소스 상수 지정됩니다.

파일에서 질감 만들기

메모

D3DX 유틸리티 라이브러리 Windows 8에서는 사용되지 않으며 Windows 스토어 앱에서는 지원되지 않습니다.

 

Direct3D 10에서 텍스처를 만들 때 뷰를생성해야 합니다. 뷰는 렌더링 중에 텍스처에 액세스하는 방법을 디바이스에 알려주는 개체입니다. 텍스처에 액세스하는 가장 일반적인 방법은 셰이더사용하여 텍스처에서 읽는 것입니다. 셰이더 리소스 뷰는 렌더링하는 동안 텍스처에서 읽는 방법을 셰이더에게 알려줍니다. 텍스처를 만들 때 사용할 뷰 종류를 지정해야 합니다.

텍스처를 만들고 초기 데이터를 로드하는 방법은 텍스처와 뷰를 별도로 만들거나 텍스처와 뷰를 동시에 만드는 두 가지 방법으로 수행할 수 있습니다. API는 두 가지 기술을 모두 제공하므로 요구 사항에 더 적합한 기술을 선택할 수 있습니다.

텍스처 만들기 및 별도로 보기

텍스처를 만드는 가장 쉬운 방법은 이미지 파일에서 텍스처를 로드하는 것입니다. 텍스처를 만들려면 하나의 구조를 채운 후 D3DX10CreateTextureFromFile에 텍스처의 이름을 지정하세요.

ID3D10Device *pDevice = NULL;
// Initialize D3D10 device...

D3DX10_IMAGE_LOAD_INFO loadInfo;
ZeroMemory( &loadInfo, sizeof(D3DX10_IMAGE_LOAD_INFO) );
loadInfo.BindFlags = D3D10_BIND_SHADER_RESOURCE;

ID3D10Resource *pTexture = NULL;
D3DX10CreateTextureFromFile( pDevice, L"sample.bmp", &loadInfo, NULL, &pTexture, NULL );

D3DX10CreateTextureFromFile D3DX 함수는 세 가지 작업을 수행합니다. 첫째, Direct3D 10 텍스처 개체를 만듭니다. 둘째, 입력 이미지 파일을 읽습니다. 셋째, 텍스처 개체에 이미지 데이터를 저장합니다. 위의 샘플에서는 BMP 파일이 로드되지만 함수는 다양한 파일 형식을 로드할 수 있습니다.

바인딩 플래그는 렌더링하는 동안 셰이더 단계가 텍스처에서 읽을 수 있도록 하는 셰이더 리소스로 텍스처가 생성됨을 나타냅니다.

위의 예제에서는 모든 로드 매개 변수를 지정하지 않습니다. 실제로 입력 이미지에 따라 적절한 값을 선택할 수 있도록 D3DX에 맡기는 것이 좋으므로, 로드 매개 변수를 간단히 0으로 설정하는 것이 유리합니다. 입력 이미지에서 텍스처가 만들어지는 모든 매개 변수를 확인하려면 다음과 같이 loadInfo 매개 변수에 NULL 지정하기만 하면 됩니다.

D3DX10CreateTextureFromFile( pDevice, L"sample.bmp", NULL, NULL, &pTexture, NULL );

로드 정보에 NULL 지정하는 것은 간단하면서도 강력한 바로 가기입니다.

이제 텍스처가 만들어졌으므로 셰이더에 대한 입력으로 텍스처를 바인딩할 수 있도록 셰이더 리소스 뷰를 만들어야 합니다. D3DX10CreateTextureFromFile 텍스처에 대한 포인터가 아닌 리소스에 대한 포인터를 반환하므로 로드된 리소스의 정확한 유형을 결정해야 하며, CreateShaderResourceView사용하여 셰이더 리소스 뷰를 만들 수 있습니다.

D3D10_SHADER_RESOURCE_VIEW_DESC srvDesc;
D3D10_RESOURCE_DIMENSION type;
pTexture->GetType( &type );
switch( type )
{
    case D3D10_RESOURCE_DIMENSION_BUFFER:
    //...
    break;
    case D3D10_RESOURCE_DIMENSION_TEXTURE1D:
    //...
    break;
    case D3D10_RESOURCE_DIMENSION_TEXTURE2D:
    {
        D3D10_TEXTURE2D_DESC desc;
        ID3D10Texture2D *pTexture2D = (ID3D10Texture2D*)pTexture;
        pTexture2D->GetDesc( &desc );
        
        srvDesc.Format = desc.Format;
        srvDesc.ViewDimension = D3D10_SRV_DIMENSION_TEXTURE2D;
        srvDesc.Texture2D.MipLevels = desc.MipLevels;
        srvDesc.Texture2D.MostDetailedMip = desc.MipLevels -1;

    }
    break;
    case D3D10_RESOURCE_DIMENSION_TEXTURE3D:
    //...
    break;
    default:
    //...
    break;
}

ID3D10ShaderResourceView *pSRView = NULL;
pDevice->CreateShaderResourceView( pTexture, &srvDesc, &pSRView );

위의 샘플에서는 2D 셰이더 리소스 뷰를 만들지만 다른 셰이더-리소스 뷰 형식을 만드는 코드는 매우 유사합니다. 이제 모든 셰이더 단계에서 이 텍스처를 입력으로 사용할 수 있습니다.

D3DX10CreateTextureFromFileCreateShaderResourceView 사용하여 텍스처를 만들고 연결된 뷰를 사용하여 셰이더 스테이지에 바인딩할 질감을 준비하는 한 가지 방법입니다. 이렇게 하는 또 다른 방법은 텍스처와 뷰를 동시에 만드는 것입니다. 이 내용은 다음 섹션에서 설명합니다.

텍스처 만들기 및 동시에 보기

Direct3D 10을 사용하려면 런타임 중에 텍스처와 셰이더 리소스 뷰를 모두 텍스처에서 읽어야 합니다. 텍스처 및 셰이더 리소스 뷰를 만드는 것이 일반적인 작업이기 때문에, D3DX는 이를 위해 D3DX10CreateShaderResourceViewFromFile를 제공합니다.

D3DX10_IMAGE_LOAD_INFO loadInfo;
ZeroMemory( &loadInfo, sizeof(D3DX10_IMAGE_LOAD_INFO) );
loadInfo.BindFlags = D3D10_BIND_SHADER_RESOURCE;
loadInfo.Format = DXGI_FORMAT_BC1_UNORM;

ID3D10ShaderResourceView *pSRView = NULL;
D3DX10CreateShaderResourceViewFromFile( pDevice, L"sample.bmp", &loadInfo, NULL, &pSRView, NULL );

단일 D3DX 호출을 사용하면 텍스처 및 셰이더 리소스 뷰가 모두 만들어집니다. loadInfo 매개 변수의 기능은 변경되지 않습니다. 텍스처를 만드는 방법을 사용자 지정하거나 loadInfo 매개 변수에 NULL 지정하여 입력 파일에서 필요한 매개 변수를 파생할 수 있습니다.

D3DX10CreateShaderResourceViewFromFile 함수에서 반환된 ID3D10ShaderResourceView 개체는 나중에 필요한 경우 원래 ID3D10Resource 인터페이스를 검색하는 데 사용할 수 있습니다. 이 작업은 GetResource 메서드를 호출하여 수행할 수 있습니다.

D3DX는 하나의 함수를 제공하여 텍스처 및 셰이더 리소스 뷰를 편리하게 생성합니다. 텍스처를 생성하고 애플리케이션의 요구 사항에 가장 적합한 뷰를 결정하는 것은 사용자에게 달려 있습니다.

이제 텍스처 및 셰이더 리소스 뷰를 만드는 방법을 알게 되었으므로 다음 섹션에서는 셰이더를 사용하여 해당 텍스처에서 샘플링(읽기)하는 방법을 보여 줍니다.

빈 질감 만들기

경우에 따라 애플리케이션은 텍스처를 만들고 텍스처에 저장할 데이터를 계산하거나 그래픽 파이프라인 사용하여 이 텍스처에 렌더링하고 나중에 다른 처리에서 결과를 사용하려고 합니다. 이러한 텍스처는 텍스처를 만들 때 지정한 사용량 종류에 따라 그래픽 파이프라인 또는 애플리케이션 자체에서 업데이트할 수 있습니다.

텍스처로 렌더링

런타임 중에 데이터로 채울 빈 텍스처를 만드는 가장 일반적인 사례는 애플리케이션이 텍스처에 렌더링한 다음 후속 단계에서 렌더링 작업의 결과를 사용하려는 경우입니다. 이 용도로 만든 질감은 기본 사용지정해야 합니다.

다음 코드 샘플에서는 파이프라인이 렌더링할 수 있는 빈 텍스처를 만들고 이후에 셰이더입력으로 사용합니다.

// Create the render target texture
D3D10_TEXTURE2D_DESC desc;
ZeroMemory( &desc, sizeof(desc) );
desc.Width = 256;
desc.Height = 256;
desc.MipLevels = 1;
desc.ArraySize = 1;
desc.Format = DXGI_FORMAT_R32G32B32A32_FLOAT;
desc.SampleDesc.Count = 1;
desc.Usage = D3D10_USAGE_DEFAULT;
desc.BindFlags = D3D10_BIND_RENDER_TARGET | D3D10_BIND_SHADER_RESOURCE;

ID3D10Texture2D *pRenderTarget = NULL;
pDevice->CreateTexture2D( &desc, NULL, &pRenderTarget );

텍스처를 만들려면 애플리케이션에서 텍스처가 가질 속성에 대한 몇 가지 정보를 지정해야 합니다. 텍셀의 질감 너비와 높이는 256으로 설정됩니다. 이 렌더링 대상에는 단일 밉맵 수준만 필요합니다. 배열 크기가 1로 설정되도록 렌더링 대상은 하나만 필요합니다. 각 텍셀에는 매우 정확한 정보를 저장하는 데 사용할 수 있는 4개의 32비트 부동 소수점 값이 포함되어 있습니다(DXGI_FORMAT참조). 픽셀당 하나의 샘플만 필요합니다. 메모리에서 렌더링 대상을 가장 효율적으로 배치할 수 있으므로 사용이 기본값으로 설정됩니다. 마지막으로 텍스처가 렌더링 대상으로 바인딩되고 셰이더 리소스가 다른 시점에 지정됩니다.

파이프라인에 직접 렌더링하기 위해 텍스처를 바인딩할 수 없습니다. 다음 코드 샘플과 같이 렌더링 대상 보기를 사용합니다.

D3D10_RENDER_TARGET_VIEW_DESC rtDesc;
rtDesc.Format = desc.Format;
rtDesc.ViewDimension = D3D10_RTV_DIMENSION_TEXTURE2D;
rtDesc.Texture2D.MipSlice = 0;

ID3D10RenderTargetView *pRenderTargetView = NULL;
pDevice->CreateRenderTargetView( pRenderTarget, &rtDesc, &pRenderTargetView );

렌더링 대상 보기의 형식은 단순히 원래 질감의 형식으로 설정됩니다. 리소스의 정보는 2D 텍스처로 해석되어야 하며 렌더링 대상의 첫 번째 Mipmap 수준만 사용하려고 합니다.

렌더링 대상 뷰를 만들어 파이프라인에 대한 출력을 위해 렌더링 대상을 바인딩할 수 있도록 하는 방법과 마찬가지로 렌더링 대상을 입력으로 파이프라인에 바인딩할 수 있도록 셰이더 리소스 뷰를 만들어야 합니다. 다음 코드 샘플에서는 이를 보여 줍니다.

// Create the shader-resource view
D3D10_SHADER_RESOURCE_VIEW_DESC srDesc;
srDesc.Format = desc.Format;
srDesc.ViewDimension = D3D10_SRV_DIMENSION_TEXTURE2D;
srDesc.Texture2D.MostDetailedMip = 0;
srDesc.Texture2D.MipLevels = 1;

ID3D10ShaderResourceView *pShaderResView = NULL;
pDevice->CreateShaderResourceView( pRenderTarget, &srDesc, &pShaderResView );

셰이더 리소스 뷰 설명의 매개 변수는 렌더링 대상 뷰 설명과 매우 유사하며 동일한 이유로 선택되었습니다.

수동으로 텍스처 채우기

경우에 따라 애플리케이션은 런타임에 값을 계산하고, 수동으로 텍스처에 배치한 다음, 그래픽 파이프라인이 나중에 렌더링 작업에서 이 텍스처를 사용할 있습니다. 이렇게 하려면 애플리케이션에서 CPU가 기본 메모리에 액세스할 수 있도록 빈 텍스처를 만들어야 합니다. 이 작업은 동적 텍스처를 만들고 특정 메서드를 호출하여 기본 메모리에 대한 액세스 권한을 얻는 방식으로 수행됩니다. 다음 코드 샘플에서는 이 작업을 수행하는 방법을 보여 줍니다.

D3D10_TEXTURE2D_DESC desc;
desc.Width = 256;
desc.Height = 256;
desc.MipLevels = desc.ArraySize = 1;
desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
desc.SampleDesc.Count = 1;
desc.Usage = D3D10_USAGE_DYNAMIC;
desc.BindFlags = D3D10_BIND_SHADER_RESOURCE;
desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE;
ID3D10Texture2D *pTexture = NULL;
pd3dDevice->CreateTexture2D( &desc, NULL, &pTexture );

형식은 각 구성 요소가 8비트로 정의된 픽셀당 32비트로 설정됩니다. 사용량 매개 변수는 동적으로 설정되고 바인딩 플래그는 셰이더에서 텍스처에 액세스하도록 설정됩니다. 나머지 텍스처 설명은 렌더링 대상을 만드는 것과 비슷합니다.

호출하면 애플리케이션이 텍스처의 기본 메모리에 액세스할 수 있습니다. 그런 다음 검색된 포인터를 사용하여 텍스처를 데이터로 채웁니다. 이 내용은 다음 코드 샘플에서 확인할 수 있습니다.

D3D10_MAPPED_TEXTURE2D mappedTex;
pTexture->Map( D3D10CalcSubresource(0, 0, 1), D3D10_MAP_WRITE_DISCARD, 0, &mappedTex );

UCHAR* pTexels = (UCHAR*)mappedTex.pData;
for( UINT row = 0; row < desc.Height; row++ )
{
    UINT rowStart = row * mappedTex.RowPitch;
    for( UINT col = 0; col < desc.Width; col++ )
    {
        UINT colStart = col * 4;
        pTexels[rowStart + colStart + 0] = 255; // Red
        pTexels[rowStart + colStart + 1] = 128; // Green
        pTexels[rowStart + colStart + 2] = 64;  // Blue
        pTexels[rowStart + colStart + 3] = 32;  // Alpha
    }
}

pTexture->Unmap( D3D10CalcSubresource(0, 0, 1) );

다중 렌더 타겟

한 번에 최대 8개의 렌더링 대상 뷰를 파이프라인에 바인딩할 수 있습니다(OMSetRenderTargets). 각 픽셀(또는 다중 샘플링을 사용하는 경우 각 샘플)에 대해 혼합은 각 렌더링 대상 보기에 대해 독립적으로 수행됩니다. BlendEnable 및 RenderTargetWriteMask의 혼합 상태 변수 중 두 가지는 8개 배열이며, 각 배열 멤버는 렌더링 대상 뷰에 해당합니다. 여러 렌더링 대상을 사용하는 경우 각 렌더링 대상은 동일한 리소스 종류(버퍼, 1D 텍스처, 2D 텍스처 배열 등)이어야 하며 동일한 차원(너비, 높이, 3D 텍스처의 깊이 및 텍스처 배열의 배열 크기)이 있어야 합니다. 렌더링 대상이 다중 샘플링된 경우 모두 픽셀당 동일한 수의 샘플이 있어야 합니다.

활성 상태인 렌더링 대상 수에 관계없이 깊이 스텐실 버퍼가 하나만 활성화될 수 있습니다. 텍스처 배열을 렌더링 대상으로 사용하는 경우 모든 뷰 차원이 일치해야 합니다. 렌더링 대상의 질감 형식이 같을 필요는 없습니다.

리소스(Direct3D 10)