DirectX

4. 삼각형 띄우기

devRiripong 2023. 12. 9.
반응형

오늘 한 것들 

1. CreateGeometry를 만들어 삼각형의 구조(VertexData)를 만들고, VertexBuffer를 만들어 GPU에 건내주기

2. CreateInputLayout에서 VertexBuffer를 Input Assembler에 넣을 때 GPU에게 어떻게 분석해서 끊어 읽을지 알려주기

3. Default.hlsl에서 Vertex shader, Pixel shader 만들기

4. 셰이더 파일을 로드하는 LoadShaderFromFile을 이용해 Blob에 저장하고, GPU에 건낼 수 있는 VS와 PS를 Blob을 이용해  만들기

5. VS를 이용하여 CreateInputLayout 함수 완성하고, GPU에 넘길 Vertex의 구조 묘사한 내용을 InputLayout 변수에 채우기

6. _vertexBuffer, _inputLayout, _vertexShader, _pixelShader를 GPU에 연결하고 실행하기

 

 

float _clearColor[4] = { 0.f, 0.f, 0.f, 0.f };
이렇게 수정하여 검은 화면이 뜨게 한다. . 

 

이번 시간은 삼각형을 그리는 게 목표다.

 

삼각형 하나를 그리더라도 렌더링 파이프라인을 거쳐야 한다.

(공부 방법 : 렌더링 파이프 라인을 옆에 띄어 두고 어디에 해당하는지 본다.)

 

1. CreateGeometry를 만들어 삼각형의 구조(VertexData)를 만들고, VertexBuffer를 만들어 GPU에 건내주기

먼저 Game.h에  void CreateGeometry(); 
함수를 선언하고, Game::Init에서 호출한다. 구현부도 만들어 준다. 

Vertex(정점)이라는 정보를 이용해 얘를 묘사해 줄 것이다.


Struct.h에 가서 정점에 대해 정의를 해준다. 

struct Vertex
{
Vec3 position; 
Color color; 
};

 

Game.h에 가서 
도형을 만들 때 사용할 변수를 vector<Vertex>로 선언한다. 

private: 
// Geometry
vector<Vertex> _vertices;
ComPtr<ID3D11Buffer> _vertexBuffer = nullptr;

 

그럼 CreateGeometry에서는 가장 먼저 무엇을 해야 할까? 

void Game::CreateGeometry()
{
	// VertexData
	{
		_vertices.resize(3);

		_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.f, 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);
	}
}

어떻게 삼각형을 묘사할지를 데이터를 만들어 준 것이다. 
이 데이터는 아직 까지 CPU의 RAM에 있다.  GPU쪽 VRAM에도 똑같은 정보를 만들어 줘야 한다.

void Game::CreateGeometry()
{
// VertexData - CPU 메모리에 있는 거 
{
_vertices.resize(3);

_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.f, 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);
}

// VertexBuffer
{
D3D11_BUFFER_DESC desc; 
ZeroMemory(&desc, sizeof(desc)); 
desc.Usage = D3D11_USAGE_IMMUTABLE; 
// https://learn.microsoft.com/ko-kr/windows/win32/api/d3d11/ne-d3d11-d3d11_usage
//CPU랑 GPU가 어떻게 얘를 가지고 작업을 할지 
//여기선 초기 세팅만 하면 고칠 일 없어서 IMMUTABLE로 
desc.BindFlags = D3D11_BIND_VERTEX_BUFFER; 
// Input assembler에서 건내 주는 vertex buffer를 만들고 있는 것이기 때문
desc.ByteWidth = (uint32)(sizeof(Vertex) * _vertices.size()); 

D3D11_SUBRESOURCE_DATA data; 
ZeroMemory(&data, sizeof(data)); 
data.pSysMem = _vertices.data(); // &_vertices[0];와 같은 의미

_device->CreateBuffer(&desc, &data, _vertexBuffer.GetAddressOf()); 
// 설정한 값 desc, data에 의해가지고 GPU 쪽에 버퍼가 만들어 지면서 
// CPU의 메모리에서 들고 있었던 vertices에 관한 정보가 복사가 되어 넘어 간다. 
// 그 다음 부터는 GPU의 메모리만 Read Only로 사용하겠구나 예측이 가능하다.  
}
}

 

이렇게 정점 버퍼가 _vertexBuffer에 만들어 졌다. 
여기서 한 게  삼각형의 구조(VertexData)를 그려 보았고, vertexBuffer를 만들어서 GPU에 건내주는 역할까지 했다. 
15%왔다. 

2. CreateInputLayout에서 VertexBuffer를 Input Assembler에 넣을 때 GPU에게 어떻게 분석해서 끊어 읽을지 알려주기

void CreateInputLayout(); 을 만들어 준다.
렌더링 파이프라인에서 Vertex Buffer를 Input Assembler에 넣어줄 건데, 이 정보가 어떻게 되어 있는지를 묘사를 해줘야 한다.
GPU에서 봤을 때는 아직까지는 데이터 쪼가리다. 어떻게 분석해서 어떻게 끊어 읽어야 하는지 알려달라 해가지고, 그걸 하는 거다.

void Game::CreateInputLayout()
{
D3D11_INPUT_ELEMENT_DESC layout[] =
{
{"POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0},
{"COLOR", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0}, 
// 12바이트 부터 컬러가 시작 offset
};

const int32 count = sizeof(layout) / sizeof(D3D11_INPUT_ELEMENT_DESC);
// _device->CreateInputLayout(layout, count, ); 
// 세번째 인자로 Shader에 대한 정보를 받아주고 있어. 
// Shader를 먼저 만들어서 로드를 해야겠구나 알 수 있다.
}

 

흐름상으로는 얘 묘사하는 게 맞는데 _device->CreateInputLayout의 세번째 인자를 넣으려면 셰이더를 맞춰 줘야 하기 때문에 셰이더 부터 만들어 주고 온다. 

 

3. Default.hlsl에서 Vertex shader, Pixel shader 만들기

셰이더란 무엇이냐? 
렌더링 파이프라인에서 VertexShader, PixelShader 이 2개가 가장 대표적인데 이걸 프로그래밍적으로 코딩을 할 수 있다고 했었어. 
GPU에게 어떤 일을 해라 일감 자체를 HLSL 이라는 쉐이더 문법으로 만들어서 건내줄 것인데 그 부분을 먼저 만들어야 한다. 

SourceFiles에 98. Shaders라는 필터를 만든다. 
우클릭 new item의  HLSL의 Vertex Shader File(꼭지점 셰이더)을 선택하고, Default.hlsl로 이름을 정한다. 
셰이더는 사용 방법이 2가지가 있다. 
컴파일 하면 결과물이 CSO라는 파일로 만들어진다. 빌드를 해서 결과물이 만들어지게 되는데 결과물을 바로 로드해서 사용하는 경우가 있겠고, 프로그램을 시작하는 순간에 컴파일을 한 다음에 동적으로 그걸 들고 가는 경우가 있다. 
실행할 때 마다 다시 컴파일 하면 그것도 셰이더가 많아지면 부하가 되니까 만들어진 걸 사용하는게 좀 더 낫긴 한데, 여기선 그냥 진행해보자. 

프로젝트 우클릭 속성에 가서 보면 HLSL Compliler라는 항목이 생겼다. 원래 없었지만 HLSL이라는 셰이더 파일 만들었기 때문에 생긴 것이다.

컴파일해서 CSO파일이 만들어지면 그것도 그것대로 사용하고, 동적으로 실행이 될 때 로드하는 방법으로도 사용해서 2중으로 사용할 것이다. 이렇게 하는 이유는 Default.hlsl빌드하는걸 체크하지 않으면 오타를 내거나 문법적인 오류를 만들었을 때 컴파일 타임에 잡아주지 않고 나중에 실행할 때 "로드 실패했습니다"라고 밖에 뜨지 않기 때문에 오류를 찾기가 어려워지기 때문이다.

지금은 Default.hlsl을 버텍스 셰이더로 사용하겠다라고 설정을 해서 지금 이렇게 딱 하나만 들고 있는데, vertex shader랑 pixel shader에서 사용하는 두개로 나눠도 되는데, 한 파일에 적어 넣는게 더 합리적인 경우도 많다. 

 

float4 main( float4 pos : POSITION ) : SV_POSITION
{
return pos;
}

이렇게만 되어 있었는데 처음부터 만들어 보자. 
일단 버텍스 셰이더에 들어오는 구조체를 하나 만들어 보자. C++이랑 비슷해서 읽힌다. 

struct VS_INPUT
{ 
    float4 position : POSITION; 
    float4 color : COLOR; 
};

struct VS_OUTPUT
{
    float4 position : SV_POSITION; 
    float4 color : COLOR;
};

 

VS_INPUT에서 position이 float4인 이유는 나중에 알 수 있다. 

: POSITION, :COLOR, :SV_POSITION은 입력 데이터에서 이 구성원이 어떻게 사용될 것인지를 나타내는 HLSL 세마틱(semantic)이다..

Vertex shader도 하나의 함수처럼 생각하면 된다. INPUT이랑 OUTPUT을 각각 정의를 해줄 것이다. 
OUTPUT에서 float4 position : SV_POSITION; 이렇게 SV_(시스템 밸류)를 붙인 건 SV_가 무조건 하나는 필수로 있어야 하기 때문에 이름을 이렇게 바꿔 준 것이다.

SV_POSITION는 픽셀 셰이더로 넘겨질 버텍스의 최종 클립 공간 위치를 나타낸다. 래스터라이저 단계에서 이 값을 사용하여 화면 공간 내의 픽셀로 변환하고, 그 결과로 해당 버텍스가 어디에 그려질지 결정한다.

 

그리고 VS 함수를 하나 만든다. 

// IA-VS-RS-PS-OM
// 위치와 관련된 변화
VS_OUTPUT VS(VS_INPUT input)
{ 
    // 행렬을 이용해서 막 계산 해야 하지만 지금은 일단 그대로 토스해보자.
    VS_OUTPUT output; 
    output.position = input.position; 
    output.color = input.color; 
    // 여기까지 VS
    // Rasterizer 단계로 넘어가는 건 보간하는 작업. 삼각형 안에 있는 애들만 걸러주는 거라고 보면 된다. 
    // 점점 각각의 색상이 다르다면 중간의 색깔 어떻게 보간할지 성정할 수 있어. 기본적으론 섞어서 보간. 
    // Vertex를 받아서 Rasterizer에서 처리해서 Pixel shader로 넘기게 된다. 
    // Vertex Shader가 실행이 되면 알아서 RS가 실행이 되고 PS영역으로 넘어가게 된다.   
    
    return output; 
}

 

PS 영역도 함수를 만들어 주면 된다.

// 모든 픽셀 단위에 실행되는 함수 
// 조명과 관련된 연산을 적어서 색상을 만들어주면 된다. 
// 색상과 관련된 변화
float4 PS(VS_OUTPUT input) : SV_Target
{    
    return float4(1, 0, 0, 0); // 빨간색으로 처리했다 가정
}

 

빌드를 해보면 'main' entrypoint not found라는 오류가 뜬다. 
Default.hlsl의 속성에 들어가서 보면
HLSL Compiler의 General에서 Shader type은 vertex shader로 
shader 모델은 5.0으로 
Entrypoint Name은 main으로 되어 있는데 main함수가 없으니 VS로 바꿔주면 된다.

 

이제 빌드 하면 에러가 없어질 것이다. 방금처럼 에러를 잡아주는게 편리하다. 그래서 컴파일 하는 버전을 사용한다.
Output 메시지를 보면 
1>compilation object save succeeded; see C:\Users\JangShinyoung\Documents\DirectX11Game\GameCoding\Binaries\Default.cso
Default.cso가 만들어 진 것을 볼 수 있다. 나중엔 이 결과물만 실시간으로 로딩해서 사용하는 식으로 하는 것도 괜찮다. 하지만 지금 단계에서는 시작하자마자 셰이더 파일을 로드해서 사용하는 식으로 만들어 볼 것이다.

 

4. 셰이더 파일을 로드하는 LoadShaderFromFile을 이용해 Blob에 저장하고, GPU에 건낼 수 있는 VS와 PS를 Blob을 이용해 만들기

셰이더를 로드해서 저장을 해야 하는데 ID3DBlob이라는 애로 저장을 하게 된다. 
이제 

1. 셰이더를 로드하는 부분 

2. VS, PS를 만드는 부분

이렇게 두단계가 들어간다.
Game.h에 

// VS
ComPtr<ID3D11VertexShader> _vertexShader = nullptr; 
ComPtr<ID3DBlob> _vsBlob = nullptr; 

// PS
ComPtr<ID3D11PixelShader> _pixelShader = nullptr; 
ComPtr<ID3DBlob> _psBlob = nullptr;

이렇게 선언하고, 

이제 파일을 로드해서 만들어야 한다.
Game.h에 
void LoadShaderFromFile(const wstring& path, const string& name, const string& version, ComPtr<ID3DBlob>& blob); 
선언을 하고,

pch.h에 

#include <string>

를 추가하고,

Game.cpp에 정의한다. 

void Game::LoadShaderFromFile(const wstring& path, const string& name, const string& version, ComPtr<ID3DBlob>& blob)
{
const uint32 compileFlag = D3DCOMPILE_DEBUG | D3DCOMPILE_SKIP_OPTIMIZATION; 

// pch.h에서 d3dcompliler.h를 include했기에 지원이 되는 함수 
HRESULT hr = ::D3DCompileFromFile(
path.c_str(),
nullptr,
D3D_COMPILE_STANDARD_FILE_INCLUDE,
name.c_str(),
version.c_str(),
compileFlag,
0,
blob.GetAddressOf(),
nullptr); 

CHECK(hr); 
}

이걸 범용적으로 사용을 하면 된다. 

이제 당장 필요한게  
void CreateVS(); 
void CreatePS(); 
파일로 존재 하던거를 로드하면 메모리에 들고 있는 것이기 때문에, GPU에게 건내줘야 하는데 이거를 로드하는 작업을 해 줄 것이다.

// 셰이더를 로드해서 Blob이라는 걸 만들어준 다음에 그 Blob에 있는 정보들을 이용해서 
// Vertex shader를 만들어주면 최종적으로 완료가 되면 _vertexShader가 채워진다. 
void Game::CreateVS()
{
LoadShaderFromFile(L"Default.hlsl", "VS", "vs_5_0", _vsBlob); // _vsBlob이 채워지게 된다. 

HRESULT hr = _device->CreateVertexShader(_vsBlob->GetBufferPointer(),
_vsBlob->GetBufferSize(), nullptr, _vertexShader.GetAddressOf()); 
CHECK(hr); 
}

void Game::CreatePS()
{
LoadShaderFromFile(L"Default.hlsl", "PS", "ps_5_0", _psBlob); // _psBlob이 채워지게 된다. 

HRESULT hr = _device->CreatePixelShader(_psBlob->GetBufferPointer(),
_psBlob->GetBufferSize(), nullptr, _pixelShader.GetAddressOf());
CHECK(hr);
}

 

5. VS를 이용하여 CreateInputLayout 함수 완성하고, GPU에 넘길 Vertex의 구조를 묘사한 내용을 InputLayout 변수에 채우기

vertexShader와 pixelShader가 만들어 졌다면 이걸 가지고, 아까 하던 CreateInputLayout의 인자를 채운다.


InputLayout이란 VS에서 넘겨 받은 input의  

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


요 아이들에 대한 묘사를 해야 하는 것이기 떄문에, pixelShader와 상관 없고, vertexShader 즉 _vsBlob에 대한 정보만 넣어주면 된다. 

 

_device->CreateInputLayout(layout, count, _vsBlob->GetBufferPointer(), _vsBlob->GetBufferSize(), );


이렇게 넣어 주고, 마지막 인자는 InputLayout의 변수의 GetAddressOf로 얻은 주소에 결과물을 넣어주면된다. 

Game.h에 가서 InputLayout 변수를 선언한다. 

  ComPtr<ID3D11InputLayout> _inputLayout = nullptr;


이 InputLayout은 넘겨주는 Vertex의 구조를 묘사하는 애라고 했어. 그걸 CreateInputLayout의 마지막 인자로 받아주면 된다. 

void Game::CreateInputLayout()
{
	D3D11_INPUT_ELEMENT_DESC layout[] =
	{
		{"POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0},
		{"COLOR", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0}, 
	};

	const int32 count = sizeof(layout) / sizeof(D3D11_INPUT_ELEMENT_DESC);
	_device->CreateInputLayout(layout, count, 
        	_vsBlob->GetBufferPointer(), _vsBlob->GetBufferSize(), _inputLayout.GetAddressOf());  
}


함수가 너무 많아서 정신을 못차릴 수 있기는 한데, 원리만 놓고 보면
Init에 돌아가서 
CreateGeometry(); 를 해서 먼저 삼각형의 기하학 도형을 만들었고, 
CreateVS();  CreatePS(); 를 해서 각각의 셰이더를 로드한 다음에 
그 사이에  CreateInputLayout(); 를 해서, VS단계에서 건내줘야 하는 구조체의 생김새 자체(정의 자체)를 레이아웃으로 만들어 줬다고 볼 수 있다. 
이렇게 _vertexBuffer, _inputLayout, _vertexShader, _vsBlob, _pixelShader, _psBlob을 다 만들어 줬다. 

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

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

CreateGeometry(); 
CreateVS(); 
CreateInputLayout(); 
CreatePS(); 
}


Init으로 가서 함수들을 호출하고, 일단 컴파일을 해본다.

지금은 아직 렌더링 파이프라인에 묵어주지 않았기 때문에 일단은 Shader가 로드가 되는지만 살펴볼 것이다. 실행해서 별 다른 문제가 없으면 되는 거. 
Shader를 로드 하는 거 까진 성공 했다는 거다. CreatePS에서 CHECK에 브레이크 포인트 잡아서 확인할 수도 있다. 

쉐이더를 읽어서 컴파일해서 들고 있는 거 까지 성공했다는 거. 

 

6. _vertexBuffer, _inputLayout, _vertexShader, _pixelShader를 GPU에 연결하고 실행하기

void CreateGeometry(); 기하학 적인 도형을 만들었고
void CreateInputLayout(); 도형에 대한 설명서를 작성했고
void CreateVS();  GPU에게 시킬 일들을 셰이더라는 애로 만들어 놨으니
void CreatePS(); 
최종적으로 이걸 다 연결해서준비를 해주면 된다. 

Render에서 RenderBegin, End는 공용으로 하는 것이고, 
물체마다 렌더링 할 때 셰이더 리소스 라거나 연결을 해줘야 하는데 이 부분을 작성한다고 보면 된다. 

void Game::Render()
{
RenderBegin(); 

// IA - VS - RS - PS - OM
{
uint32 stride = sizeof(Vertex); 
uint32 offset = 0; 

// IA
// 코딩하는게 아니라 세팅하는 거
_deviceContext->IASetVertexBuffers(0, 1, _vertexBuffer.GetAddressOf(), &stride, &offset); 
_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); 

// OM

_deviceContext->Draw(_vertices.size(), 0); 
}

RenderEnd(); 
}


실행하면 삼각형이 잘 뜬다. 


지금은 Default.hlsl의 PS에서 return 값의 색을 빨강으로 지정해서 색이 이렇게 나오는데 
만약 VertexShader의 색 그대로 나오게 하고 싶다면

float4 PS(VS_OUTPUT input) : SV_Target
{        
    return input.color; // 빨간색으로 처리했다 가정
}

이렇게 하는 것도 하나의 방법이다. 

CreateGeometry에서 

void Game::CreateGeometry()
{
// VertexData - CPU 메모리에 있는 거 
{
_vertices.resize(3);

_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.f, 0.5f, 0.f);
_vertices[1].color = Color(0.f, 1.f, 0.f, 1.f);

_vertices[2].position = Vec3(0.5f, -0.5f, 0.f);
_vertices[2].color = Color(0.f, 0.f, 1.f, 1.f);
}


이런식으로 vertex의 색을 하나는 초록색 하나는 파랑색으로 하면 그라데이션이 일어난다. 


이 그라데이션을 해주는 단계는 어딜까 ?
Rasterizer 단계

 

7. 정리

요약을 하면 삼각형을 한번에 띄웠다. 
셰이더는 디버그가 안되기 때문에 하나 실수 하면 찾기가 어렵다. 

중요한 건 이게 완성 됐다로 끝내는 게 아니라 어떻게 완성 되었는지를 계속 복기를 해야 한다. 
DirectX렌더링 파이프 라인을 보면서 계속 생각을 해야 한다. 

맨 먼저 정점을 만들었다. 
원래 CPU 메모리에서 갖고 있었는데 GPU쪽 VertexBuffer를 만들어 줬다. 리소스가 GPU쪽에 복사 된 거다. 
그 다음에 IA 단계에서 IASetVertexBuffer를 이용해 꽂아 주고, 
VertexShader에 넘어가는데, 지정하는 단계도 쉽지 않았어. 결과적으로 VS함수가 실행이 된다. 세 정점을 대상으로 VS 함수가 실행이 되는데 주체가 GPU다. 
결국 정점에 대한 연산할 거 VS에 넣어줘야 하는데 좌표계 변환을 VS에서 처리하게 된다. 
나중에 애니까지 들어갈 수 있어. 카메라 위치에 따라 좌표가 변환되는 거 등 공식을 넣어줄 거다. 
그 정점이 fix가 되어 return이 될 것이다.
그 다음에 테셀레이션 단계인데 지형 같은 거 할 때 삼각형 늘리고 그런 작업들이야. 그건 일단 무시하고, 
Rasterizer 단계로 넘어가게 된다. 
이게 결국 삼각형 있을 때 보정해서 내부의 무언가를 설정하는게 Rasterizer 단계다.
삼각형 안에 모든 픽셀들 대상으로 Pixel shder가 실행이 되는데, 지금은 PS에서 return input.Color만 했는데 그라데이션이 일어난게 신기하다. PS어딘가에 중간 색이 뜬다는 건데, 세 점은 빨초파인 어느새 노락색이 포한 된 것일까? Rasterizer 단계에서 모든 픽셀들 대상으로 다시 계산을 한 거다. 그 계산 된 걸 PS에 어떤 색상 고를지 공식으로 넣어준다. 빛 연산에 따라 달라진다.

VS, PS 를 어떻게 짜느냐에 따라 온갖 거를 할 수 있다. 

PS, VS가 빛공식과 물체, 사물에 대한 변화를 묘사하는 설계도라고 볼 수 있다. 
여기에 세부적으로 옵션을 건드릴 수 있게끔 툴로 만들어주게 되면 그게 게임 엔진에서 말하는 Material이다. 
Shader와 옵션들 새부적 설정들 묶어서 건내주는 거라고 할 수 있다. 원리는 이렇게 동작한다. 

RenderTarget은 최종 결과 나왔을 때 어디에 그려줘 하는 거다. 렌더 타겟도 조작할 수 있다. 텍스쳐에 저장해줘 하면, CCTV 기능 같은 거 만들 수 있다. 

결론은 이게 기초인데 이걸 가지고 장난을 칠 것이다.

 

반응형

'DirectX' 카테고리의 다른 글

6. ConstantBuffer  (0) 2023.12.13
5. 텍스쳐와 UV  (0) 2023.12.13
3. 장치 초기화  (0) 2023.12.06
2. 기본 프레임워크  (0) 2023.12.02
1. 렌더링 OT  (0) 2023.12.01

댓글