DirectX/DirectX 3D_(구)

26_Projection

컴맹학자 2021. 8. 3. 19:03
728x90

Viewport.cpp, h

더보기
#pragma once

class Viewport
{
public:
	Viewport(float width, float height, float x = 0, float y = 0, float minDepth = 0, float maxDepth = 1);
	~Viewport();

	void RSSetViewport();
	void Set(float width, float height, float x = 0, float y = 0, float minDepth = 0, float maxDepth = 1);

	float GetWidth() { return width; }
	float GetHeight() { return height; }

	Vector3 Project(const Vector3& source, Matrix& W, Matrix& V , Matrix& P);

private:
	float x, y;
	float width, height;
	float minDepth, maxDepth;

	D3D11_VIEWPORT viewport;
};

 

#include "Framework.h"
#include "Viewport.h"

Viewport::Viewport(float width, float height, float x, float y, float minDepth, float maxDepth)
{
	Set(width, height, x, y, minDepth, maxDepth);
}

Viewport::~Viewport()
{
	
}

void Viewport::RSSetViewport()
{
	D3D::GetDC()->RSSetViewports(1, &viewport);
}

void Viewport::Set(float width, float height, float x, float y, float minDepth, float maxDepth)
{
	viewport.TopLeftX = this->x = x;
	viewport.TopLeftY = this->y = y;
	viewport.Width = this->width = width;
	viewport.Height = this->height = height;
	viewport.MinDepth = this->minDepth = minDepth;
	viewport.MaxDepth = this->maxDepth = maxDepth;

	RSSetViewport();
}

Vector3 Viewport::Project(const Vector3 & source, Matrix & W, Matrix & V, Matrix & P)
{
	Vector3 position = source;
	Vector3 result;

	Matrix WVP = W * V* P;
	D3DXVec3TransformCoord(&result, &position, &WVP);

	//중요 3d -> 2d 좌표값 계산
	result.x = ((result.x + 1) * 0.5f) * width + x;
	result.y = ((-result.y + 1) * 0.5f) * height + y; //y는 내려갈수록 +이므로 반전
	result.z = (result.z * (maxDepth - minDepth)) + minDepth;


	return result;
}

ProjectDemo.cpp, h

 

더보기
#pragma once
#include "Systems/IExecute.h"

class ProjectDemo : 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:
	void CreateMesh();

private:
	Shader* shader;

	CubeSky* sky;

	Vector3 direction = Vector3(-1, -1, 1);
	ID3DX11EffectVectorVariable* sDirection;

	MeshCylinder* pointmarker;
	
	
	MeshPlane* plane;
	MeshCube* cube;

	MeshCylinder* cylinder[10];
	MeshSphere*   sphere[10];

	Shader* cubeMapShader;
	CubeMap* cubeMap;

};

 

#include "stdafx.h"
#include "ProjectDemo.h"

void ProjectDemo::Initialize()
{
	Context::Get()->GetCamera()->RotationDegree(25, 0, 0);
	Context::Get()->GetCamera()->Position(1, 36, -85);
	((Freedom*)Context::Get()->GetCamera())->Speed(50);

	shader = new Shader(L"15_Mesh.fxo");
	sky = new CubeSky(L"Environment/SnowCube1024.dds");

	CreateMesh();

	sDirection = shader->AsVector("LightDirection");

	cubeMapShader = new Shader(L"16_CubeMap.fxo");
	cubeMap = new CubeMap(cubeMapShader);
	cubeMap->Texture(L"Environment/DesertCube1024.dds");
	cubeMap->GetTransform()->Position(0, 20, 0);
	cubeMap->GetTransform()->Scale(10, 10, 10);

	pointmarker = new MeshCylinder(shader, 0.5f, 0.2f , 1.0f, 1.0f , 15);
	pointmarker->DiffuseMap(L"Red.png");
	pointmarker->GetTransform()->Position(0, 15, 0);
}

void ProjectDemo::Destroy()
{
	SafeDelete(shader);

	SafeDelete(sky);

	//SafeDelete(quad);
	SafeDelete(plane);
	SafeDelete(cube);

	for (UINT i = 0; i < 10; i++)
	{
		SafeDelete(cylinder[i]);
		SafeDelete(sphere[i]);
	}

	SafeDelete(cubeMapShader);
	SafeDelete(cubeMap);

	SafeDelete(pointmarker);


}

void ProjectDemo::Update()
{
	ImGui::SliderFloat3("LightDirection", direction, -1, +1);
	sDirection->SetFloatVector(direction);

	sky->Update();

	//Mesh Pass
	{
		static bool bWireFrame = false;
		ImGui::Checkbox("WireFrame", &bWireFrame);
		plane->Pass(bWireFrame == true ? 1 : 0);
		cube->Pass(bWireFrame == true ? 1 : 0);

		for (UINT i = 0; i < 10; i++)
		{
			cylinder[i]->Pass(bWireFrame == true ? 1 : 0);
			sphere[i]->Pass(bWireFrame == true ? 1 : 0);
		}
	}

	//pointmarker 이동
	{
		Vector3 P;
		pointmarker->GetTransform()->Position(&P);

		if (Keyboard::Get()->Press(VK_UP))
			P += Context::Get()->GetCamera()->Forward() * 20.0f * Time::Delta();
		else if (Keyboard::Get()->Press(VK_DOWN))
			P -= Context::Get()->GetCamera()->Forward() * 20.0f * Time::Delta();
		
		if (Keyboard::Get()->Press(VK_RIGHT))
			P += Context::Get()->GetCamera()->Right() * 20.0f * Time::Delta();
		if (Keyboard::Get()->Press(VK_LEFT))
			P -= Context::Get()->GetCamera()->Right() * 20.0f * Time::Delta();

		P.y = 15.0f;
		pointmarker->GetTransform()->Position(P);
	}
	
	cube->Update();
	plane->Update();
	for (UINT i = 0; i < 10; i++)
	{
		cylinder[i]->Update();
		sphere[i]->Update();
	}

	cubeMap->Update();

	pointmarker->Update();
}

void ProjectDemo::Render()
{
	sky->Render();

	//Project 테스트
	{
		Transform transform;
		transform.World(pointmarker->GetTransform()->World()); // pointmarker위치

		Vector3 temp;
		transform.Position(&temp);
		temp.y += 3;
		transform.Position(temp);

		Matrix W, V, P;
		W = transform.World();
		V = Context::Get()->View();
		P = Context::Get()->Projection();

		//3D -> 2d 좌표로
		Vector3 pPos = Context::Get()->GetViewport()->Project(Vector3(0, 0, 0), W, V, P); //카메라값
		Vector3 wPos = Vector3(transform.World()._41, transform.World()._42, transform.World()._43); //월드값

		//글자찍기
		string str = "VP : ";
		str += to_string((int)pPos.x) + " ," + to_string((int)pPos.y) + " ," + to_string((int)pPos.z) + "\n";
		str += "WP : ";
		str += to_string((int)wPos.x) + " ," + to_string((int)wPos.y) + " ," + to_string((int)wPos.z);
		Gui::Get()->RenderText(Vector2(pPos.x, pPos.y), Color(0, 1, 0, 1), str);
	}

	for (UINT i = 0; i < 10; i++)
	{
		cylinder[i]->Render();
		sphere[i]->Render();
	}

	{
		cube->Render();
		plane->Render();
		cubeMap->Render();
		pointmarker->Render();
	}


}

void ProjectDemo::CreateMesh()
{
	plane = new MeshPlane(shader, 2.5, 2.5);
	plane->GetTransform()->Scale(12, 1, 12);
	plane->DiffuseMap(L"floor.png");
	
	cube = new MeshCube(shader);
	cube->GetTransform()->Scale(20, 10, 20);
	cube->GetTransform()->Position(0, 5, 0);
	cube->DiffuseMap(L"Stones.png");

	for (UINT i = 0; i < 5; i++) 
	{
		//왼쪽
		cylinder[i * 2 + 0] = new MeshCylinder(shader, 0.3f, 0.5f, 3.0f, 20, 20);
		cylinder[i * 2 + 0]->GetTransform()->Position(-30, 6, (float)i * 15.0f - 15.0f);
		cylinder[i * 2 + 0]->GetTransform()->Scale(5, 5, 5);
		cylinder[i * 2 + 0]->DiffuseMap(L"Bricks.png");

		//오른쪽
		cylinder[i * 2 + 1] = new MeshCylinder(shader, 0.3f, 0.5f, 3.0f, 20, 20);
		cylinder[i * 2 + 1]->GetTransform()->Position(+30, 6, (float)i * 15.0f - 15.0f);
		cylinder[i * 2 + 1]->GetTransform()->Scale(5, 5, 5);
		cylinder[i * 2 + 1]->DiffuseMap(L"Bricks.png");


		//왼쪽
		sphere[i * 2 + 0] = new MeshSphere(shader,0.5f, 20, 20);
		sphere[i * 2 + 0]->GetTransform()->Position(-30, 15.5f, (float)i * 15.0f - 15.0f);
		sphere[i * 2 + 0]->GetTransform()->Scale(5, 5, 5);
		sphere[i * 2 + 0]->DiffuseMap(L"Wall.png");

		//오른쪽
		sphere[i * 2 + 1] = new MeshSphere(shader, 0.5f, 20, 20);
		sphere[i * 2 + 1]->GetTransform()->Position(+30, 15.5f, (float)i * 15.0f - 15.0f);
		sphere[i * 2 + 1]->GetTransform()->Scale(5, 5, 5);
		sphere[i * 2 + 1]->DiffuseMap(L"Wall.png");
	}

}

핵심 함수

더보기

3D 좌표계를 2D 좌표로 구하는 함수

result.x = ((result.x + 1) * 0.5f) * width + x; 
result.y = ((-result.y + 1) * 0.5f) * height + y;

  

1. 3D 좌표는 정가운데가 0,0 이고 2D 좌표에서는 왼쪽 상단이 0,0 이다

2. 2D 좌표는 UV 값처럼 0 ~ 1 표현 하기때문에 D3DXVec3TransformCoord() 함수를 통해서 위치값을 바꿔줌

3. 2번 보충으로 project 공간은 -1 ~ 1 값으로 범위 지정 하기 떄문에 +1 해서 2D 좌표계로 맞춤

4. 0.5를 곱하는 이유는 만약 result.x + 1(y도 포함) result.x에 1 이상 들어오면 0 ~ 1로 값을 떨구기 위한 보정값

5. width + x 경우는 ((result.x + 1) * 0.5f) 계산을 하고선 실제 화면 값을 곱해서 넣어줌

 

result.z = (result.z * (maxDepth - minDepth)) +minDepth; // 0 ~ 1만 가짐


보충

더보기

1. Projection : view(카메라)가 비춰지는 영역 공간

2. Projection 범위 안에 있는지 없는지 체크하기 위한 평면 방정식이 들어 있음
평면 방정식-> ax + by + cz + d = 0

3. Project을 지나면 2D 유사 좌표로 변환된다.

4. 2D에선 원근 투영이 있으면 안된다. 
 ex) 캐릭터가 거리상 따라 ID나 체력 같은게 커지거나 작아지면 안됨


실행

 

 

위에 있는 함수로 글자가 커지거나 작아지는게 아닌 pointmarker위치 위에서 일정 하게 유지 하면서 출력

VP : 카메라가 이동 하면 계속 값이 변경

WP : 실제 움직이는 월드 값 

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

28_Raycasting(AABB 충돌)  (0) 2021.08.04
27_Raycast  (0) 2021.08.03
25_Viewport  (0) 2021.08.02
24_StructuredBuffer(CS)  (0) 2021.08.02
23_TextureBuffer (CS)  (0) 2021.07.29