1. 문제 상황
이렇게 정점은 위치/normal/색/uv좌표 순으로 Shader에 넘겨주고 있었고
Pixel Shader에서는 적절히 받아온 텍스처를 Sampling해주고 있었습니다.
그런데 여기서 발생한 문제점이 Texture의 색들이 전부 섞여서 나타나는 것이었습니다.
색이 섞이는 것을 알게 될때 까지도 상당한 시간이 소요 됐습니다.
우선 위의 사진처럼 큐브 텍스처를 넘겨주게 되면 전체가 회색으로 렌더링 되었습니다.
2. 원인 추론
문제를 바탕으로 추론한점은 다음과 같습니다.
2-1. UV좌표가 잘못 됐나?
UV좌표가 잘못 넘어가서 큐브 텍스처 바깥에 있는 회색 공간에 Mapping이 되어있는 것인가?
그러나 이 추측은 잘못된 것으로 밝혀 졌는데
그 이유는 아래 처럼 텍스처를 변경한뒤 파이프 라인에 넘겨주니 큐브색이 더 어두워졌다는 점이었습니다.
2-2. Texture의 색이 전부 섞이는 것인가?
그러던 중 갑자기 든 생각은 텍스처의 색을 전부 섞어서 렌더하는것이 아닐까라는 추측을 하게 되었고
사진처럼 텍스처를 만들어서 파이프 라인에 넘겨 주었습니다.
저의 추측대로 현재 텍스처로 넘겨준 색들을 전부 섞어서 렌더링 한다는 점을 발견했습니다. (빨강 + 노랑 = 주황)
여기까지 알아내고 답을 알아내기 까지는 한나절 이상의 시간이 소요 됐습니다..
3. 문제 해결 과정
3-1. Vertex가 Shader에 맵핑되기 직전의 정점 정보들을 확인
정상적으로 들어오고 있었다.
3-2. Input layout에서 혹시나 크기를 잘못 잡아주거나 순서가 잘못 되어있지는 않나 확인
정상적인 순서 였다.
D3D11_INPUT_ELEMENT_DESC layout[] =
{
{ "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 },
{ "NORMAL", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 },
{ "COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 },
{ "TexCoord", 0, DXGI_FORMAT_R32G32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 },
};
3-3. 혹시나 쉐이더를 잘못 맵핑해 주고 있는 것이 아닌가?
쉐이더에 있는 행렬 변환 코드 삭제시 큐브가 렌더링 안되는 현상으로 볼때
쉐이더에는 일단 값이 들어오긴 하는것으로 판단했습니다.
3-4. 쉐이더에 들어오는 UV값을 확인하기 위해서 아래과 같이 쉐이더 코드를 변경
초록색으로 큐브가 변했고, UV에는 0,1만 넘어오고 있다고 판단했습니다.
만약 UV가 정점마다 할당된 다른 값이 었다면 이렇게 단색으로 나오는 것이 아닌 그라데이션이 나와야 합니다.
즉 UV값이 어디선가 소실되고 있다는 것을 알게 됐습니다.
float4 mainPS(PS_INPUT Input) : SV_TARGET
{
float2 UV = Input.Tex;
return float4(UV, 0, 1); // UV 좌표를 색상으로 표현
}
3-4를 통해 UV자체에 정상적인 값이 넘어오지 않는것은 확인됐으나 결과적으로 어떤것이 문제인지는 알 수 없었다.
4. 결론 및 원인
정점데이터를 구성하는 FVector 구조체들이 alignas(16)으로 되어있었기 때문...
처음 봤던 키워드였기에 alignas라는 키워드랑 UV가 넘어가지 못하는 것이랑 무슨 연관이 있나 생각을 해보았습다.
alignas(16)이라는 키워드는 구조체 요소들을 16바이트로 정렬한다는 의미입니다.
그래서 만약 FVector2처럼 float 2개를 가지는 구조체에 이 키워드를 붙혀주는 경우 모자란 8바이트 만큼
Padding(빈공간)이 삽입되게 되고 결국이 자료가 파이프라인으로 넘어갈때 Padding이란 쓰레기값을 넘겨주기에
이러한 문제가 생겼다고 추측하고 있습니다.
애초에 layout을 잡아줄때 들어가는 값들의 크기를 정해주고 있습니다.
8바이트(u,v)만 정확히 넘어가야 하는데
쓰레기값이 섞여 있었음으로 정상적으로 uv가 넘어갈 수 없던 것이었습니다.
아래 영상은 align을 지우고 실행했을때의 모습입니다. 이전처럼 초록색 단색으로 나오는 것이 아닌
uv좌표에 따라서 자연스러운 그라데이션이 연출되고 있고,
이는 uv좌표가 이전처럼 고정된 값이 아닌 정점마다 설정해준 적절한 값이 넘어오는 것으로 추론할 수 있습니다.
1.결론 키워드를 쓰려면 꼭 잘 알아보고 사용하자!
2. 쉐이더 디버깅은 매우 어렵다.
3. 상용엔진에 감사한다.
'DirectX11' 카테고리의 다른 글
[DX11] Matarial Sorting을 통한 최적화 (0) | 2025.03.29 |
---|---|
[DX11] Constant Buffer에 값 넘길 때 주의할 점(Shader로 Matarial값 넘길 때 주의할점) (0) | 2025.03.26 |
[DX11] UV좌표를 활용한 Text 렌더링 (0) | 2025.03.19 |
[DX11] Texture Atlas, UV좌표계 (0) | 2025.03.19 |
[DX11] Shader Resource View(SRV), Sampler에 대해서 (0) | 2025.03.18 |