목차

     

     


     

     

    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);
    }

     


     

    실행화면