응애맘마조
221130 강의 본문
오늘 강의를 작성하기 전에 오타 난 부분을 알려드리겠습니다.
//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는 아직 작성하지 않았습니다.
읽어주셔서 감사합니다.