응애맘마조

221130 강의 본문

공부/2D강의

221130 강의

TH.Wert 2022. 12. 1. 00:57

오늘 강의를 작성하기 전에 오타 난 부분을 알려드리겠습니다.

//VertexBuffer.h

count = vertices.size();
//Rect.h

vector<UINT> indices;

Matrix world;
Matrix S, R, T;

VertexBuffer.h 파일의 코드에 오타가 있었습니다. (해당 일자의 내용에서는 수정했습니다.)
Rect.h 파일에서 vector 부분과 Matrix를 D3DMATRIX라고 잘못 쓴 부분이 있었습니다. (해당 일자의 내용에서는 수정했습니다.)

거의 스크린 창에 띄우기까지 다 왔습니다. Unitest 솔루션에도 많은 작성이 있었습니다. 오늘 내용을 정리하겠습니다.

//VertexColor.hlsl

struct VetrtexInput
{
	float4 position : POSITION0;
	float4 color : COLOR0;
};

struct PixelInput
{
	float4 position : SV_POSITION0;
	float4 color : COLOR0;
};

cbuffer WorldBuffer : register(b0)
{
	matrix _world;
}

cbuffer VPBuffer : register(b1)
{
	matrix _view;
	matrix _projection;
}

PixelInput VS(VertexInput input)
{
	PixelInput output;

	output.position = mul(input.position, _world);
	output.position = mul(output.position, _view);
	output.position = mul(output.position, _projection);

	output.color = input.color;
	return output;
}

float4 PS(PixelInput input) : SV_Target
{
	return input.color;
}

먼저 VertexColor.hlsl파일입니다.
SV_POSITION0는 SV를 검색합니다.
cbuffer는 constBuffer의 약자로 상수 버퍼입니다.
register는 0에서 127까지 있고 b가 붙은 건 슬롯 번호처럼 생각하면 됩니다.

//Framework.h

#pragma once

#include <Windows.h>
#include <iostream>
#include <time.h>
#include <stdlib.h>
#include <string>
#include <vector>
#include <unordered_map>
#include <assert.h>

using namespace std;

//순서 중요
//DirectX
#include <d3dcompiler.h>
#include <d3d11.h>
#include <D3DX10math.h>
#include <D3DX11async.h>

#pragma comment(lib, "dxgi.lib")
#pragma comment(lib, "d3d11.lib")
#pragma comment(lib, "d3dx11.lib")
#pragma comment(lib, "d3dx10.lib")
#pragma comment(lib, "d3dcompiler.lib")
/*---------------------------------------------------*/
//ImGui
#include "ImGui/imgui.h"
#include "ImGui/imgui_internal.h"
#include "ImGui/imgui_impl_dx11.h"
#include "ImGui/imgui_impl_win32.h"
#pragma comment(lib, "ImGui/ImGui.lib")
/*---------------------------------------------------*/
//typedef
typedef D3DXVECTOR3 Vector3;
typedef D3DXVECTOR2 Vector2;
typedef D3DXMATRIX Matrix;
typedef D3DXCOLOR Color;
typedef UINT uint;
/*---------------------------------------------------*/
//Framework
#include "Interface/IObject.h"

#include "Systems/Window.h"

#include "Utilities/SingletonBase.h"

#include "Systems/Graphics.h"
#include "Systems/Keyboard.h"
#include "Systems/Mouse.h"
#include "Systems/Timer.h"

#include "Utilities/Gui.h"
/*---------------------------------------------------*/
//define
#define DEVICE Graphics::Get()->GetDevice()
#define DC Graphics::Get()->GetDC()
#define CHECK(p) assert(SUCCEEDED(p))
#define SAFE_DELETE(p) { if(p) {delete(p); (p) = nullptr;} }
#define SAFE_DELETE_ARRAY(p) { if(p) {delete[](p); (p) = nullptr;} }
#define SAFE_RELEASE(p) { if(p) {(p)->Release(); (p) = nullptr;} }

#define WinMaxWidth 1280
#define WinMaxHeight 720
/*---------------------------------------------------*/
//include
#include "Renders/Resources/VertexTypes.h"
#include "Renders/Resources/ShaderBuffer.h"
#include "Renders/Resources/GlobalBuffer.h"

#include "Renders/IA/VertexBuffer.h"
#include "Renders/IA/IndexBuffer.h"
#include "Renders/IA/InputLayout.h"

#include "Renders/Shaders/VertexShader.h"
#include "Renders/Shaders/PixelShader.h"
/*---------------------------------------------------*/
//Variable
extern HWND handle;
const wstring ShaderPath = L"../_Shaders/";

수정된 Framework.h입니다. typedef와 Framework 순서가 바뀌었고 마지막 줄에
const wstring ShaderPath = L"../_Shaders/" 코드가 추가되었습니다.

//Rect.cpp

#include "Framework.h"
#include "Rect.h"

Rect::Rect(Vector3 position, Vector3 size, float rotation)
    :position(position), size(size),rotation(rotation)

{
    //Vertices
    {
        vertices.assign(4, VertexColor());

        vertices[0].position = Vector3(-0.5f, -0.5f, 0.0f);
        vertices[0].color = Color(1, 0, 0, 1);

        vertices[1].position = Vector3(0.5f, 0.5f, 0.0f);
        vertices[1].color = Color(1, 0, 0, 1);

        vertices[2].position = Vector3(0.5f, -0.5f, 0.0f);
        vertices[2].color = Color(1, 0, 0, 1);

        vertices[3].position = Vector3(-0.5f, 0.5f, 0.0f);
        vertices[3].color = Color(1, 0, 0, 1);
    }

    //VertexBuffer
    {
        vb = new VertexBuffer();
        vb->Create(vertices, D3D11_USAGE_DYNAMIC);
    }

    //indexBuffer
    {
        indices = { 0, 1, 2, 0, 3, 1 };

        ib = new IndexBuffer();
        ib->Create(indices, D3D11_USAGE_IMMUTABLE);
    }

    //VertexShader
    {
        vs = new VertexShader();
        vs->Create(ShaderPath + L"VertexColor.hlsl", "VS");
    }

    //InputLayout
    {
        il = new InputLayout();
        il->Create(VertexColor::descs, VertexColor::count, vs->GetBlob());
    }

    //PixelShader
    {
        ps = new PixelShader();
        ps->Create(ShaderPath + L"VertexColor.hlsl", "VS");
    }

    //world
    {
        wb = new WorldBuffer();
    }

}

Rect::~Rect()
{
    SAFE_DELETE(wb);

    SAFE_DELETE(il);

    SAFE_DELETE(vs);
    SAFE_DELETE(ps);

    SAFE_DELETE(ib);
    SAFE_DELETE(vb);
}

void Rect::Update()
{
    D3DXMatrixTranslation(&T, position.x, position.y, position.z);
    D3DXMatrixScaling(&S, size.x, size.y, size.z);
    D3DXMatrixRotationZ(&R, rotation);

    world = S * R * T;
    wb->SetWorld(world);
}

void Rect::Render()
{
    vb->SetIA();
    ib->SetIA();
    il->SetIA();
    DC->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);

    vs->SetShader();
    wb->SetVSBuffer(0);

    ps->SetShader();

    DC->DrawIndexed(ib->GetCount(), 0, 0);
}

void Rect::GUI()
{
    ImGui::InputFloat3(MakeLabel("Pos").c_str(), position, 2);
    ImGui::InputFloat3(MakeLabel("Size").c_str(), size, 2);
    ImGui::InputFloat3(MakeLabel("Rot").c_str(), &rotation, 2);
    if (ImGui::ColorPicker4("Color", color));
        UpdateColor();

}

void Rect::UpdateColor()
{
    D3D11_MAPPED_SUBRESOURCE subResource;
    DC->Map(vb->GetResource(), 0, D3D11_MAP_WRITE_DISCARD, 0, &subResource);
    {
        for (VertexColor& v : vertices)
            v.color = color;

        memcpy(subResource.pData, vertices.data(), vb->GetCount() * vb->GetStride());
    }
    DC->Unmap(vb->GetResource(), 0);
}

string Rect::MakeLabel(string preFix)
{
    string label = preFix + "##" + to_string((UINT)this);
    return label;
}

Rect.cpp입니다. 어제는 시간상 작성하지 못했습니다.
indices = { 0, 1, 2, 0, 3, 1 }은 삼각형을 2개 그려서 사각형 만들기 위해 정점을 잡은 부분입니다.
소멸자 Rect(~Rect)를 보면 역순으로 메모리 해제를 했는데 안전성을 위해서 역순으로 해제를 했습니다.
D3DXMatrixRotationZ(&R, rotation)은 Z축으로 회전하기 때문에 작성했습니다. (X, Y는 3D에서 합니다.)
D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST는 정점을 그려주는 방식입니다.

정점의 순서대로 그려지게 됩니다. (출처 : https://www.asawicki.info/news_1524_how_to_flip_triangles_in_triangle_mesh)

//Windows.h

struct DXDesc
Window(DXDesc desc);
WPARAM Run(IObject* mainObj);
static DXDesc desc;

//Windows.cpp

DXDesc Window::desc;
Window::Window(DXDesc desc)
WPARAM Window::Run(IObject* mainObj)

Windows 클래스에서 Win을 DX로 바꾸면서 변경된 부분의 코드를 따로 올렸습니다.

Framework 솔루션은 여기까지입니다. 이후에는 Unitest 솔루션입니다.

//stdafx.h

#pragma once

#include "Framework.h"
#pragma comment(lib, "Framework.lib")

stdafx.h입니다. Framework에 있던 솔루션을 가져왔습니다.( 그냥 코드만 적으면 안 돼서 VC++ 디렉터리에서 따로 설정을 했습니다.)

//Program.h

#pragma once

#include "stdafx.h"
#include "Demos/RectDemo.h"

class Program : public IObject
{
private:
	virtual void Init() override;
	virtual void Destroy() override;
	virtual void Update() override;
	virtual void Render() override;
	virtual void PostRender() override;
	virtual void GUI() override;

private:
	void Push(IObject* obj);

	VPBuffer* vpb = nullptr;
	Matrix view, proj;

	vector<IObject*> objs;
};

Program.h입니다. (#include "Demos/RectDemo.h"는 하단에 작성하겠습니다.) 코드에 대한 설명은 없었습니다.

//Program.cpp

#include "Program.h"

void Program::Init()
{
	vpb = new VPBuffer();
	D3DXMatrixLookAtLH(&view, &Vector3(0, 0, 0), &Vector3(0, 0, 1), &Vector3(0, 1, 0));
	D3DXMatrixOrthoOffCenterLH(&proj, 0.0f, (float)WinMaxWidth, 0.0f, (float)WinMaxHeight, 0, 1);
	vpb->SetView(view);
	vpb->Setproj(proj);

	Push(new RectDemo);
}

void Program::Destroy()
{
	SAFE_DELETE(vpb);
	for (IObject* obj : objs)
	{
		obj->Destroy();
		SAFE_DELETE(obj);
	}
}

void Program::Update()
{
	for (IObject* obj : objs)
	{
		obj->Update();
	}
}

void Program::Render()
{
	vpb->SetVSBuffer(1);
	for (IObject* obj : objs)
	{
		obj->Render();
	}
}

void Program::PostRender()
{
	for (IObject* obj : objs)
	{
		obj->PostRender();
	}
}

void Program::GUI()
{
	for (IObject* obj : objs)
	{
		obj->GUI();
	}
}

void Program::Push(IObject* obj)
{
	objs.push_back(obj);
	obj->Init();
}

int WINAPI WinMain(HINSTANCE instance, HINSTANCE prevInstance, LPSTR param, int command)
{
	srand((UINT)time(NULL));

	DXDesc desc;
	desc.AppName = L"D2DGame";
	desc.instance = instance;
	desc.handle = NULL;
	desc.width = WinMaxWidth;
	desc.height = WinMaxHeight;

	Program* program = new Program();
	Window* window = new Window(desc);
	WPARAM wParam = window->Run(program);
	SAFE_DELETE(window);
	SAFE_DELETE(program);

	return wParam;

}

Program.cpp입니다. D3DXMatrixLookAtLH, D3DXMatrixOrthoOffCenterLH에서 오류가 나지만 내일 해결한다고 하셨습니다. 코드에 대한 설명은 없었습니다.

//Imgui.ini

[Window][Debug##Default]
Pos=60,60
Size=400,400
Collapsed=0

[Window][FPS]
Pos=1180,15
Size=200,32
Collapsed=0

[Window][MousePose]
Pos=1180,30
Size=200,60
Collapsed=0

[Window][Vstnc]
Pos=0,15
Size=200,32
Collapsed=0

[Window][ImGui Demo]
Pos=683,64
Size=357,252
Collapsed=0

[Window][Rects]
Pos=671,111
Size=371,437
Collapsed=0

[Docking][Data]

Imgui.ini입니다. 전에 만들었던 ImGui를 출력하기 위해 만들었습니다. (폴더 내의 txt 파일로 확인 가능합니다.)

//RectDemo.h

#pragma once

#include "stdafx.h"
#include "Geometries/Rect.h"

class RectDemo : public IObject
{
public:
	virtual void Init() override;
	virtual void Destroy() override;
	virtual void Update() override;
	virtual void Render() override;
	virtual void PostRender() override;
	virtual void GUI() override;

private:
	vector<class Rect*> rects;
};

RectDemo.h입니다. RectDemo에서 사각형을 출력할 건데 아직 오류가 잡히지 않아서 출력이 되지 않았습니다.
코드에 대한 설명은 없었습니다.

//RectDemo.cpp

#include "RectDemo.h"

void RectDemo::Init() {}

void RectDemo::Destroy()
{
	for (Rect* r : rects)
		SAFE_DELETE(r);
}

void RectDemo::Update()
{
	if (Mouse::Get()->Down(0))
		rects.push_back(new Rect(Mouse::Get()->GetPosition(), Vector3(100, 100, 1), 0.0f));
	for (Rect* r : rects)
		r->Update();
}

void RectDemo::Render()
{
	for (Rect* r : rects)
		r->Render();
}

void RectDemo::PostRender()
{
}

void RectDemo::GUI()
{
	ImGui::Begin("Rects");
	{
		for (Rect* r : rects)
			r->GUI();
	}
	ImGui::End();
}

RectDemo.cpp입니다. Init()은 작성하지 않은 게 아니라 비어있는 부분입니다. PostRender는 아직 작성하지 않았습니다.

읽어주셔서 감사합니다.

'공부 > 2D강의' 카테고리의 다른 글

221202 강의  (0) 2022.12.02
221201 강의  (0) 2022.12.02
221129 강의  (0) 2022.11.30
221128 강의  (0) 2022.11.29
221125 강의  (0) 2022.11.26
Comments