DirectX/DirectX 3D_(구)

11_Terrain

컴맹학자 2021. 7. 2. 22:56
728x90

Terrain.cpp, h

더보기
#include "Framework.h"
#include "Terrain.h"

Terrain::Terrain(Shader * shader, wstring heightFile)
	:shader(shader)
{
	hightMap = new Texture(heightFile);
	
	CreateVertexData();
	CreateIndexData();
	CreateBuffer();

	D3DXMatrixIdentity(&world);
}

Terrain::~Terrain()
{
	SafeDeleteArray(vertices);
	SafeRelease(vertexBuffer);

	SafeDeleteArray(indices);
	SafeRelease(indexBuffer);

	SafeDelete(hightMap);
}

void Terrain::Update()
{
	shader->AsMatrix("World")->SetMatrix(world);
	shader->AsMatrix("View")->SetMatrix(Context::Get()->View());
	shader->AsMatrix("Projection")->SetMatrix(Context::Get()->Projection());

}

void Terrain::Render()
{
	UINT stride = sizeof(VertexTerrain);
	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);
}

void Terrain::CreateVertexData()
{
	//hightMap의 가로 세로 크기
	width = hightMap->GetWidth();
	height = hightMap->GetHeight();

	//픽셀 정보 가져오기
	vector<Color> pixels;
	hightMap->ReadPixel(&pixels);

	//생성
	vertexCount = width * height;
	vertices = new VertexTerrain[vertexCount];
	for (UINT z = 0; z < height; z++)
	{
		for (UINT x = 0; x < width; x++)
		{
			UINT index = width  * z + x;

			//World 좌표계랑 UV 좌표계는 다르기 떄문에 반전 시켜야함
			UINT pixel = width * (height - z - 1 ) + x;

			vertices[index].Position.x = (float)x;
			vertices[index].Position.y = pixels[pixel].r * (255.0f / 10);
			vertices[index].Position.z = (float)z;
		}
	}
}

void Terrain::CreateIndexData()
{
	//Set Index Subresource
	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::CreateBuffer()
{
	//Create VertexBuffer
	{
		D3D11_BUFFER_DESC desc;
		ZeroMemory(&desc, sizeof(D3D11_BUFFER_DESC));
		desc.ByteWidth = sizeof(VertexTerrain) * vertexCount;
		desc.BindFlags = D3D11_BIND_VERTEX_BUFFER;

		D3D11_SUBRESOURCE_DATA data = { 0 };
		data.pSysMem = vertices;

		Check(D3D::GetDevice()->CreateBuffer(&desc, &data, &vertexBuffer));
	}

	//Create IndexBuffer
	{
		D3D11_BUFFER_DESC desc;
		ZeroMemory(&desc, sizeof(D3D11_BUFFER_DESC));
		desc.ByteWidth = sizeof(UINT) * indexCount;
		desc.BindFlags = D3D11_BIND_INDEX_BUFFER;

		D3D11_SUBRESOURCE_DATA data = { 0 };
		data.pSysMem = indices;

		Check(D3D::GetDevice()->CreateBuffer(&desc, &data, &indexBuffer));
	}
}
#pragma once
class Terrain
{
public:
	Terrain(Shader* shader, wstring heightFile);
	~Terrain();

	void Update();
	void Render();
	UINT& Pass() { return pass; }

private:
	void CreateVertexData();
	void CreateIndexData();
	void CreateBuffer();


private:
	struct VertexTerrain
	{
		Vector3 Position;
	};

private:
	Shader* shader;
	UINT pass = 0;

	UINT width, height;

	UINT vertexCount;
	VertexTerrain* vertices;
	ID3D11Buffer* vertexBuffer;

	UINT indexCount;
	UINT* indices;
	ID3D11Buffer* indexBuffer;

	Matrix world;

	//높이맵
	Texture* hightMap;
};

TerrainDemo.cpp, h

더보기
#include "stdafx.h"
#include "TerrainDemo.h"

void TerrainDemo::Initialize()
{
	Context::Get()->GetCamera()->RotationDegree(6, 0, 0);
	Context::Get()->GetCamera()->Position(110, 50, 0);
	((Freedom*)Context::Get()->GetCamera())->Speed(50);

	shader = new Shader(L"11_Terrain.fxo");
	terrain = new Terrain(shader, L"HightMap256.png");
}

void TerrainDemo::Destroy()
{
	SafeDelete(shader);
	SafeDelete(terrain);
}

void TerrainDemo::Update()
{
	//쉐이더에 등록한 Pass 갯수 반환
	static UINT Pass = shader->PassCount() - 1;
	ImGui::InputInt("Pass", (int*)&Pass);
	Pass %= 2;

	terrain->Pass() = Pass;
	terrain->Update();
}

void TerrainDemo::Render()
{
	terrain->Render();

}


#pragma once
#include "Systems/IExecute.h"

class TerrainDemo : public IExecute
{
public:
	virtual void Initialize() 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:
	struct Vertex
	{
		Vector3 Position;
		Vector2 Uv;
	};


private:
	Shader* shader;

	Terrain* terrain;
};


11_Terrain.fx

더보기
matrix World, View, Projection;

struct VertexInput
{
    float4 Position : Position;
};

struct VertexOutput
{
    float4 Position : SV_Position;
};

RasterizerState RS
{
    FillMode = WireFrame;
};

VertexOutput VS(VertexInput input)
{
    VertexOutput output;
    output.Position = mul(input.Position, World);
    output.Position = mul(output.Position, View);
    output.Position = mul(output.Position, Projection);

    return output;
}

float4 PS(VertexOutput input) : SV_Target
{
    return float4(1, 1, 0, 1);
}

technique11 T0
{
    pass P0
    {
        SetVertexShader(CompileShader(vs_5_0, VS()));
        SetPixelShader(CompileShader(ps_5_0, PS()));
    }

    pass P1
    {
        SetRasterizerState(RS);

        SetVertexShader(CompileShader(vs_5_0, VS()));
        SetPixelShader(CompileShader(ps_5_0, PS()));
    }

}

실행

 


지금부터 진짜로 3D 내용의 시작이라고 볼 수 있음

 

Diffusemap은 기본 색상 이라서 높이 관련은 따로  Hightmap을 사용을 해서 지형을 만듬

지형의 크기는 Hightmap정보를 받아서 사용하기 때문에 Index 에서 가로 세로 -1 해줘야함

 

Environment안에 이제부터 지형, 날씨, 구름...등을 작성을 하면 UnitTest에서 사용하기 때문에

즉 한번 선언하면 왠만하면 수정을 안하기 때문에 Framework에다 만들어서 사용

 

'DirectX > DirectX 3D_(구)' 카테고리의 다른 글

13_BaseMap  (0) 2021.07.04
12_Normal [1/2]  (0) 2021.07.03
10_Sampler  (0) 2021.07.02
09_Texture  (0) 2021.06.30
08_Cube  (0) 2021.06.30