[DirectX11] 067 Projection
목차
Projection
IA -> VS -> RS -> PS -> OM
VS (World, View, Projection 조정)
RS (vp)
NDC 공간
z(깊이)는 0~1인 이유는? (카메라) 뒤쪽은 없다. 고로 음수는 쓸 일이 없다.
- Perspective 원근 투영: 가까울수록 크고, 멀수록 작다.
- Orthographic 직교 투영:
Projection 과정 = 3D 정점 → W, V, P → 2D
Unprojection 과정 = 2D → W, V, P → 3D 정점
Picking이란?
- 마우스 클릭 위치에서 far위치로부터의 거리를 활용하여 Unprojection
Shader | |
Framework | |
Viewer | |
Viewport.h .cpp | |
UnitTest | |
Projection | |
ProjectionDemo.h .cpp | |
Main.h .cpp |
Viewport
Viewport.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; }
//최종적으로 변환된 위치
void Project(Vector3* pOut, Vector3& source, Matrix& W, Matrix& V, Matrix& P);
private:
float x, y;
float width, height;
float minDepth, maxDepth;
D3D11_VIEWPORT viewport;
};
Viewport.cpp
더보기
#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();
}
void Viewport::Project(Vector3 * pOut, Vector3 & source, Matrix & W, Matrix & V, Matrix & P)
{
Vector3 position = source; //받은 위치 저장
Matrix wvp = W * V * P;
//position을 wvp공간변환하여 pOut에 대입. // pOut(Vector3), &position(Vector3), &wvp(Matrix)
D3DXVec3TransformCoord(pOut, &position, &wvp); //&position x &wvp = pOut
//x,y는 시작위치, z는 깊이, z는 projection의 비율을 만드는 식 사용.
pOut->x = ((pOut->x + 1.0f) * 0.5f) * width + x;
pOut->y = ((-pOut->y + 1.0f) * 0.5f) * height + y;
pOut->z = (pOut->z * (maxDepth - minDepth)) + minDepth;
}
Projection Demo
ProjectionDemo.h
더보기
#pragma once
#include "Systems/IExecute.h"
class ProjectionDemo : 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:
void Mesh();
void Airplane();
void Kachujin();
void KachujinCollider();
void Pass(UINT mesh, UINT model, UINT anim);
private:
Shader* shader;
CubeSky* sky;
Material* floor;
Material* stone;
Material* brick;
Material* wall;
MeshRender* cube;
MeshRender* cylinder;
MeshRender* sphere;
MeshRender* grid;
ModelRender* airplane = NULL;
ModelAnimator* kachujin = NULL;
ColliderObject** colliders;
vector<MeshRender *> meshes;
vector<ModelRender *> models;
vector<ModelAnimator *> animators;
};
ProjectionDemo.cpp
더보기
#include "stdafx.h"
#include "ProjectionDemo.h"
void ProjectionDemo::Initialize()
{
Context::Get()->GetCamera()->RotationDegree(20, 0, 0);
Context::Get()->GetCamera()->Position(1, 36, -85);
shader = new Shader(L"55_Render.fx");
sky = new CubeSky(L"Environment/GrassCube1024.dds");
Mesh();
Airplane();
Kachujin();
KachujinCollider();
}
void ProjectionDemo::Update()
{
Vector3 position;
airplane->GetTransform(0)->Position(&position);
position.x -= 5;
position.z = 0.0f;
Vector3 position2D; //변환할 2D 위치 선언
Matrix W, V, P;
D3DXMatrixIdentity(&W);
V = Context::Get()->View();
P = Context::Get()->Projection();
Context::Get()->GetViewport()->Project(&position2D, position, W, V, P);//2D 위치로 변환
Gui::Get()->RenderText(position2D.x, position2D.y, 1, 0, 0, "Airplane");
sky->Update();
cube->Update();
grid->Update();
cylinder->Update();
sphere->Update();
airplane->Update();
kachujin->Update();
for (UINT i = 0; i < kachujin->GetTransformCount(); i++)
{
Matrix attach;
kachujin->GetAttachTransform(i, &attach);
position = Vector3(0, 0, 0);
Context::Get()->GetViewport()->Project(&position2D, position, attach, V, P);
Gui::Get()->RenderText(position2D.x, position2D.y, 1, 1, 1, "Hand");
colliders[i]->Collider->GetTransform()->World(attach);
colliders[i]->Collider->Update();
}
}
void ProjectionDemo::Render()
{
static float width = D3D::Width();
static float height = D3D::Height();
static float x = 0.0f;
static float y = 0.0f;
ImGui::InputFloat("Width", &width, 1.0f);
ImGui::InputFloat("Height", &height, 1.0f);
ImGui::InputFloat("X", &x, 1.0f);
ImGui::InputFloat("Y", &y, 1.0f);
Context::Get()->GetViewport()->Set(width, height, x, y);
static float fov = 0.25f;
ImGui::InputFloat("Fov", &fov, 0.001f);
static float minZ = 0.1f, maxZ = 1000.0f;
ImGui::InputFloat("MinZ", &minZ, 1.0f);
ImGui::InputFloat("MaxZ", &maxZ, 1.0f);
Perspective* perspective = Context::Get()->GetPerspective();
perspective->Set(D3D::Width(), D3D::Height(), minZ, maxZ, Math::PI * fov);
sky->Render();
Pass(0, 1, 2);
wall->Render();
sphere->Render();
brick->Render();
cylinder->Render();
stone->Render();
cube->Render();
floor->Render();
grid->Render();
airplane->Render();
kachujin->Render();
for (UINT i = 0; i < kachujin->GetTransformCount(); i++)
colliders[i]->Collider->Render();
}
void ProjectionDemo::Mesh()
{
//Create Material
{
floor = new Material(shader);
floor->DiffuseMap("Floor.png");
//floor->SpecularMap("Floor_Specular.png");
//floor->NormalMap("Floor_Normal.png");
//floor->Specular(1, 1, 1, 20);
stone = new Material(shader);
stone->DiffuseMap("Stones.png");
//stone->SpecularMap("Stones_Specular.png");
//stone->NormalMap("Stones_Normal.png");
//stone->Specular(1, 1, 1, 20);
brick = new Material(shader);
brick->DiffuseMap("Bricks.png");
//brick->SpecularMap("Bricks_Specular.png");
//brick->NormalMap("Bricks_Normal.png");
//brick->Specular(1, 0.3f, 0.3f, 20);
wall = new Material(shader);
wall->DiffuseMap("Wall.png");
//wall->SpecularMap("Wall_Specular.png");
//wall->NormalMap("Wall_Normal.png");
//wall->Specular(1, 1, 1, 20);
}
//Create Mesh
{
Transform* transform = NULL;
cube = new MeshRender(shader, new MeshCube());
transform = cube->AddTransform();
transform->Position(0, 5, 0);
transform->Scale(20, 10, 20);
grid = new MeshRender(shader, new MeshGrid(5, 5));
transform = grid->AddTransform();
transform->Position(0, 0, 0);
transform->Scale(12, 1, 12);
cylinder = new MeshRender(shader, new MeshCylinder(0.5f, 3.0f, 20, 20));
sphere = new MeshRender(shader, new MeshSphere(0.5f, 20, 20));
for (UINT i = 0; i < 5; i++)
{
transform = cylinder->AddTransform();
transform->Position(-30, 6, -15.0f + (float)i * 15.0f);
transform->Scale(5, 5, 5);
transform = cylinder->AddTransform();
transform->Position(30, 6, -15.0f + (float)i * 15.0f);
transform->Scale(5, 5, 5);
transform = sphere->AddTransform();
transform->Position(-30, 15.5f, -15.0f + (float)i * 15.0f);
transform->Scale(5, 5, 5);
transform = sphere->AddTransform();
transform->Position(30, 15.5f, -15.0f + (float)i * 15.0f);
transform->Scale(5, 5, 5);
}
}
sphere->UpdateTransforms();
cylinder->UpdateTransforms();
cube->UpdateTransforms();
grid->UpdateTransforms();
meshes.push_back(sphere);
meshes.push_back(cylinder);
meshes.push_back(cube);
meshes.push_back(grid);
}
void ProjectionDemo::Airplane()
{
airplane = new ModelRender(shader);
airplane->ReadMesh(L"B787/Airplane");
airplane->ReadMaterial(L"B787/Airplane");
Transform* transform = airplane->AddTransform();
transform->Position(2.0f, 9.91f, 2.0f);
transform->Scale(0.004f, 0.004f, 0.004f);
airplane->UpdateTransforms();
models.push_back(airplane);
}
void ProjectionDemo::Kachujin()
{
kachujin = new ModelAnimator(shader);
kachujin->ReadMesh(L"Kachujin/Mesh");
kachujin->ReadMaterial(L"Kachujin/Mesh");
kachujin->ReadClip(L"Kachujin/Sword And Shield Idle");
kachujin->ReadClip(L"Kachujin/Sword And Shield Walk");
kachujin->ReadClip(L"Kachujin/Sword And Shield Run");
kachujin->ReadClip(L"Kachujin/Sword And Shield Slash");
kachujin->ReadClip(L"Kachujin/Salsa Dancing");
Transform* transform = NULL;
transform = kachujin->AddTransform();
transform->Position(0, 0, -30);
transform->Scale(0.075f, 0.075f, 0.075f);
kachujin->PlayTweenMode(0, 0, 1.0f);
transform = kachujin->AddTransform();
transform->Position(-15, 0, -30);
transform->Scale(0.075f, 0.075f, 0.075f);
kachujin->PlayTweenMode(1, 1, 1.0f);
transform = kachujin->AddTransform();
transform->Position(-30, 0, -30);
transform->Scale(0.075f, 0.075f, 0.075f);
kachujin->PlayTweenMode(2, 2, 0.75f);
transform = kachujin->AddTransform();
transform->Position(15, 0, -30);
transform->Scale(0.075f, 0.075f, 0.075f);
kachujin->PlayBlendMode(3, 0, 1, 2);
kachujin->SetBlendAlpha(3, 1.5f);
transform = kachujin->AddTransform();
transform->Position(30, 0, -32.5f);
transform->Scale(0.075f, 0.075f, 0.075f);
kachujin->PlayTweenMode(4, 4, 0.75f);
kachujin->UpdateTransforms();
kachujin->SetAttachTransform(40);
animators.push_back(kachujin);
}
void ProjectionDemo::KachujinCollider()
{
UINT count = kachujin->GetTransformCount();
colliders = new ColliderObject*[count];
for (UINT i = 0; i < count; i++)
{
colliders[i] = new ColliderObject();
colliders[i]->Init = new Transform();
colliders[i]->Init->Position(0, 0, 0);
colliders[i]->Init->Scale(10, 30, 10);
colliders[i]->Transform = new Transform();
colliders[i]->Collider = new Collider(colliders[i]->Transform, colliders[i]->Init);
}
}
void ProjectionDemo::Pass(UINT mesh, UINT model, UINT anim)
{
for (MeshRender* temp : meshes)
temp->Pass(mesh);
for (ModelRender* temp : models)
temp->Pass(model);
for (ModelAnimator* temp : animators)
temp->Pass(anim);
}
실행화면
'⭐ DirectX > DirectX11 3D' 카테고리의 다른 글
[DirectX11] 069 Collider (0) | 2023.03.13 |
---|---|
[DirectX11] 068 Unprojection - 2D 좌표를 3D 좌표로 변환 (0) | 2023.03.13 |
[DirectX11] 066 3D 공간에서 충돌체 선택하기 (0) | 2023.03.08 |
[DirectX11] 064~65 Bone 위치에 충돌체 삽입하기 (0) | 2023.03.06 |
[DirectX11] 063 Compute Shader - GetAnimationBone 구현하기 (0) | 2023.03.06 |
댓글
이 글 공유하기
다른 글
-
[DirectX11] 069 Collider
[DirectX11] 069 Collider
2023.03.13 -
[DirectX11] 068 Unprojection - 2D 좌표를 3D 좌표로 변환
[DirectX11] 068 Unprojection - 2D 좌표를 3D 좌표로 변환
2023.03.13 -
[DirectX11] 066 3D 공간에서 충돌체 선택하기
[DirectX11] 066 3D 공간에서 충돌체 선택하기
2023.03.08 -
[DirectX11] 064~65 Bone 위치에 충돌체 삽입하기
[DirectX11] 064~65 Bone 위치에 충돌체 삽입하기
2023.03.06