인덱스버퍼

현재 -> 사각형- 삼각형 2개  만약 이런식이라면 그 많은 도형을 표현하기엔 메모리가 너무 많이 소모된다.

-> 인덱스 버퍼사용

정점들에 인덱스(넘버)를 부여하여 사용

 

이걸 코드로 만들어보자 일단 정점을 하나 추가해보자 그리고 정점 순서에 맞게 좌표를 수정해준다.

//13 -> 012
//02 -> 213
_vertices[0].position = Vec3(-0.5f, -0.5f, 0.f);
_vertices[0].color = Color(1.f, 0.f, 0.f, 1.f);
_vertices[1].position = Vec3(-0.5f, 0.5f, 0.f);
_vertices[1].color = Color(1.f, 0.f, 0.f, 1.f);
_vertices[2].position = Vec3(0.5f, -0.5f, 0.f);
_vertices[2].color = Color(1.f, 0.f, 0.f, 1.f);
_vertices[3].position = Vec3(0.5f, 0.5f, 0.f);
_vertices[3].color = Color(1.f, 0.f, 0.f, 1.f);

 

인덱스버퍼에 필요한 변수를 만들고 Geometry에 인덱스 버퍼 부분을 만들어주자

변수 

//인덱스버퍼 - 이거도 Geometry에 포함
vector<uint32> _indices;
ComPtr<ID3D11Buffer> _indexBuffer = nullptr;
//Index
{
	_indices = { 0,1,2,2,1,3 };
}

//IndexBuffer
{
	D3D11_BUFFER_DESC desc;
	ZeroMemory(&desc, sizeof(desc));
	desc.Usage = D3D11_USAGE_IMMUTABLE;			//gpu만 read only
	desc.BindFlags = D3D11_BIND_INDEX_BUFFER;
	desc.ByteWidth = (uint32)(sizeof(uint32) * _indices.size());

	D3D11_SUBRESOURCE_DATA data;
	ZeroMemory(&data, sizeof(data));
	data.pSysMem = _indices.data();			//첫번째 시작주소 cpu값이 복사된다.

	HRESULT hr= _device->CreateBuffer(&desc, &data, _indexBuffer.GetAddressOf());
	CHECK(hr);
}

 

인덱스 버퍼 세팅

IA 세팅 과정 중에 -> 랜더에 있는 세팅부분에 추가해줘야한다. 

기존

	//IA - 세팅부분
	_deviceContext->IASetVertexBuffers(0, 1, _vertexBuffer.GetAddressOf(),&stride, &offset);
	_deviceContext->IASetInputLayout(_inputLayout.Get());
	_deviceContext->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST);		//삼각형으로 만들어주기

 

수정

	//IA - 세팅부분
	_deviceContext->IASetVertexBuffers(0, 1, _vertexBuffer.GetAddressOf(),&stride, &offset);
	_deviceContext->IASetIndexBuffer(_indexBuffer.Get(), DXGI_FORMAT_R32_UINT,0);
	_deviceContext->IASetInputLayout(_inputLayout.Get());
	_deviceContext->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST);		//삼각형으로 만들어주기
    
    
    //인덱스를 통해 그려주기
    _deviceContext->DrawIndexed(_indices.size(), 0, 0);

 

이렇게하면 Index버퍼를 사용할 준비가 완료되었다. 

 

실행화면

 

정점버퍼와 인덱스버퍼의 차이점

-> 인덱스버퍼는 삼각형에 넘어가는 정점 개수를 줄여줘 메모리적으로 효율적으로 작업할 수 있다.

 

정점버퍼와 인덱스버퍼의 조합으로 삼각형이 어떻게 만들어지는지 판단할 수 있다.

 

이제 사각에 이미지를 띄워보자 

 

중요한 점 : uv좌표, 쉐이더코드 수정

 

uv좌표 - 이미지의 좌상단 0,0 우하단 1,1로 했을 때 퍼센티지로 가져오기 위함 

uv좌표

 

Stuct.h 수정 및 정점정보 수정

#pragma once
#include "Types.h"


struct Vertex
{
	Vec3 position;		//12바이트 0부터시작
	//Color color;		//12부터시작
	Vec2 uv;			
};

 

//정점정보
{
	_vertices.resize(4);

	//13 -> 012
	//02 -> 213
	_vertices[0].position = Vec3(-0.5f, -0.5f, 0.f);
	_vertices[0].uv = Vec2(0.f, 1.f);
	//_vertices[0].color = Color(1.f, 0.f, 0.f, 1.f);
	_vertices[1].position = Vec3(-0.5f, 0.5f, 0.f);
	_vertices[1].uv = Vec2(0.f, 0.f);
	//_vertices[1].color = Color(1.f, 0.f, 0.f, 1.f);
	_vertices[2].position = Vec3(0.5f, -0.5f, 0.f);
	_vertices[2].uv = Vec2(1.f, 1.f);
	//_vertices[2].color = Color(1.f, 0.f, 0.f, 1.f);
	_vertices[3].position = Vec3(0.5f, 0.5f, 0.f);
	_vertices[3].uv = Vec2(1.f, 0.f);
	//_vertices[3].color = Color(1.f, 0.f, 0.f, 1.f);
}

 

그리고 이에 맞게 InputLayout을 고쳐줘야하는데 이 때 쉐이더와 맞춰주어야하기 때문에 

많이 사용하는 TEXCOORD - 텍스처의 좌를 사용한다. 

InputLayout 및 쉐이더 수정

struct VS_INPUT
{
    float4 position : POSITION;
    //float4 color : COLOR;
    float2 uv : TEXCOORD;
};

struct VS_OUTPUT
{
    float4 position : SV_POSITION;      //시스템 VALUE  무조건 있어야한다.
    //float4 color : COLOR;
    float2 uv : TEXCOORD;
};
	//입력에 대한 정보 ~바이트부터 뛰면 칼러인지 
	D3D11_INPUT_ELEMENT_DESC layout[] =
	{
		{"POSITION",0,DXGI_FORMAT_R32G32B32_FLOAT,0,0,D3D11_INPUT_PER_VERTEX_DATA,0},
		{"TEXCOORD",0,DXGI_FORMAT_R32G32_FLOAT,0,12,D3D11_INPUT_PER_VERTEX_DATA,0}
	};

 

이미지파일 소스를 gpu쪽에도 건네줘서 알고있도록 해야한다. 

레지스터에 등록해주기

//함수의 인자같은 존재, 오브젝트마다 달라질수있다.
Texture2D texture0 : register(t0);      //레지스터에 등록
SamplerState sampler0 : register(s0);

 

등록해준 레지스터를 통해 텍스처 색상을 가져오기 

//모든 픽셀단위 대상 - 색상관련
float4 PS(VS_OUTPUT input) : SV_Target  //랜더 타켓하는 곳으로 보내주기
{
    float4 color = texture0.Sample(sampler0, input.uv);     //텍스처0번 uv좌표를 통해 색상 빼오기
    
    return color;
}

해당 이미지파일을 cpu에서 리소스로 가지고 gpu쪽에도 만들어준 다음 파이프라인에 연결

 

픽셀쉐이더부분에서 CreateSRV를 통해 할 수 있다.

SRV 쉐이더 리소스 뷰 만들어주기 

SRV변수 추가 -이미지를 어떻게 쓸것인가 

이것을 통해 이미지를 건네준다.  

//SRV - 이미지를 어떻게 쓸것인가
ComPtr<ID3D11ShaderResourceView> _shaderResourceView = nullptr;
void Game::CreateSRV()
{
	DirectX::TexMetadata md;
	DirectX::ScratchImage img;
	HRESULT hr = ::LoadFromWICFile(L"cat.png", WIC_FLAGS_NONE, &md, img);
	CHECK(hr);

	//쉐이더리소스뷰 만들기
	hr = ::CreateShaderResourceView(_device.Get(), img.GetImages(), img.GetImageCount(), md, _shaderResourceView.GetAddressOf());
	CHECK(hr);
}

 

이제 Init부분에 함수를 넣고 Render의 PS부분에서 이미지와 연결시켜주자 

void Game::Init(HWND hwnd)
{
	_hwnd = hwnd;
	_width = GWinSizeX;
	_height = GwinSizeY;


	CreateDeviceAndSwapChain();
	CreateRenderTargetView();
	SetViewport();

	//삼각형 그리기 파트
	CreateGeometry();
	CreateVS();
	CreateInputLayout();
	CreatePS();

	CreateSRV();
}
	//PS
	_deviceContext->PSSetShader(_pixelShader.Get(), nullptr, 0);
	_deviceContext->PSSetShaderResources(0, 1, _shaderResourceView.GetAddressOf());		//0번슬롯에 1개

 

실행화면 

 

uv 1일때 

uv 0.5일때

 

uv좌표가 1을 초과했을 때 어떻게 할지

-> 레스터라이저단계의 샘플스테이트를 통해 관리 

 

어떤게 범용적 어떤게 오브젝트에 종속적인지 생각해보기 

ex) GeoMetry - 매쉬 - 오브젝트 대상

쉐이더 - 범용적

'게임공부 > Directx11' 카테고리의 다른 글

[Directx11]4. 삼각형 그리기  (1) 2024.07.01
[Directx11]3.장치초기화  (0) 2024.06.27
[Directx11]2.초기설정  (0) 2024.06.26
[Directx11]그래픽스OT  (0) 2024.06.25
[Directx11]2.랜더링 파이프라인2  (0) 2024.06.21

+ Recent posts