35 Constant Buffer

gksrudtlr
|2025. 1. 16. 15:17

ConstBuffer Class

  • 이번에는 ConstantBuffer를 이용해 그려진 사각형을 움직여 볼 것이다
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파일을 복사해준다
  • 그 이유는 이전과 동일한 방식으로 그림을 그릴 것이기 때문이다
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;
}

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()));
    }
};
  • 이제 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()가 호출되면서 변한 값들이 적용되어 물체가 이동하는 것을 볼 수 있다

'DirectX' 카테고리의 다른 글

37 Texture  (0) 2025.01.20
36 Camera  (0) 2025.01.20
34 사각형 띄우기  (0) 2025.01.16
33 새 프로젝트 시작  (0) 2025.01.16
32 Data  (0) 2025.01.12