앞서 공부한 정점들을 나열한 Grid, 그리고 사각형들의 좌표에 UV좌표를 정규화해 부여하고 픽셀마다 이미지를 붙이는 Texture, 2가지를 사용해 그럴듯한 지형을 만들어보자.
먼저 Grid를 다시 복습해보자면, 3D 공간에 존재하는 3가지 축의 좌표, X, Y, Z의 값 중 X, Z값을 이용해 바닥이라 부를 수 있는 평면을 만들어 냈다.
2024.06.24 - [DirectX] - Grid 그리기
Grid 그리기
1. Grid ?책에서 표현하는 xz 평면에 수많은 정점으로 이루어진 격자을 Grid라고 한다.기본도형인 삼각형으로 만든 이 평면구조는 지형과 물 렌더링에 유용하게 사용된다. 가로 width개 * 세로 height
jabberworcky.tistory.com
이때 X, Z좌표를 부여했던 코드를 보면
for (UINT y = 0; y <= height; y++)
{
for (UINT x = 0; x <= width; x++)
{
UINT i = (width + 1) * y + x;
vertices[i].Position.x = (float)x;
vertices[i].Position.y = 0.0f;
vertices[i].Position.z = (float)y;
}
}
로 구성되어 있는데 Direct3D의 세축을 보면 상하로 향하는 Y값이 0이고, 전후좌우로 향하는 X,Z에 값을 지정해 지평선처럼 보이는 바닥을 만들었다.
여기서 추측 할 수 있는 것은 Y값, 높이에 해당하는 값을 지정한다면 높이가 각각 다른 점이 튀어 오른다는 사실이다.
하지만 어떻게 수많은 점의 Y값을 하나하나 입력할 수 있을까? 임의로 랜덤값을 부여한다 해도 멋없는 지형이 나올것이다.
Y값은 그레이 스케일이란 단색 텍스쳐 파일을 하나 읽어와 색의 RGB값을 Y값으로 지정해 그럴듯한 지형을 표현해보자.
파일을 읽어와 픽셀 값을 r, g, b, a로 분해해 D3DXCOLOR값으로 저장, 추출한다.
// Texture2D_DESC 생성
D3D11_TEXTURE2D_DESC srcDesc;
src->GetDesc(&srcDesc);
// 값 설정
D3D11_TEXTURE2D_DESC desc;
ZeroMemory(&desc, sizeof(D3D11_TEXTURE2D_DESC));
desc.Width = srcDesc.Width;
desc.Height = srcDesc.Height;
desc.MipLevels = 1;
desc.ArraySize = 1;
desc.Format = readFormat;
desc.SampleDesc = srcDesc.SampleDesc;
desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
desc.Usage = D3D11_USAGE_STAGING;
// ID3D11Texture2D 인터페이스 생성
// TEXTURE2D_DESC에 텍스처를 로딩해 저장
ID3D11Texture2D* texture;
device->CreateTexture2D(&desc, NULL, &texture);
Check(D3DX11LoadTextureFromTexture(device, src, NULL, texture));
// 이미지 크기만큼 컬러값 배열 생성
UINT* colors = new UINT[desc.Width * desc.Height];
D3D11_MAPPED_SUBRESOURCE subResource;
device->Map(texture, 0, D3D11_MAP_READ, NULL, &subResource);
{
memcpy(colors, subResource.pData, sizeof(UINT) * desc.Width * desc.Height);
}
device->Unmap(texture, 0);
for (UINT y = 0; y < desc.Height; y++)
{
for (UINT x = 0; x < desc.Width; x++)
{
UINT index = desc.Width * y + x;
float f = 1.0f / 255.0f;
float r = f * (float)((0xFF000000 & colors[index]) >> 24);
float g = f * (float)((0x00FF0000 & colors[index]) >> 16);
float b = f * (float)((0x0000FF00 & colors[index]) >> 8);
float a = f * (float)((0x000000FF & colors[index]) >> 0);
pixels->push_back(D3DXCOLOR(a, b, g, r));
}
}
이렇게 추출한 픽셀 데이터의 r 값을 10진수로 정규화해 y 값에 적용한다.
for (UINT z = 0; z < height; z++)
{
for (UINT x = 0; x < width; x++)
{
UINT index = width * z + x;
UINT pixel = width * (height - 1 - z) + x;
vertices[index].Position.x = (float)x;
vertices[index].Position.y = heights[pixel].r * 255.0f / 10.0f;
vertices[index].Position.z = (float)z;
}
}
기본 도형과 점의 높이값을 지정해준 것만으로 그럴듯한 지형지물이 완성되었다.
그레이스케일은 그레이박스와 같이 레벨의 프로토타입을 만드는데 쓰이는 기법이라고 얼핏 들었던 기억이 있는데 이런식으로 높낮이만을 지정해 직접 제작하는건 신기한 경험이였다.
또 픽셀값을 가지고 어떤 작업을 한다라면 엔진에서 사용해봤던 마스킹이 떠올랐는데 Direct3D로도 경험해봤으면 좋겠다.
Mesh(1) - 원기둥, 원 (0) | 2024.07.31 |
---|---|
Terrain(2) - Normal 값을 통한 음영 (1) | 2024.07.18 |
Texture(3) - 좌표지정모드 (0) | 2024.07.11 |
Texture(2) - 필터, 확대와 축소 (1) | 2024.07.08 |
Texture(1) - UV 좌표 (0) | 2024.07.08 |