텍스처 적용(2) - 텍스처 생성

WanJu Kim·2022년 12월 29일

Direct3D

목록 보기
23/29

일반적으로 텍스처 자료는 디스크에 저장된 이미지 파일에서 읽어서 ID3D11Texture2D 객체에 적재한다. 텍스처는 알다시피 자원 뷰를 따로 만들어서 파이프라인에 묶어야 한다. 그 과정은 다음과 같다.

  1. D3DX11CreateTextureFromFile을 호출해서 디스크에 저장된 이미지 파일로부터 ID3D11Texture2D 객체를 생성한다.
  2. ID3D11Device::CreateShaderResourceView를 호출해서 그 텍스처에 대한 셰이더 자원 뷰를 생성한다.
  3. 픽셸 세이더에서 출력 코드를 작성한다.

첫 두 단계를 한꺼번에 해주는 함수가 D3DX에 있다.

HRESULT D3DX11CreateShaderResourceViewFromFile(
	ID3D11Device *pDevice,
	LPCTSTR pSrcFile,
	D3DX11_IMAGE_LOAD_INFO *pLoadInfo,
	ID3DXllThreadPump *pPump,
	ID3DllShaderResourceView **ppShaderResourceView,
	HRESULT *pHResult
);
  1. pDevice : 텍스처를 생성할 Direct3D 장치를 가리키는 포인터.
  2. pSrcFile : 경로를 포함한 이미지 이름.
  3. pLoadInfo : 추가적인 이미지 정보. 원본 이미지의 정보를 그대로 사용하려면 널 값을 지정한다.
  4. pPump : 새로운 스레드를 띄워서 자원을 적재할 때 쓰인다. 주 스레드에서 자원을 적재하려면 널 값을 지정하면 된다.
  5. ppShaderResourceView : 셰이더 자원 뷰를 가리키는 포인터를 돌려준다.
  6. pHResult : pPump에 널 값을 지정했다면, 여기에도 널 값을 지정한다.

이 함수는 BMP, JPG, PNG, DDS, TIFF, GIF, WMP 텍스처 파일 형식을 지원한다. 다음은 tree.png라는 이미지 파일로 텍스처를 생성하는 예이다.

ID3D11ShaderResourceView* mDiffuseMapSRV;
HR(D3DX11CreateShaderResourceViewFromFile(md3dDevice,
	L"./Tree.png", nullptr, nullptr, &srv, nullptr));

텍스처를 만들었다면, 이를 파이프라인에 묶어줘야 한다. 묶는 함수는 다음과 같이 PSSetShaderResources 함수를 이용한다.

m_immediateContext->PSSetShaderResources(0, 1, &srv);	

이 함수의 제1 매개변수는 시작 슬롯이다. 자원을 배열 형식으로 넘겨주는데 그 배열의 시작 슬롯을 말한다. 보통 0부터 시작한다. 제2 매개변수는 넘겨주는 개수이다. 우리는 1개만 넘기므로 1로 한다. 제3 매개변수는 배열 포인터를 반환해준다.

이러면 이제 픽셀 셰이더 안에서 받을 준비가 된 것이다. 셰이더의 텍스트 출력 부분 코드는 다음과 같다.

Texture2D sourceTex : register(t0);
SamplerState samp : register(s0);

float4 PS(PixelInput input) : SV_Target
{
    return sourceTex.Sample(samp,input.uv);
}

Texture2D sourceTex : register(t0); 이 문구가 텍스처 자원을 받는 문구다. 텍스처 객체를 나타내는 형식은 Texture2D이다.

여기서 상수 버퍼 때처럼 변수 뒤에 : register(t0)을 붙여줘야 한다. 달라진 건 뒤의 t0이다. 무슨 의미인가? t는 텍스처 자원을 받겠다는 뜻이고, 0은 텍스처 자원 배열의 인덱스이다. CPU에서 보내줄 때 배열 0번부터 시작해 1개 넣었으므로, 그 자원은 배열의 0에 있을 것이다. 그래서 저렇게 썼다. 만약 PSSetShaderResources(2, 1, &srv) 이런식으로 2번에서 시작해 1개 넣었으면 뭘로 받아야 할까? 당연히 2로 받으면 된다. Texture2D는 0 ~ 127까지 128개를 전달 받을 수 있다.

밑에 SamplerState samp : register(s0)은 무엇인가? CPU에서 넘길 수 있는 또 다른 자원 '샘플러'라는 건데, 굳이 안 받아도 출력할 수 있다. 그럼 왜 필요하냐? PS함수에 Sample 함수의 제1 매개변수로 필요하기 때문이다. Sample 함수는 '제1 매개변수에서 설정한 조건으로 샘플링해서, 호출 객체를, 제2 매개변수인 uv좌표 따라서 출력해주세요'라는 의미이다.

이렇게 하고 실행 하면 텍스처가 나온다.

profile
Question, Think, Select

0개의 댓글