class ConstBufferDemo : public IExecute
{
public:
void Init() override;
void Update() override;
void Render() override;
private:
shared_ptr<Shader> shader;
shared_ptr<Geometry<VertexColorData>> geometry;
shared_ptr<VertexBuffer> vertexBuffer;
shared_ptr<IndexBuffer> indexBuffer;
Vec3 translation = Vec3(0.0f, 0.0f, 0.0f);
Matrix world = Matrix::Identity;
Matrix view = Matrix::Identity;
Matrix projection = Matrix::Identity;
};
ConstBufferDemo.cpp
void ConstBufferDemo::Init()
{
shader = make_shared<Shader> (L"03.ConstBuffer.fx");
geometry = make_shared<Geometry<VertexColorData>>();
GeometryHelper::CreateQuad(geometry, Color(1.0f, 0.0f, 0.0f,1.0f));
vertexBuffer = make_shared<VertexBuffer>();
vertexBuffer->Create(geometry->GetVertices());
indexBuffer = make_shared<IndexBuffer>();
indexBuffer->Create(geometry->GetIndices());
}
void ConstBufferDemo::Update()
{
float deltaTime = TIME->GetDeltaTime();
//업데이트 함수에서 어떤 특정값을 빼는 것은 컴퓨터마다 속도가 달라 Update 호출 주기가 달라 컴퓨터 사양마다 속도가 달라질 것이다
//그래서 이를 해결하기 위해 deltaTime을 곱해줘야 한다
if (INPUT->GetButton(KEY_TYPE::A))
translation.x -= 3.0f * deltaTime;
if(INPUT->GetButton(KEY_TYPE::D))
translation.x += 3.0f * deltaTime;
if(INPUT->GetButton(KEY_TYPE::W))
translation.y += 3.0f * deltaTime;
if(INPUT->GetButton(KEY_TYPE::S))
translation.y -= 3.0f * deltaTime;
//SRT
world = Matrix::CreateTranslation(translation);
}
void ConstBufferDemo::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());
}
이 클래스 역시 이전 클래스를 복사해 이름만 바꿔준뒤 물체가 이동을 할 것이므로 Vec3 translation 변수를 만들어준다
또한 World, View, Projection 변환을 위해 matrix 형 변수도 3개 만들 것이다
Init()에서는 이전과 동일하지만 Render()에서 World, View, Projection을 이 세개의 상수를 Shader로 넘겨줄 것이기 때문에 shader->GetMatrix()에 string 인자를 넘겨주어 Shader에 동일한 문자열이 있는지 찾아주고, 그 변수에 SetMatrix()를 통해 알맞은 정보를 float*형태로 넘겨준다
나머지는 기존과 동일하며, 이제 움직임을 구현하기 위해 Update()에서 TIME->GetDeltaTime() 가져와 줄 것이다
그리고 INPUT을 통해 원하는 키를 설정해 translation의 x,y축을 가져와 원하는 속도에 DeltaTime을 곱한 뒤 더하거나 빼줄 것이다
이때 Update()에서 특정 값을 가져와 연산을 하는 것은 컴퓨터의 속도에 따라 Update() 호출 주기가 다르므로 컴퓨터 사양에 따라 결과 값이 달라지는 문제가 생긴다
이를 해결하기 위해 좀전에 가져온 DeltaTime을 곱해 호출된 주기에 따라 변하는 것이 아닌 DeltaTime에 따라 값이 변하도록 해준다
이렇게 연산된 결과를 Matrix로 변환하여 world에 저장해준다
world상에서 위치가 변할것이므로 world에 저장해준것이다
이런 과정을 통해 물체가 그려지고 움직임이 있을 때 마다 연산된 상수 값들이 ConstantBuffer를 통해 Shader로 넘어가고, 반영된 결과물이 화면에 그려지게 된다
Shader
물체가 ConstantBuffer값을 이용해 이동하는지 확인하기 위해 전 시간에 만들었던 fx파일을 복사해준다
이제 CPU에서 상수 값으로 가져올 값인 matrix의 World, View, Projection을 변수로 만들어 주는데 이는 Render()에서Shader->GetMatrix()에 인자로 넘겨줬던 string 값과 동일해야 하며 순서도 맞춰줘야 원하는 곳에 원하는 값이 제대로 들어간다
이 World, View, Projection을 통해 물체가 이동하고, 카메라에 보이는 것등이 달라지는 것이다
이 상수 값들이 변화하면 그려지는 물체도 변화해야 하므로 VS()에서output.position에 mul함수를 통해 input.position과 World를 곱해 World 상에 물체가 이동한 위치를 변경해 저장한다
현재는 View와 Projection이 변하지는 않지만 이 값들도 output.position에 곱한 뒤 output.position에 저장해준다
결과
main 함수에 app을 ConstBufferDemo 클래스로 바꿔준 뒤 출력을 하면 결과물을 볼 수 있다
이제 우리가 설정해둔 버튼을 누르면 계속해서 Update()가 호출되면서 변한 값들이 적용되어 물체가 이동하는 것을 볼 수 있다