프로젝트 설정
기존에 작업했던 작업물에서 3D 에 맞춰 작업하기 위해 새로운 프로젝트를 만들어보자. 기존에 사용했던 코드들 중 일부는 그대로 가져와주고 파이프라인 작업은 조금더 세련된 방법으로 수정한다.
VS에서 Windows 데스크탑 마법사로 프로젝트를 만들어준다.
그리고 나서 먼저 라이브러리를 만들어주자.
파일 구조는 위와 같이 맞춰주고 Enginge 프로젝트에서 설정을 맞춰준다.
위 과정은 많은 생략이 되어있다. 기존에 작성된 코드를 복사 하기도 한 반면 새로운 라이브러리들도 많이 추가되었기 때문에 너무 긴 글이 탄생할까 생략되었다.
여기서 중요한건 Shader인데 우리가 2D 에서 사용하던 Render는 IA 과정과 VS, RS, PS 등등 여러 과정을 수동으로 전부 다 넣어줬어야 하는 반면 이건 자동으로 그 과정을 스킵해준다는게 중요한 포인트이다.
사각형 띄우기
QuadDemo 라는 클래스를 만들어서 IExecute 클래스를 상속받아 Init Update Render를 이용해 사각형를 화면에 띄워보자. 쉐이더는 다음과 같이 지정해 사용한다.
그 전에 간단한 사각형이나 도형들은 GeometryHelper라는 클래스를 만들어서 미리 정의해두자.
#include "pch.h"
#include "GeometryHelper.h"
void GeometryHelper::CreateQuad(shared_ptr<Geometry<VertexColorData>> geometry, Color color)
{
vector<VertexColorData> vtx;
vtx.resize(4);
vtx[0].position = Vec3(-0.5f, -0.5f, 0.f);
vtx[0].color = color;
vtx[1].position = Vec3(-0.5f, 0.5f, 0.f);
vtx[1].color = color;
vtx[2].position = Vec3(0.5f, -0.5f, 0.f);
vtx[2].color = color;
vtx[3].position = Vec3(0.5f, 0.5f, 0.f);
vtx[3].color = color;
geometry->SetVertices(vtx);
vector<uint32> idx = { 0,1,2,2,1,3 };
geometry->SetIndices(idx);
}
이제 Quad는 이렇게 채울 수 있을 것이다.
#pragma once
#include "IExecute.h"
#include "Geometry.h"
class QuadDemo : public IExecute
{
public:
void Init() override;
void Update() override;
void Render() override;
shared_ptr<Shader> _shader;
shared_ptr<Geometry<VertexColorData>> _geometry;
shared_ptr<VertexBuffer> _vertexBuffer;
shared_ptr<IndexBuffer> _indexBuffer;
};
#include "pch.h"
#include "02. QuadDemo.h"
#include "GeometryHelper.h"
void QuadDemo::Init()
{
DC->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
_shader = make_shared<Shader>(L"02. Quad.fx");
_geometry = make_shared<Geometry<VertexColorData>>();
GeometryHelper::CreateQuad(_geometry, Color(1.f, 0.f, 0.f, 1.f));
_vertexBuffer = make_shared<VertexBuffer>();
_vertexBuffer->Create(_geometry->GetVertices());
_indexBuffer = make_shared<IndexBuffer>();
_indexBuffer->Create(_geometry->GetIndices());
}
void QuadDemo::Update()
{
}
void QuadDemo::Render()
{
uint32 stride = _vertexBuffer->GetStride();
uint32 offset = _vertexBuffer->GetOffset();
DC->IASetVertexBuffers(0, 1, _vertexBuffer->GetComPtr().GetAddressOf(), &stride, &offset);
DC->IASetIndexBuffer(_indexBuffer->GetComPtr().Get(), DXGI_FORMAT_R32_UINT, 0);
_shader->DrawIndexed(0, 0, _indexBuffer->GetCount(), 0, 0);
}
struct VertexInput
{
float4 position : POSITION;
float4 color : COLOR;
};
struct VertexOutput
{
float4 position : SV_POSITION;
float4 color : COLOR;
};
VertexOutput VS(VertexInput input)
{
VertexOutput output;
output.position = input.position;
output.color = input.color;
return output;
}
float4 PS(VertexOutput input) : SV_TARGET
{
return input.color;
}
RasterizerState FillModeWireFrame
{
FillMode = WireFrame;
};
technique11 T0
{
pass P0
{
SetVertexShader(CompileShader(vs_5_0, VS()));
SetPixelShader(CompileShader(ps_5_0, PS()));
}
pass P1
{
SetRasterizerState(FillModeWireFrame);
SetVertexShader(CompileShader(vs_5_0, VS()));
SetPixelShader(CompileShader(ps_5_0, PS()));
}
};
이렇게 쉐이더를 설정하고 코드를 실행하면 다음과 같이 나온다. 만약 와이어프레임 모드로 설정을 하게 되면 오른쪽과 같이 나온다.
Constant Buffer
이번에는 Constant Buffer에 대해 실습해보자. 우리가 어떤 오브젝트를 화면에 보여주기 위해 VS 과정에서 좌표계를 수정하는 연산을 한적이 있는데 이는 ConstBuffer를 이용해서 진행했다. 이를 간결하게 하는 걸 해보자.
matrix World;
matrix View;
matrix Projection;
struct VertexInput
{
float4 position : POSITION;
float4 color : COLOR;
};
struct VertexOutput
{
float4 position : SV_POSITION;
float4 color : COLOR;
};
VertexOutput VS(VertexInput input)
{
VertexOutput 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;
}
이전에는 cbuffer : register 등으로 이용해 직접적으로 변수를 사용할 레지스터에 꽂아줬지만 이제 그냥 변수만 선언하고 그 값만 채워주면 바로 사용할 수 있다.
#pragma once
#include "IExecute.h"
#include "Geometry.h"
class ConstBuffer : public IExecute
{
public:
void Init() override;
void Update() override;
void Render() override;
shared_ptr<Shader> _shader;
shared_ptr<Geometry<VertexColorData>> _geometry;
shared_ptr<VertexBuffer> _vertexBuffer;
shared_ptr<IndexBuffer> _indexBuffer;
Vec3 _translation = Vec3(0.f, 0.f, 0.f);
Matrix _world = Matrix::Identity;
Matrix _view = Matrix::Identity;
Matrix _projection = Matrix::Identity;
};
#include "pch.h"
#include "03. ConstBufferDemo.h"
#include "GeometryHelper.h"
void ConstBuffer::Init()
{
DC->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
_shader = make_shared<Shader>(L"03. ConstBuffer.fx");
_geometry = make_shared<Geometry<VertexColorData>>();
GeometryHelper::CreateQuad(_geometry, Color(0.f, 1.f, 0.f, 1.f));
_vertexBuffer = make_shared<VertexBuffer>();
_vertexBuffer->Create(_geometry->GetVertices());
_indexBuffer = make_shared<IndexBuffer>();
_indexBuffer->Create(_geometry->GetIndices());
}
void ConstBuffer::Update()
{
float dt = TIME->GetDeltaTime();
if (INPUT->GetButton(KEY_TYPE::A))
{
_translation.x -= 3.f * dt;
}
else if (INPUT->GetButton(KEY_TYPE::D))
{
_translation.x += 3.f * dt;
}
else if (INPUT->GetButton(KEY_TYPE::W))
{
_translation.y += 3.f * dt;
}
else if (INPUT->GetButton(KEY_TYPE::S))
{
_translation.y -= 3.f * dt;
}
// SRT
_world = Matrix::CreateTranslation(_translation);
}
void ConstBuffer::Render()
{
_shader->GetMatrix("World")->SetMatrix((float*)&_world);
_shader->GetMatrix("View")->SetMatrix((float*)&_view);
_shader->GetMatrix("Projection")->SetMatrix((float*)&_projection);
uint32 stride = _vertexBuffer->GetStride();
uint32 offset = _vertexBuffer->GetOffset();
DC->IASetVertexBuffers(0, 1, _vertexBuffer->GetComPtr().GetAddressOf(), &stride, &offset);
DC->IASetIndexBuffer(_indexBuffer->GetComPtr().Get(), DXGI_FORMAT_R32_UINT, 0);
_shader->DrawIndexed(0, 0, _indexBuffer->GetCount(), 0, 0);
}
'C++ > DirectX 11' 카테고리의 다른 글
[DirectX] DirectX 11 3D 입문 - Height Map, Normal, Mesh (0) | 2024.09.13 |
---|---|
[DirectX] DirectX 11 3D 입문 - 카메라, 텍스처, Geometry (0) | 2024.09.12 |
[DirectX] 엔진 구조로 제작하기 - Material, Animation, Data (0) | 2024.09.10 |
[DirectX] 엔진 구조로 제작하기 - Managers (0) | 2024.09.06 |
[DirectX] 엔진 구조로 제작하기 - Component, MeshRenderer (2) | 2024.09.05 |