오늘까지 수업시간을 통해 만든 DX 엔진에서 드디어 mesh 데이터를 import를 해서 draw을 하는데... 읭?? '솔져'의 왼쪽 발에 텍스처가 없는 듯 발이 시커멓게 나옵니다 ㅠㅠ
에이 설마 하며 텍스처 파일을 보니.. 당연히(?) 텍스처 파일은 문제가 없었어요. 그렇다면 혹시 모델링 mesh에 문제가 있으려나요?
학원에는 마야(autodesk Maya™)가 설치 안되어 있어서 집에 와서야 soldier.fbx파일을 '마야'로 열어보았습니다. 가끔 3D 작업 툴에서 fbx로 export를 할때 노말(normal)이 꼬이는 경우가 있어서.. 이번에도 그런 경우일까 싶은 생각이 들었어요.
마야로 열어보니 '엔진'에서는 볼 수 없었던 '포즈'가 표현이 되는군요 ㅎㅎ 그건 그렇고 '마야'에서는 텍스처가 정상적으로 보이네요.
그리고 혹시나 했던 노말 방향도 정상입니다. (마야나 맥스에서는 노말이 뒤집히면 텍스처가 (1) 그래도 제대로 보이는 경우도 있고 (2) 어떤 경우에는 시커멓게 표현이 되는 경우도 있습니다)
흠.. 암튼 mesh에는 문제가 없고 그렇다면 분명 UV가 꼬이거나 뭔가.. 암튼 UV에 문제가 있을 듯 해요. 그래서 UV Editor로 UV 상태를 체크해봤습니다.
역시 UV 문제네요! 우상단 UV 좌표계에 있어야 할 UV중 왼쪽 발에 해당되는 UV 부분이 범위를 벗어나 있네요 ㅡ,.ㅡ;
사실 이 부분은 개발자의 입장에서 보면 디자이너의 실수가 아니냐고 할 수도 있지만 UV가 복잡한 경우 가끔 디자이너가 이렇게 작업을 하기도 합니다. 물론 이게 좋은 방법은 아니지만.. 3D 툴에서는 친절하게도 이런 것들도 아주 잘 처리를 해주고 있으니까요 ^^;; (자칫 이런 걸로 디자이너와 개발자 간에 다툼이 발생하기도 하겠네요 ㅎㅎ)
실제로 마야나 맥스 등 3D 툴에서는 프로그램에서 알아서 UV 범위를 벗어나는 범위를 반복 처리를 해줘서 디자이너가 모델링을 할 때는 아무런 문제가 없답니다. (렌더링 및 최종 파이널까지도 전혀 문제가 없구요~)
자, 어쨌든 문제점은 찾았으니 해결 방법을 찾아야 합니다. 2가지 방법 중 하나이겠죠. (1) 모델링 데이터에서 UV를 알맞게 다시 수정을 해주는 방법과 (2) 모델링 데이터는 손대지 않고 범위를 벗어난 UV를 엔진에서 코드로 처리를 해주는 방법이 있을 텐데요 디자이너 입장에서는 당연히 (1)의 방법이 편하고 빠르겠지만 개발자가 처리를 해야 한다는 상황에서 (2)의 방법으로 해결을 해보고자 했습니다.
우선은 그동안 우리가 만든 엔진은 아무래도 기본에 충실하게 구현을 하게 됨에 따라 이렇게 디자이너의 귀여운(?) 실수로 인해 범위를 벗어나는 UV 좌표를 처리하는 부분을 고려하지 않았을 가능성이 있을 거란 생각이 들었습니다.
그래서 소스 파일을 열어보니.. (이 부분 소스코드는 직접 작성한 것이 아니라서 금방 찾지는 못하고 살짝 헤매긴 했어요 ㅋㅋ)
역시 예상대로 UV 어드레싱 범위를 타이트하게 구현을 했더라구요. UV 좌표계에서 기본적으로 사용하는 0에서 1까지의 범위를 벗어나는 부분은 'CLAMP'를 시켜주고 있어요.
그래서 '솔져'의 왼쪽발의 UV가 엉뚱한 UV 좌표 공간에 있는 것을 과감히 CLAMP를 해서 처리를 하지 않았기에 그냥 black으로 그려진 것 같습니다.
MS DirectX11문서 중에 'D3D11_TEXTURE_ADDRESS_MODE' 부분을 참고해보니 모드 1번, 'WRAP'이라고 하는 랩핑 모드가 있더군요. (참고 : https://docs.microsoft.com/en-us/windows/win32/api/d3d11/ne-d3d11-d3d11_texture_address_mode)
모델링 파일에서 UV맵 좌표 공간에서 U방향으로만 벗어났으니 AddressU 부분만 기존 어드레싱 모드 D3D11_TEXTURE_ADDRESS_CLAMP를 D3D11_TEXTURE_ADDRESS_WRAP으로 바꿔주면 될 것 같아요.
코드를 수정하고 다시 실행 해보니 이제 '솔져'의 왼쪽발도 제대로 텍스처가 입혀져 잘 그려지고 있네요.
아래는 수정된 SamplerState.cpp 코드입니다.
#include "Core.h"#include "SamplerState.h"#include <Utility/STLException.h>
namespace STL{ SamplerState::SamplerState() : samplerState(nullptr) { }
SamplerState::~SamplerState() { SafeRelease(samplerState); }
void SamplerState::Create(ID3D11Device* device) { // 샘플러 스테이트 생성. D3D11_SAMPLER_DESC samplerDesc = {}; samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; samplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP; samplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP; samplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP;
auto result = device->CreateSamplerState(&samplerDesc, &samplerState); ThrowIfFailed(result, "Failed to create sampler state"); }
void SamplerState::Bind(ID3D11DeviceContext* context, uint32 index) { context->PSSetSamplers(index, 1, &samplerState); }}
#DirectX
#texture
#UVcoord
#UVAddressMode
#SamplerState
#CLAMP
#WRAP
#다이렉트X샘플링
#sampler
0 comments:
댓글 쓰기