KoreanFoodie's Study

DirectX 11 2D 게임 프로그래밍 - 7. Vertex Shader Stage 본문

Game Dev/DirectX

DirectX 11 2D 게임 프로그래밍 - 7. Vertex Shader Stage

GoldGiver 2021. 10. 25. 21:34


DirectX 11 2D 게임 프로그래밍 - 7. Vertex Shader Stage

이번 글에서는 hlsl을 이용해 간단한 Vertex Shaer를 만드는 실습을 해 보도록 하겠다.

HLSL은 High Level Shader Language로, 예전에 어셈블리어로 만들던 것을 더 사람이 보기 쉽게 표현한 언어라고 보면 된다. 프로젝트에 HLSl탭으로 생성한 후, 프로젝트에서 제외시켜서 사용한다. (컴파일에 용이)

 

알아두어야 할 개념 :

1. Semantic : Semantic은 데이터의 출처와 역할에 대한 분명한 의미를 부여하기 위한 키워드이다.

 

 

Color.hlsl

struct VertexInput
{
	// float4는 vector4와 같음
	// Semantic : 데이터의 출처와 역할에 대한 분명한 의미를 부여하기 위한 키워드
	float4 position : POSITION0; // POSITION이 Semantic, 0가 Semantic Index
	float4 color : COLOR0;
};

struct PixelInput
{
	// SV : System Value - 중요한 값... 
	float4 position : SV_POSITION0;
	float4 color : COLOR0;
};

PixelInput VS(VertexInput input)
{
	PixelInput output;

	output.position = input.position;
	output.color = input.color;

	return output;
}

 

Execute.cpp

Vertex Shader와 Input Layout 부분을 구현하여 Color.hlsl을 연동시켜주자.

#include "stdafx.h"
#include "Execute.h"

#include "Graphics.h"

Execute::Execute()
{
	// 그냥 쓰면 불완전한 형식은 사용할 수 없다고 나옴. 따라서 해당 자료형의 헤더파일을 include 해주어야 한다.
	graphics = new Graphics();
	graphics->Initialize();
	graphics->CreateBackBuffer(static_cast<uint>(Settings::Get().GetWidth()), static_cast<uint>(Settings::Get().GetHeight()));

	// 시계방향으로 회전하는 직각삼각형 만들기
	vertices = new VertexColor[3];

	// Vertex Data
	{

		vertices[0].position = D3DXVECTOR3(-0.5f, -0.5f, 0.0f);
		vertices[0].clear_color = D3DXCOLOR(1.01f, 0.0f, 0.0f, 1.0f);

		vertices[1].position = D3DXVECTOR3(+0.5f, +0.5f, 0.0f);
		vertices[1].clear_color = D3DXCOLOR(1.01f, 0.0f, 0.0f, 1.0f);

		vertices[2].position = D3DXVECTOR3(+0.5f, -0.5f, 0.0f);
		vertices[2].clear_color = D3DXCOLOR(1.01f, 0.0f, 0.0f, 1.0f);

	}


	// Vertex Buffer
	{
		D3D11_BUFFER_DESC desc;

		ZeroMemory(&desc, sizeof(D3D11_BUFFER_DESC));
		
		// Usage란? : GPU와 CPU 중 누가 데이터를 읽거나 쓸 것인지 결정하는 플래그
		// D3D11_USAGE_DEFAULT : GPU만 데이터를 읽고 쓸 수 있다.
		// D3D11_USAGE_IMMUTABLE : GPU만 데이터를 읽을 수 있다. (쓰기는 불가)
		desc.Usage = D3D11_USAGE_DEFAULT; 
		
		// Buffer형 데이터를 어느 스테이지에서 사용할 건지 지정해주는 플래그다.
		desc.BindFlags = D3D11_BIND_VERTEX_BUFFER;

		// Vertex 버퍼를 어느 정도 크기로 생성할 것인지?
		desc.ByteWidth = sizeof(VertexColor) * 3;

		// 부가적인 데이터.. CPU데이터를 GPU에 연결할 수 있다.
		D3D11_SUBRESOURCE_DATA sub_data;
		ZeroMemory(&sub_data, sizeof(D3D11_SUBRESOURCE_DATA));
		sub_data.pSysMem = vertices;

		auto hr = graphics->GetDevice()->CreateBuffer(&desc, &sub_data, &vertex_buffer);

		assert(SUCCEEDED(hr));
	}

	// Vertex Shader
	{
		// D3DX11로 시작하는 함수들은 최신 DirectX SDK에는 지원하지 않는다.
		auto hr = D3DX11CompileFromFileA
		(
			"Color.hlsl",
			nullptr,
			nullptr,
			"VS", // entry point
			"vs_5_0",
			0,
			0,
			nullptr,
			&vs_blob,
			nullptr,
			nullptr
		);

		assert(SUCCEEDED(hr));

		hr = graphics->GetDevice()->CreateVertexShader(vs_blob->GetBufferPointer(), vs_blob->GetBufferSize(), nullptr, &vertex_shader);
		assert(SUCCEEDED(hr));

	}


	// Input Layout
	{
		D3D11_INPUT_ELEMENT_DESC layout_desc[]
		{  
			{ "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
			{ "COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 },
		};

		auto hr = graphics->GetDevice()->CreateInputLayout(layout_desc, 2, vs_blob->GetBufferPointer(), vs_blob->GetBufferSize(), &input_layout);
		assert(SUCCEEDED(hr));
	}
}

Execute::~Execute()
{
	SAFE_RELEASE(input_layout);

	SAFE_RELEASE(vertex_shader);
	SAFE_RELEASE(vs_blob);

	SAFE_RELEASE(vertex_buffer);

	SAFE_DELETE_ARRAY(vertices);
	SAFE_DELETE(graphics);
}

void Execute::Update()
{
}

void Execute::Render()
{
	// stride : 정점 하나의 크기에 대한 정보
	uint stride = sizeof(VertexColor);

	// offset : 정점 정보 중에 어떤 정점부터 사용할 것인지에 대한 정보
	uint offset = 0;

	graphics->Begin();

	// Rendering Part
	// 자원을 만들때는 device, GPU에 연동할 때는 device_context
	{
		// IA
		graphics->GetDeviceContext()->IASetVertexBuffers(0, 1, &vertex_buffer, &stride, &offset);
	
		graphics->GetDeviceContext()->IASetInputLayout(input_layout);

		// 정점을 어떻게 연결할 것인가에 대한 연결성 정보. 여기서는 삼각형으로 이어라...
		graphics->GetDeviceContext()->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST)	;


		// VS : 정점의 개수만큼 호출된다.
		graphics->GetDeviceContext()->VSSetShader(vertex_shader, nullptr, 0);

	}
	graphics->End();

}

//

더 자세한 내용이 궁금하시다면 직접 들어보시는 걸 추천드립니다!

 
Comments