• Home
  • About
    • 게임 개발자 유정룡 photo

      게임 개발자 유정룡

      포트폴리오

    • Learn More
    • Email
    • Github
    • Bitbucket
  • Projects
    • All Projects
    • All Tags

DirectX11 공부 2일차(Vertext Shader, Pixel Shader)

02 Jun 2021

Reading time ~3 minutes

배운것

  1. Vertext Shader
  2. InputLayout연결
  3. Pixel Shader

Vertext Shader

Vertext Buffer 정점의 정보를 저장해 두는 정점들의 집합버퍼

Vertext Shader 는 주로 Vertext Buffer의 정점들을 3D 공간으로 변형시키도록 작성된 작은 프로그램

Color.hlsl

struct vertexInput
{
	float4 position : POSITION0;
	float4 color : COLOR0;
};

struct PixelInput
{
	float4 position : SV_POSITION0;
	float4 color : COLOR0;
};

PixelInput VS(vertexInput input)
{
	PixelInput output;
	output.position = input.position;
	output.color = input.color;
	
	return output;
}

쉐이더 파일 일단 자세한 설명은 추후 함

Execute.h (추가요소)

	ID3D11VertexShader* vertex_shader = nullptr;
	ID3DBlob* vs_blob = nullptr;					// Binary Large Object

ID3D11VertexShader : Vertex Shader단계를 제어하는 실행 가능한 프로그램을 관리

Vertex Shader 인터페이스를 생성하려면 ID3D11Device :: CreateVertexShader를 호출

ID3DBlob(Binary Large Object) : 임의 길이의 데이터를 반환하는 데 사용함

Execute.cpp (추가요소)

Execute::Execute()
{
	'
	'
	'
	// VertexShader
	{
		HRESULT hr = D3DX11CompileFromFileA
		(
			"Color.hlsl",
			nullptr,
			nullptr,
			"VS",
			"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 }
		};

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

D3DX11CompileFromFileA : 쉐이더 컴파일

Input Layout : GPU에 버텍스 구조체의 레이아웃을 설명하는 D3D 오브젝트

D3D11_INPUT_ELEMENT_DESC : 각각의 버텍스 속성, 배열로 정의해서 버텍스 전체에 대한 input layout 오브젝트를 만듦

CreateInputLayout : 컴파일 된 쉐이더에서 버텍스 쉐이더 개체를 만듦

Render()
{
	'
	'
	'
		// VS // 정점 개수만큼 호출
		graphics->GetDeviceContext()->VSSetShader(vertex_shader, nullptr, 0);
	}
	'
	'
	'
}

정점 갯수만큼 호출을 해줌

Pixel Shader

Pixel Shader : 렌더링 될 각각의 픽셀들의 색을 계산. 최종적으로 픽셀이 어떻게 보일지를 결정

Color.hlsl (추가요소)

float4 PS(PixelInput input) : SV_Target
{
    return input.color;
}

SV_Target을 사용하여 현재 세팅된 메인 렌더 타겟을 사용하라고 알려줌

Pixel Shader 의 색을 계산하기 위해 색을 반환

Execute.h (추가요소)

	ID3D11PixelShader* pixel_shader = nullptr;
	ID3DBlob* ps_blob = nullptr;

ID3D11PixelShader : 픽셀 쉐이더 단계를 저아하는 실행 가능한 프로그램을 관리

Execute.cpp (추가요소)

생성자

{
	HRESULT hr = D3DX11CompileFromFileA
	(
		"Color.hlsl",
		nullptr,
		nullptr,
		"PS",
		"ps_5_0",
		0,
		0,
		nullptr,
		&ps_blob,
		nullptr,
		nullptr
	)
	assert(SUCCEEDED(hr));

	hr = graphics->GetDevice()->CreatePixelShader(ps_blob->GetBufferPointer(, ps_blob->GetBufferSize(), nullptr, &pixel_shader);
	assert(SUCCEEDED(hr));
}

Vertex Shader와 비슷하겜 사용

대신 CreatePixelShader를 사용

Render()
{
	'
	'
	'
	// PS
		graphics->GetDeviceContext()->PSSetShader(pixel_shader, nullptr, 0);

		graphics->GetDeviceContext()->Draw(3, 0);
	'
	'
	'
}

PSSetShader를 사용하여 픽셀 쉐이더를 세팅해주고

Draw로 그려줌 Draw(정점의 갯수, 시작 위치)

어예 무지개 삼각형 와!

아 색이 왜 저렇게 나오냐하면 GPU는 병렬 처리 되기 때문에 동시에 랜더링 해서 그렇다고 수업에서 그랬다.

좀더 찾아보니, 각 정점의 색을 주게 되면 나머지 색은 정점으로 가면 갈수록 정점의 색으로 보간이 되서 값이 들어가게 된다고 한다. (학교 OpenGL수업이 생각났다.)

사각형

그래픽스의 모든 물체는 삼각형으로 이루어져있음

왜?

포프TV에서 봤는지 어디서 주워들었는지 기억이 안나는데 각 도형의 축에 변형을 줘도 도형의 변형이 없기 때문에 사용한다고 들었다.

오피셜 아니니까 믿지 마시고 수업에서는 가장 다양한 도형을 만들 수 있기 때문이라고 한다.

그래서 지금까지의 기본적인 내용으로 사각형을 만들고 싶으면 삼각형 두개를 사용하여 만들어야 한다.

Execute의 생성자에서 정점의 갯수를 6개로 늘린다.

vertices = new VertexColor[6];
vertices[0].position = D3DXVECTOR3(-0.5f, -0.5f, 0.0f);
vertices[0].color = D3DXCOLOR(1.0f, 0.0f, 0.0f, 1.0f);

vertices[1].position = D3DXVECTOR3(-0.5f, 0.5f, 0.0f);
vertices[1].color = D3DXCOLOR(0.0f, 1.0f, 0.0f, 1.0f);

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

vertices[3].position = D3DXVECTOR3(0.5f, -0.5f, 0.0f);
vertices[3].color = D3DXCOLOR(0.0f, 0.0f, 1.0f, 1.0f);

vertices[4].position = D3DXVECTOR3(-0.5f, 0.5f, 0.0f);
vertices[4].color = D3DXCOLOR(0.0f, 1.0f, 0.0f, 1.0f);

vertices[5].position = D3DXVECTOR3(0.5f, 0.5f, 0.0f);
vertices[5].color = D3DXCOLOR(1.0f, 0.0f, 0.0f, 1.0f);

색은 그냥 무지개로 만들었다

그리고 난 뒤 버텍스 버퍼에서 리소스 설정할때 바이트 크기를 정점의 갯수만큼 늘린다.

D3D11_BUFFER_DESC desc;
ZeroMemory(&desc, sizeof(D3D11_BUFFER_DESC));
desc.Usage = D3D11_USAGE_IMMUTABLE;						
desc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
desc.ByteWidth = sizeof(VertexColor) * 6;				// 요기요기

마지막으로 Draw할때 정점의 갯수를 총 갯수로 늘린다.

graphics->GetDeviceContext()->Draw(6, 0);

그렇게 하면

와! 무지개 사각형!

이쁘장하게 만들 수 있다

후기

슬슬 재밌어 진다. 하다 보면 어려워서 다시 노잼 되겠지 ㅋㅋ



DirectX Share Tweet +1