[DirectX11] 023 Get Height
그리드의 크기가 일정한 지형을 만들어보자.
Get Height
( V2 - V0 ) x ( x - V0.x)
ddx = (position.x - v[0].x) / 1.0f;
ddz = (position.z - v[0].z) / 1.0f;

V0 + ( V2 - V0 ) * ( x - V0.x) + ( V1 - V0 ) * ( z - V0.z)
v[0] + (v[2] - v[0]) * ddx + (v[1] - v[0]) * ddz;
V3 + ( V1 - V3 ) * ddx + ( V2 - V0) * ddz
v[3] + (v[1] - v[3]) * ddx + (v[2] - v[3]) * ddz;
- ddx + ddz < 1 인 경우, 좌측하단 삼각형 안에 위치
- ddx + ddz > 1 인 경우, 우측상단 삼각형 안에 위치
Terrain
Terrain.h
더보기
#pragma once class Terrain { public: typedef VertexNormal TerrainVertex; public: Terrain(Shader* shader, wstring heightFile); ~Terrain(); void Update(); void Render(); void Pass(UINT val) { pass = val; } float GetHeight(Vector3& position); private: void CreateVertexData(); void CreateIndexData(); void CreateNormalData(); void CreateBuffer(); private: UINT pass = 0; Shader* shader; Texture* heightMap; UINT width, height; UINT vertexCount; TerrainVertex* vertices; ID3D11Buffer* vertexBuffer; UINT indexCount; UINT* indices; ID3D11Buffer* indexBuffer; };
Terrain.cpp
더보기
#include "Framework.h" #include "Terrain.h" Terrain::Terrain(Shader * shader, wstring heightFile) : shader(shader) { heightMap = new Texture(heightFile); CreateVertexData(); CreateIndexData(); CreateNormalData(); CreateBuffer(); } Terrain::~Terrain() { SafeDelete(heightMap); SafeDeleteArray(vertices); SafeDeleteArray(indices); SafeRelease(vertexBuffer); SafeRelease(indexBuffer); } void Terrain::Update() { static Vector3 direction = Vector3(-1, -1, 1); ImGui::SliderFloat3("Direction", direction, -1, 1); shader->AsVector("Direction")->SetFloatVector(direction); Matrix world; D3DXMatrixIdentity(&world); shader->AsMatrix("World")->SetMatrix(world); shader->AsMatrix("View")->SetMatrix(Context::Get()->View()); shader->AsMatrix("Projection")->SetMatrix(Context::Get()->Projection()); } void Terrain::Render() { //for (int i = 0; i < vertexCount; i++) //{ // Vector3 start = vertices[i].Position; // Vector3 end = vertices[i].Position + vertices[i].Normal * 2; // DebugLine::Get()->RenderLine(start, end, Color(0, 1, 0, 1)); //} UINT stride = sizeof(TerrainVertex); UINT offset = 0; D3D::GetDC()->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); D3D::GetDC()->IASetVertexBuffers(0, 1, &vertexBuffer, &stride, &offset); D3D::GetDC()->IASetIndexBuffer(indexBuffer, DXGI_FORMAT_R32_UINT, 0); shader->DrawIndexed(0, pass, indexCount); } float Terrain::GetHeight(Vector3 & position) { UINT x = (UINT)position.x; UINT z = (UINT)position.z; if (x < 0 || x > width) return FLT_MIN; if (z < 0 || z > height) return FLT_MIN; UINT index[4]; index[0] = width * z + x; index[1] = width * (z + 1) + x; index[2] = width * z + x + 1; index[3] = width * (z + 1) + x + 1; Vector3 v[4]; for (int i = 0; i < 4; i++) v[i] = vertices[index[i]].Position; float ddx = (position.x - v[0].x) / 1.0f; float ddz = (position.z - v[0].z) / 1.0f; Vector3 result; if(ddx + ddz <= 1.0f) result = v[0] + (v[2] - v[0]) * ddx + (v[1] - v[0]) * ddz; else { //값을 뒤집어준다. ddx = 1.0f - ddx; ddz = 1.0f - ddz; result = v[3] + (v[1] - v[3]) * ddx + (v[2] - v[3]) * ddz; } return result.y; } void Terrain::CreateVertexData() { vector<Color> heights; heightMap->ReadPixel(DXGI_FORMAT_R8G8B8A8_UNORM, &heights); width = heightMap->GetWidth(); height = heightMap->GetHeight(); vertexCount = width * height; vertices = new TerrainVertex[vertexCount]; 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; } } } void Terrain::CreateIndexData() { indexCount = (width - 1) * (height - 1) * 6; indices = new UINT[indexCount]; UINT index = 0; for (UINT y = 0; y < height - 1; y++) { for (UINT x = 0; x < width - 1; x++) { indices[index + 0] = width * y + x; indices[index + 1] = width * (y + 1) + x; indices[index + 2] = width * y + x + 1; indices[index + 3] = width * y + x + 1; indices[index + 4] = width * (y + 1) + x; indices[index + 5] = width * (y + 1) + x + 1; index += 6; } } } void Terrain::CreateNormalData() { for (UINT i = 0; i < indexCount / 3; i++) { UINT index0 = indices[i * 3 + 0]; UINT index1 = indices[i * 3 + 1]; UINT index2 = indices[i * 3 + 2]; TerrainVertex v0 = vertices[index0]; TerrainVertex v1 = vertices[index1]; TerrainVertex v2 = vertices[index2]; Vector3 a = v1.Position - v0.Position; Vector3 b = v2.Position - v0.Position; Vector3 normal; D3DXVec3Cross(&normal, &a, &b); vertices[index0].Normal += normal; vertices[index1].Normal += normal; vertices[index2].Normal += normal; } for (UINT i = 0; i < vertexCount; i++) D3DXVec3Normalize(&vertices[i].Normal, &vertices[i].Normal); } void Terrain::CreateBuffer() { //Create Vertex Buffer { D3D11_BUFFER_DESC desc; ZeroMemory(&desc, sizeof(D3D11_BUFFER_DESC)); desc.ByteWidth = sizeof(TerrainVertex) * vertexCount; desc.BindFlags = D3D11_BIND_VERTEX_BUFFER; D3D11_SUBRESOURCE_DATA subResource = { 0 }; subResource.pSysMem = vertices; Check(D3D::GetDevice()->CreateBuffer(&desc, &subResource, &vertexBuffer)); } //Create Index Buffer { D3D11_BUFFER_DESC desc; ZeroMemory(&desc, sizeof(D3D11_BUFFER_DESC)); desc.ByteWidth = sizeof(UINT) * indexCount; desc.BindFlags = D3D11_BIND_INDEX_BUFFER; D3D11_SUBRESOURCE_DATA subResource = { 0 }; subResource.pSysMem = indices; Check(D3D::GetDevice()->CreateBuffer(&desc, &subResource, &indexBuffer)); } }
GetHeight
GetHeightDemo.h
더보기
#pragma once #include "Systems/IExecute.h" class GetHeightDemo : public IExecute { public: virtual void Initialize() override; virtual void Ready() override {} virtual void Destroy() override; virtual void Update() override; virtual void PreRender() override {} virtual void Render() override; virtual void PostRender() override {} virtual void ResizeScreen() override {} private: Shader* shader; Terrain* terrain; Vector3 position = Vector3(0, 0, 0); Shader* triShader; ID3D11Buffer* vertexBuffer; };
GetHeightDemo.cpp
더보기
#include "stdafx.h" #include "GetHeightDemo.h" void GetHeightDemo::Initialize() { Context::Get()->GetCamera()->RotationDegree(12, 0, 0); Context::Get()->GetCamera()->Position(35, 10, -55); ((Freedom *)Context::Get()->GetCamera())->Speed(20); shader = new Shader(L"19_Terrain.fx"); terrain = new Terrain(shader, L"Terrain/Gray256.png"); terrain->Pass(1); triShader = new Shader(L"09_World.fx"); Vertex vertices[3]; vertices[0].Position = Vector3(+0, +1, 0); vertices[1].Position = Vector3(-1, +0, 0); vertices[2].Position = Vector3(+1, +0, 0); //Create Vertex Buffer { D3D11_BUFFER_DESC desc; ZeroMemory(&desc, sizeof(D3D11_BUFFER_DESC)); desc.ByteWidth = sizeof(Vertex) * 3; desc.BindFlags = D3D11_BIND_VERTEX_BUFFER; D3D11_SUBRESOURCE_DATA subResource = { 0 }; subResource.pSysMem = vertices; Check(D3D::GetDevice()->CreateBuffer(&desc, &subResource, &vertexBuffer)); } } void GetHeightDemo::Destroy() { SafeDelete(shader); SafeDelete(terrain); SafeDelete(triShader); SafeRelease(vertexBuffer); } void GetHeightDemo::Update() { terrain->Update(); if (Keyboard::Get()->Press(VK_RIGHT)) position.x += 20.0f * Time::Delta(); else if (Keyboard::Get()->Press(VK_LEFT)) position.x -= 20.0f * Time::Delta(); if (Keyboard::Get()->Press(VK_UP)) position.z += 20.0f * Time::Delta(); else if (Keyboard::Get()->Press(VK_DOWN)) position.z -= 20.0f * Time::Delta(); //float Terrain::GetHeight()에서 return result.y값을 가져다쓴다. //기준점인 vertices[0].Position = Vector3(0, 1, 0). 기준점 y값이 1이므로 1.0f를 더해준다. position.y = terrain->GetHeight(position) + 1.0f; Matrix R, T; D3DXMatrixRotationX(&R, Math::ToRadian(180)); D3DXMatrixTranslation(&T, position.x, position.y, position.z); Matrix world = R * T; triShader->AsMatrix("World")->SetMatrix(world); triShader->AsMatrix("View")->SetMatrix(Context::Get()->View()); triShader->AsMatrix("Projection")->SetMatrix(Context::Get()->Projection()); } void GetHeightDemo::Render() { terrain->Render(); UINT stride = sizeof(Vertex); UINT offset = 0; D3D::GetDC()->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); D3D::GetDC()->IASetVertexBuffers(0, 1, &vertexBuffer, &stride, &offset); triShader->Draw(0, 0, 3); string str = to_string(position.x) + ", " + to_string(position.y) + ", " + to_string(position.z); Gui::Get()->RenderText(5, 60, str); }
실행화면

'⭐ DirectX > DirectX11 3D' 카테고리의 다른 글
[DirectX11] 025~26 Mesh (0) | 2023.01.21 |
---|---|
[DirectX11] 024 Vertical Raycast (0) | 2023.01.20 |
[DirectX11] 020~22 Normal Vector (0) | 2023.01.18 |
[DirectX11] 019 Heightmap (0) | 2023.01.16 |
[DirectX11] 018 Texture Sampler (0) | 2023.01.16 |
댓글
이 글 공유하기
다른 글
-
[DirectX11] 025~26 Mesh
[DirectX11] 025~26 Mesh
2023.01.21 -
[DirectX11] 024 Vertical Raycast
[DirectX11] 024 Vertical Raycast
2023.01.20 -
[DirectX11] 020~22 Normal Vector
[DirectX11] 020~22 Normal Vector
2023.01.18 -
[DirectX11] 019 Heightmap
[DirectX11] 019 Heightmap
2023.01.16
댓글을 사용할 수 없습니다.