텍스처 리소스 만들기(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 );
D3DX 함수 D3DX10CreateTextureFromFile 은 세 가지 작업을 수행합니다. 먼저 Direct3D 10 텍스처 개체를 만듭니다. 두 번째로 입력 이미지 파일을 읽습니다. 셋째, 텍스처 개체에 이미지 데이터를 저장합니다. 위의 샘플에서는 BMP 파일이 로드되지만 함수는 다양한 파일 형식을 로드할 수 있습니다.
바인딩 플래그는 렌더링하는 동안 셰이더 단계가 텍스처에서 읽을 수 있도록 텍스처가 셰이더 리소스로 생성됨을 나타냅니다.
위의 예제에서는 모든 로드 매개 변수를 지정하지 않습니다. 실제로 D3DX에서 입력 이미지에 따라 적절한 값을 선택할 수 있으므로 로드 매개 변수를 0으로 간단히 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 셰이더 리소스 뷰를 만들지만 다른 셰이더 리소스 뷰 형식을 만드는 코드는 매우 유사합니다. 이제 모든 셰이더 단계에서 이 텍스처를 입력으로 사용할 수 있습니다.
D3DX10CreateTextureFromFile 및 CreateShaderResourceView를 사용하여 텍스처를 만들고 연결된 뷰는 셰이더 단계에 바인딩할 텍스처를 준비하는 한 가지 방법입니다. 이렇게 하는 또 다른 방법은 다음 섹션에서 설명하는 텍스처와 뷰를 동시에 만드는 것입니다.
텍스처 만들기 및 동시에 보기
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으로 설정됩니다. 이 렌더링 대상의 경우 단일 Mipmap 수준이 필요합니다. 배열 크기가 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) );
여러 Rendertargets
최대 8개의 렌더링 대상 뷰를 한 번에 파이프라인에 바인딩할 수 있습니다( OMSetRenderTargets 사용). 각 픽셀(또는 다중 샘플링을 사용하는 경우 각 샘플)에 대해 각 렌더링 대상 보기에 대해 혼합이 독립적으로 수행됩니다. BlendEnable 및 RenderTargetWriteMask의 혼합 상태 변수 중 두 가지는 8개 배열이며, 각 배열 멤버는 렌더링 대상 뷰에 해당합니다. 여러 렌더링 대상을 사용하는 경우 각 렌더링 대상은 동일한 리소스 유형 (버퍼, 1D 텍스처, 2D 텍스처 배열 등)이어야 하며 동일한 차원(너비, 높이, 3D 텍스처의 깊이 및 텍스처 배열의 배열 크기)을 가져야 합니다. 렌더링 대상이 다중 샘플링된 경우 모두 픽셀당 동일한 수의 샘플이 있어야 합니다.
활성 렌더링 대상 수에 관계없이 하나의 깊이 스텐실 버퍼만 활성 상태일 수 있습니다. 텍스처 배열을 렌더링 대상으로 사용하는 경우 모든 뷰 차원이 일치해야 합니다. 렌더링 대상은 동일한 텍스처 형식을 가질 필요가 없습니다.
관련 항목