[DX11] 텍스처 UV

jaehyeonLee·2025년 2월 9일

dx11

목록 보기
3/3

삼각형을 화면에 띄우기 까지는 해보았다. 그러면 사각형을 화면에 띄우기 위해서는 몇개의 정점들이 필요할까 4개라고 생각할 수 있지만 실제로는 6개의 정점이 필요하게될거다.그 이유가 사각형을 띄우기 위해서는 최소한 삼각형이 2개가 있어야하기때문이다.
4개만 사용해서 사각형을 만들수가 있는데 실제로는 6개의 정점을 만들어야한다는것은 지금이야 메모리로 별로 차이가 안난다고하더라도 이후 정점에 여러가지 정보들이 들어가 메모리가 커질수가 있고 삼각형이 굉장히 많이 들어가있는 mesh 데이터를 만들어야한다거나 이럴 경우 메모리 낭비가 심해질것이다.
이를 위해서 Index Buffer라는 buffer를 사용한다.

Index Buffer

IndexBuffer의 개념 같은경우에는 저번에도 한번 다룬적이 있어 간단히 다루어보면 정점에 번호를 매기고 Index Buffer에는 삼각형을 만들기 위한 정점의 순서를 저장한다

위에 사각형 처럼 0,1,2,3이 매겨지면 INDEX BUFFER에는 {0,1,2,2,1,3}이라는 정점의 번호를 매겨주면 4개의 정점으로도 사각형을 만들수있게된다.

코드

.h

vector<Vertex>_vertices;
ComPtr<ID3D11Buffer> _vertexBuffer = nullptr;
ComPtr<ID3D11InputLayout>_inputLayout = nullptr;

vector<uint32> _indices;
ComPtr<ID3D11Buffer> _indexBuffer = nullptr;

.cpp

void Game::CreateGeometry()
{	RenderBegin();
	{
		uint32 stride = sizeof(Vertex);
		uint32 offset = 0;
		//IA
		_deviceContext->IASetVertexBuffers(0, 1, _vertexBuffer.GetAddressOf(), &stride, &offset);
		_deviceContext->IASetIndexBuffer(_indexBuffer.Get(), DXGI_FORMAT_R32_UINT, 0);
		_deviceContext->IASetInputLayout(_inputLayout.Get());
		_deviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
		
		//VS
		_deviceContext->VSSetShader(_vertexShader.Get(), nullptr, 0);

		//RS

		//PS
		_deviceContext->PSSetShader(_pixelShader.Get(), nullptr, 0);
		_deviceContext->PSSetShaderResources(0, 1, _shaderResourceView.GetAddressOf());

		//OM
	
		_deviceContext->DrawIndexed(_indices.size(),0,0);
	}
	RenderEnd();
	{
		_vertices.resize(4);
		_vertices[0].position = Vec3( - 0.5f, -0.5f, 0.f );
		_vertices[0].uv = Vec2{ 0.f,1.f };
		_vertices[1].position = Vec3( -0.5f, 0.5f,0.f );
		_vertices[1].uv = { 0,0 };
		_vertices[2].position = Vec3( 0.5f,-0.5f,0.f );
		_vertices[2].uv = { 1.f,1.f };
		_vertices[3].position = Vec3(0.5f, 0.5f, 0.f);
		_vertices[3].uv = { 1.f,0 };
	}
	{
		D3D11_BUFFER_DESC desc;
		ZeroMemory(&desc, sizeof(desc));
		//IMMUTABLE : GPU만 읽을수있음 CPU는 접근 불가
		//삼각형에 대한 기하학적인 도형은 안변함 ==고칠일없음
		desc.Usage = D3D11_USAGE_IMMUTABLE;
		desc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
		desc.ByteWidth =static_cast<uint32> (sizeof(Vertex) * _vertices.size());

		D3D11_SUBRESOURCE_DATA data;
		ZeroMemory(&data, sizeof(data));
		data.pSysMem = _vertices.data();

		_device->CreateBuffer(&desc, &data, _vertexBuffer.GetAddressOf());
	}
	{
		_indices = { 0,1,2,2,1,3 };
	}
	//IndexBuffer
	{
		D3D11_BUFFER_DESC desc;
		ZeroMemory(&desc, sizeof(desc));
		//IMMUTABLE : GPU만 읽을수있음 CPU는 접근 불가
		//삼각형에 대한 기하학적인 도형은 안변함 ==고칠일없음
		desc.Usage = D3D11_USAGE_IMMUTABLE;
		desc.BindFlags = D3D11_BIND_INDEX_BUFFER;
		desc.ByteWidth = static_cast<uint32> (sizeof(uint32) * _indices.size());

		D3D11_SUBRESOURCE_DATA data;
		ZeroMemory(&data, sizeof(data));
		data.pSysMem = _indices.data();

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

텍스처 UV

UV좌표

Uv 좌표란, 텍스처 이미지를 3차원 공간애 맵핑하기 위한 2차원 공간에서의 좌표를 의미한다.
이미지의 크기가 얼마나 크던 작던, (0,0)~(1,1)의 좌표를 가진다.
이를 객체에 이미지를 씌울 때는 0과 1에 입히려는 이미지의 크기로 나눈 비율을 대입하여 이미지를 출력한다.

참고
https://blog.naver.com/hblee4119/222150877699

.h

//SRV
ComPtr<ID3D11ShaderResourceView> _shaderResourceView;

.cpp

void Game::CreateGeometry()
{
	{
		_vertices.resize(4);
		_vertices[0].position = Vec3( - 0.5f, -0.5f, 0.f );
		_vertices[0].uv = Vec2{ 0.f,1.f };
		_vertices[1].position = Vec3( -0.5f, 0.5f,0.f );
		_vertices[1].uv = { 0,0 };
		_vertices[2].position = Vec3( 0.5f,-0.5f,0.f );
		_vertices[2].uv = { 1.f,1.f };
		_vertices[3].position = Vec3(0.5f, 0.5f, 0.f);
		_vertices[3].uv = { 1.f,0 };
	}
	{
		D3D11_BUFFER_DESC desc;
		ZeroMemory(&desc, sizeof(desc));
		//IMMUTABLE : GPU만 읽을수있음 CPU는 접근 불가
		//삼각형에 대한 기하학적인 도형은 안변함 ==고칠일없음
		desc.Usage = D3D11_USAGE_IMMUTABLE;
		desc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
		desc.ByteWidth =static_cast<uint32> (sizeof(Vertex) * _vertices.size());

		D3D11_SUBRESOURCE_DATA data;
		ZeroMemory(&data, sizeof(data));
		data.pSysMem = _vertices.data();

		_device->CreateBuffer(&desc, &data, _vertexBuffer.GetAddressOf());
	}
	{
		_indices = { 0,1,2,2,1,3 };
	}
	//IndexBuffer
	{
		D3D11_BUFFER_DESC desc;
		ZeroMemory(&desc, sizeof(desc));
		//IMMUTABLE : GPU만 읽을수있음 CPU는 접근 불가
		//삼각형에 대한 기하학적인 도형은 안변함 ==고칠일없음
		desc.Usage = D3D11_USAGE_IMMUTABLE;
		desc.BindFlags = D3D11_BIND_INDEX_BUFFER;
		desc.ByteWidth = static_cast<uint32> (sizeof(uint32) * _indices.size());

		D3D11_SUBRESOURCE_DATA data;
		ZeroMemory(&data, sizeof(data));
		data.pSysMem = _indices.data();

		HRESULT hr = _device->CreateBuffer(&desc, &data, _indexBuffer.GetAddressOf());
		CHECK(hr);
	}
}
void Game::CreateSRV()
{
	DirectX::TexMetadata md;
	DirectX::ScratchImage img;
	HRESULT hr= ::LoadFromWICFile(L"MushMom.png", WIC_FLAGS_NONE,&md,img );
	CHECK(hr);
	
	hr = ::CreateShaderResourceView(_device.Get(), img.GetImages(), img.GetImageCount(), md, _shaderResourceView.GetAddressOf());
	CHECK(hr);
}
void Game::Render()
{
	RenderBegin();
	{
		uint32 stride = sizeof(Vertex);
		uint32 offset = 0;
		//IA
		_deviceContext->IASetVertexBuffers(0, 1, _vertexBuffer.GetAddressOf(), &stride, &offset);
		_deviceContext->IASetIndexBuffer(_indexBuffer.Get(), DXGI_FORMAT_R32_UINT, 0);
		_deviceContext->IASetInputLayout(_inputLayout.Get());
		_deviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
		
		//VS
		_deviceContext->VSSetShader(_vertexShader.Get(), nullptr, 0);

		//RS

		//PS
		_deviceContext->PSSetShader(_pixelShader.Get(), nullptr, 0);
		_deviceContext->PSSetShaderResources(0, 1, _shaderResourceView.GetAddressOf());

		//OM
	
		_deviceContext->DrawIndexed(_indices.size(),0,0);
	}
	RenderEnd();
}

1.Vertex Shader(VS) 단계에서 정점(Vertex)에 대응하는 UV 좌표를 계산하고,
2. Rasterizer(래스터라이저) 가 정점 데이터를 보간하여 픽셀 단위로 변환한 후,
3. Pixel Shader(PS) 단계에서 보간된 UV 좌표를 이용해 텍스처에서 색상을 샘플링함.

PS에서 실제로 UV 좌표를 이용해 텍스처 색상을 가져와서 픽셀 색상을 계산을 한다고 보면된다 .

.hlsl


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

struct VS_OUTPUT
{
    float4 position : SV_POSITION;
    float2 uv : TEXCOORD;
};

VS_OUTPUT VS(VS_INPUT input)
{
    VS_OUTPUT output;
    output.position = input.position;
    output.uv = input.uv;
    return output;
}
Texture2D texture0 : register(t0);
SamplerState sampler0 : register(s0);

float4 PS(VS_OUTPUT input) : SV_Target  
{
    float4 color = texture0.Sample(sampler0, input.uv);
    return color;
}

Texture2D texture0 : register(t0);
SamplerState sampler0 : register(s0);
위 코드는 gpu의 특정슬롯에 연결시키겠다는 의미이다.

profile
이재현의 필기노트

0개의 댓글