DirectX11

[DX11] Constant Buffer에 값 넘길 때 주의할 점(Shader로 Matarial값 넘길 때 주의할점)

yeoul0714 2025. 3. 26. 12:09

1. 개요


 

Matarial에는 정말 다양한 값들이 있습니다.

 

기본적으로 아래와 같은 값들이 쉐이더로 넘어오도록 설계하고 있습니다.

 

텍스처의 다양한 상태를 조절하는 값들입니다.

buffer MaterialCB : register(b4)
{
    float3 Ambient;
    float Opacity;
    float3 Diffuse;
    float Transparency; 
    float3 Specular;
    float RefractiveIndex;  
    float3 Emissive;
    float SpecularExponent;  
    int IlluminationModel;
};

 

그렇다면 이 값들을 constant buffer를 통해 shader에 넘겨줄 때 주의해야 할 점은 무엇이 있을까요?

오늘 소개해 드릴 예시는 실제 프로젝트 중 상당한 시간을 소요하게 만든 문제를 소개해 드리려고 합니다.

사실 알고 난 후에 보면 굉장히 간단한 문제이지만 DX를 처음 접해본다면 상당히 헤맬 수 있는 부분이기도 합니다.


 

 

2. 주의 할 점


2-1. Constant Buffer Slot확인

Constant Buffer의 Slot은 register(b4)에서 b4를 의미합니다.

4번 슬롯

 

아래 코드는 Material에 값을 넘겨주는 Constant Buffer를 Pipeline에 binding하는 코드입니다.

 

PSSetConstantBuffers라는 함수를 보면 4, 1을 인수로 넘겨주고 있는데

 

첫 번째 인자는 시작 슬롯, 두 번째는 넘겨줄 버퍼의 수입니다.

 

즉 b4로 Shader에서 받아주고 있다면 Binding 해줄 때에 4번 슬롯에 Binding해주어야 한다는 의미입니다.

 

이 숫자를 잘못 맞추어 주면, 상수 버퍼로 값이 넘어가지 않는 문제가 발생합니다.

if (UDXDConstantBuffer* DXDCB = ConstantBuffers[EConstantBufferType::Material])
{
	if (ID3D11Buffer* CbMaterial = DXDCB->GetConstantBuffer())
	{
		DXDDeviceContext->PSSetConstantBuffers(4, 1, &CbMaterial);
	}
}

 

 

2-2. Binding함수 실수

 

두 번째는 함수 실수 문제였습니다. 

 

문제 1을 해결했음에도 여전히 값은 넘어오지 않았습니다.

 

현재 Matarial값들은 전부 Pixel Shader에서 사용 중입니다.

 

그렇다면 Pipeline에 Binding 해줄 때에 당연하게도 

 

PSSetContantBuffers라는 함수를 사용 해야하지만 저는 미숙하게도 VSSetConstantBuffers를 사용 중이었습니다.

 

당연하게도 Vertex Shader에 Binding 해주었기에 Pixel Shader에서는 사용할 수 없는 값이었던 것입니다.

 

 

3-3. Constant Buffer의 정렬문제

2번까지 해결하니 다행히 값이 넘어오기 시작했습니다. 

 

그런데 이상하게도 값이 넘어오긴 하는데 mtl파일에서 설정된 값과는 다른 값이 넘어오는 문제가 생겼습니다.

 

그 이유는 바로 DirectX에서 cbuffer의 데이터는 항상 16바이트 단위로 정렬되기 때문입니다.

 

shader 코드를 보면 지금은 float3/float 이 번갈아 가며 선언되어서 16바이트 단위로 데이터를 맞추어 주고 있습니다.

 

그러나 과거 코드를 보면 float3 타입의 값들이 모두 위로 몰려있었습니다.

 

이렇게 되면 각 자료는 12바이트인데 16바이트 단위로 데이터를 잘라서 읽다 보니 온전히 데이터를 읽지 못하고

 

개발자의 의도와는 다르게 값을 읽는 현상이 생겼습니다.

buffer MaterialCB : register(b4)
{
    float3 Ambient;
    float Opacity;
    float3 Diffuse;
    float Transparency; 
    float3 Specular;
    float RefractiveIndex;  
    float3 Emissive;
    float SpecularExponent;  
    int IlluminationModel;
};

 

다들 사소한 실수 조심하시고 개발 파이팅하시길!