Directx12 3D 프로그래밍 입문/9.텍스처 적용
9.11 언덕 과 파도 예제
ftftgop3
2023. 9. 21. 20:22
1. 땅 매쉬에 풀 텍스처를 타일 방식으로 입힌다
2. 물 텍스처가 시간 함수에 따라 스크롤 기능
풀 텍스처를 땅 매쉬에 확대해서 입히면 결함이 생기기 때문에 타일 방식으로 입힘
저 해상도 텍스처를 사용해도 확대에 의한 결함이 생기지 않게 하기 위해서 타일 방식 사용
격차 텍스처 좌표 생성
그림을 보면 xz 평면의 정점에서의 격자 정점$v_{ij}$
텍스처 좌표어서 보면 텍스처 공간에서 ij 번째 격자 정점 좌표에 대응
실제 코드로 적용
GeometryGenerator::MeshData GeometryGenerator::CreateGrid(float width, float depth, uint32 m, uint32 n)
{
MeshData meshData;
uint32 vertexCount = m*n;
uint32 faceCount = (m-1)*(n-1)*2;
//
// Create the vertices.
//
float halfWidth = 0.5f*width;
float halfDepth = 0.5f*depth;
float dx = width / (n-1);
float dz = depth / (m-1);
//u, v 좌표 사이의 거리 값 연산
float du = 1.0f / (n-1);
float dv = 1.0f / (m-1);
meshData.Vertices.resize(vertexCount);
for(uint32 i = 0; i < m; ++i)
{
float z = halfDepth - i*dz;
for(uint32 j = 0; j < n; ++j)
{
float x = -halfWidth + j*dx;
meshData.Vertices[i*n+j].Position = XMFLOAT3(x, 0.0f, z);
meshData.Vertices[i*n+j].Normal = XMFLOAT3(0.0f, 1.0f, 0.0f);
meshData.Vertices[i*n+j].TangentU = XMFLOAT3(1.0f, 0.0f, 0.0f);
//텍스처를 확대해서 그리드를 덮게 한다
meshData.Vertices[i*n+j].TexC.x = j*du;
meshData.Vertices[i*n+j].TexC.y = i*dv;
}
}
텍스처 타일링
위에서의 계산에는 텍스처 좌표가 $[0 , 1] ^2$ 벗어나지 않아서 타일링이 발생하지 않는다
타일링 하기 위해서 좌표 지정 모드를 순환 모드로 설정,
텍스처 좌표 성분을 5배로 비례 해서 치역 $[0, 5]^2$으로 사상
아래의 코드는 렌더링 시 비례 행렬을 지정하는 예제
void TexWavesApp::BuildRenderItems()
{
auto wavesRitem = std::make_unique<RenderItem>();
wavesRitem->World = MathHelper::Identity4x4();
//5 x 5 비례 행렬을 텍스처 변환 행렬에 넣어 준다
XMStoreFloat4x4(&wavesRitem->TexTransform, XMMatrixScaling(5.0f, 5.0f, 1.0f));
wavesRitem->ObjCBIndex = 0;
//....
}
텍스처 애니메이션
물 텍스처 스크롤 하는 AnimatMaterials() 추가
텍스처의 순환 지정 모드와 이음매 없은 물 텍스처 사용
void TexWavesApp::AnimateMaterials(const GameTimer& gt)
{
//물 재질 텍스처 좌표를 스크롤
auto waterMat = mMaterials["water"].get();
//현재 값을 받아오고
float& tu = waterMat->MatTransform(3, 0);
float& tv = waterMat->MatTransform(3, 1);
//애니메이션 값 추가
tu += 0.1f * gt.DeltaTime();
tv += 0.02f * gt.DeltaTime();
//최대 값을 넘으면 초기값 -1 변경
if(tu >= 1.0f)
tu -= 1.0f;
if(tv >= 1.0f)
tv -= 1.0f;
//계산한 애니메이션 값을 지정
waterMat->MatTransform(3, 0) = tu;
waterMat->MatTransform(3, 1) = tv;
//재질 업데이트 시 상수 버퍼 갱신 값 지정
waterMat->NumFramesDirty = gNumFrameResources;
}
참고 및 내용 출처
프랭크 D 루나 지음, 류광 옮김
한빛 미디어
Directx 12를 이용한 3D 게임 프로그래밍 입문(2017)