4. 삼각형 그리기

MwG·2024년 11월 14일

DirectX11

목록 보기
4/7

1. 삼각형 정점 세팅

renderer::vertexes[0].pos = Vector3(0.f, 0.5f, 0.0f); 
renderer::vertexes[0].color = Vector4(0.0f, 1.0f, 0.0f, 1.0f);

renderer::vertexes[1].pos = Vector3(0.5f, -0.5f, 0.0f);
renderer::vertexes[1].color = Vector4(1.0f, 0.0f, 0.0f, 1.0f);

renderer::vertexes[2].pos = Vector3(-0.5f, -0.5f, 0.0f);
renderer::vertexes[2].color = Vector4(0.0f, 0.0f, 1.0f, 1.0f);

pos에는 x,y,z 좌표값을 설정해주고 color에는 rgba값을 설정해준다.
이때 정점의 순서를 잘 맞추는 것이 중요하다.
만약 0,1,2순이 아니라 1,0,2순이면 출력했을 때 보이지 않을 수도 있다.
기본적으로 시계방향으로 할경우 z축이 화면 밖으로 나오는 방향
반시계 방향으로 할 경우 z축이 화면안으로 들어가는 방향인데
directx가 왼손 좌표계를 사용하기 때문이다.
**openGL은 오른손 좌표계

2. 셰이더 생성

		DWORD shaderFlags = D3DCOMPILE_ENABLE_STRICTNESS;
		shaderFlags |= D3DCOMPILE_DEBUG;
		shaderFlags |= D3DCOMPILE_SKIP_OPTIMIZATION;

셰이더 플래그 생성

2-1. 정점 셰이더

ID3DBlob* errorBlob = nullptr;
D3DCompileFromFile(L"..\\Shaders_SOURCE\\TriangleVS.hlsl", nullptr, D3D_COMPILE_STANDARD_FILE_INCLUDE
							, "main","vs_5_0",shaderFlags,0,&renderer::vsBlob, &errorBlob);

mDevice->CreateVertexShader(renderer::vsBlob->GetBufferPointer(),
	renderer::vsBlob->GetBufferSize(),nullptr, &renderer::vsShader);

2-2. 픽셀 셰이더

ID3DBlob* errorBlob = nullptr;
			D3DCompileFromFile(L"..\\Shaders_SOURCE\\TrianglePS.hlsl", nullptr, D3D_COMPILE_STANDARD_FILE_INCLUDE
										, "main","ps_5_0",shaderFlags,0,&renderer::psBlob, &errorBlob);

			mDevice->CreatePixelShader(renderer::psBlob->GetBufferPointer()
				, renderer::psBlob->GetBufferSize(), nullptr, &renderer::psShader);

셰이더 오브젝트


HLSL(고급 셰이더 언어) **openGL은 GLSL이다.
셰이더 코드를 바이트 코드로 컴파일 한 후 바이트 코드를 가지고 셰이더 오브젝트 인터페이스를 만든다.

셰이더를 생성하는 함수의 세 가지 인자는 바이트 코드의 포인터, 해당 사이즈, ClassLinkage 포인터 등이 있다.

ID3DBlob(Blob:큰 데이터의 집합)인터페이스를 사용하여 컴파일된 바이트코드를 담아둬야함.

셰이더 컴파일 코드

//셰이더 컴파일 옵션

#if defined(DEBUG) || defined(_DEBUG)
UINT g_flagCompile = D3D10_SHADER_DEBUG | D3D10_SHADER_SKIP_OPTIMIZATION
                    | D3D10_SHADER_ENABLE_STRICTNESS | D3D10_SHADER_PACK_MATRIX_COLUMN_MAJOR;
#else
UINT g_flagCompile = D3D10_SHADER_ENABLE_STRICTNESS | D3D10_SHADER_PACK_MATRIX_COLUMN_MAJOR;
#endif

    // 버텍스 셰이더 코드 컴파일
    ID3DBlob* pBlobVS = NULL;
    hr = D3DX11CompileFromFile(```

            L" Tutorial02.fx ",  // 파일명

            NULL,          // 매크로정의(없음)
            NULL,          // 인클루드 파일 정의(없음)
            "VS",          //  해당 셰이더의 메인 함수 이름
            "vs_4_0",      // 버텍스 셰이더로 컴파일 (버전 4.0)
            g_flagCompile, // 컴파일 옵션
            0,             // 이펙트 컴파일 옵션(없음)
            NULL,          // 바로 컴파일하고 나서 함수를 뺀다。
            &pBlobVS,      // 컴파일된 바이트 코드
            NULL,          // 에러 메시지는 필요없음
            NULL);         // 반환값

D3D10_SHADER_DEBUG : 디버그 정보 포함
D3D10_SHADER_SKIP_OPTIMIZATION :최적화를 수행하지 않는다
D3D10_SHADER_ENABLE_STRICTNESS :구식문법을 엄밀히 체크해서 금지한다(디폴트는 체크하지 않음)
D3D10_SHADER_PACK_MATRIX_COLUMN_MAJOR : 을명시적으로 지정하지 않는한 셰이더의 행렬입출력을 열 우선으로한다

셰이더 오브젝트를 생성 후 각 파이프 라인에 설정

mContext->VSSetShader(renderer::vsShader, 0, 0);
mContext->PSSetShader(renderer::psShader, 0, 0);

3. 정점 정보를 InputAssembler로 생성

// Input layout 정점 구조 정보
D3D11_INPUT_ELEMENT_DESC inputLayoutDesces[2] = {};

inputLayoutDesces[0].AlignedByteOffset = 0;
inputLayoutDesces[0].Format = DXGI_FORMAT_R32G32B32_FLOAT;
inputLayoutDesces[0].InputSlot = 0;
inputLayoutDesces[0].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA;
inputLayoutDesces[0].SemanticName = "POSITION";
inputLayoutDesces[0].SemanticIndex = 0;

inputLayoutDesces[1].AlignedByteOffset = 12;
inputLayoutDesces[1].Format = DXGI_FORMAT_R32G32B32A32_FLOAT;
inputLayoutDesces[1].InputSlot = 0;
inputLayoutDesces[1].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA;
inputLayoutDesces[1].SemanticName = "COLOR";
inputLayoutDesces[1].SemanticIndex = 0;

mDevice->CreateInputLayout(inputLayoutDesces, 2
	, renderer::vsBlob->GetBufferPointer()
	, renderer::vsBlob->GetBufferSize()
	, &renderer::inputLayouts);


Input Assembler란?
입력 어셈블러 스테이지(input Assembler [IA]) 는 렌더링 파이프라인의 젤 처음 스테이지이자 어플리케이션으로 부터 넘겨 받은 버텍스 버퍼나 인덱스 버퍼의 데이터를 읽어 들여 [점][선][면]등의 정보를 조합하여 파이프라인의 다음 스테이지로 데이터를 흘려보내는 역할을 한다.

그밖의 셰이더에서 처리에 필요한 [시스템 생성값] 들을 추가 할수도 있다.
[시스템 생성값]은 다른 입출력 Element와 마찬가지로 [시멘틱스] 를 붙여 식별하며 입력 어셈블러가 생성하는 생성값에는
버텍스ID, 프리미티브ID, 인스턴스ID등이 있다.

버텍스 버퍼(vertex buffer)

인덱스 버퍼는 데이터의 순서를 정하는데 만약 쓰지않을 경우 버텍스 데이터 순으로 사용된다.

4. 정점 정보를 GPU에 넘기기

buffer를 통해서 넘긴다.

// System -> GPU
D3D11_BUFFER_DESC bufferDesc = {};

		bufferDesc.ByteWidth = sizeof(renderer::Vertex) * 3;
		bufferDesc.BindFlags = D3D11_BIND_FLAG::D3D11_BIND_VERTEX_BUFFER;
		bufferDesc.Usage = D3D11_USAGE::D3D11_USAGE_DYNAMIC;
		bufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_FLAG::D3D11_CPU_ACCESS_WRITE;
		
		//xyz
		//rgba
		renderer::vertexes[0].pos = Vector3(0.f, 0.5f, 0.0f);
		renderer::vertexes[0].color = Vector4(0.0f, 1.0f, 0.0f, 1.0f);

		renderer::vertexes[1].pos = Vector3(0.5f, -0.5f, 0.0f);
		renderer::vertexes[1].color = Vector4(1.0f, 0.0f, 0.0f, 1.0f);

		renderer::vertexes[2].pos = Vector3(-0.5f, -0.5f, 0.0f);
		renderer::vertexes[2].color = Vector4(0.0f, 0.0f, 1.0f, 1.0f);

		D3D11_SUBRESOURCE_DATA sub = { renderer::vertexes };
		//sub.pSysMem = renderer::vertexes;

		mDevice->CreateBuffer(&bufferDesc, &sub, &renderer::vertexBuffer);
        

5. 화면에 출력

void GraphicDevice_DX11::Draw()
	{
		// 화면 지우기
		FLOAT backgroundColor[4] = { 0.2f, 0.2f, 0.2f, 1.0f };
		mContext->ClearRenderTargetView(mRenderTargetView.Get(), backgroundColor);
		mContext->ClearDepthStencilView(mDepthStencilView.Get(), D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1.f, 0);
		
		// 뷰포트 설정 해주기 (클라이언트에 그려질 영역 설정)
		D3D11_VIEWPORT viewPort =
		{
			0, 0, application.GetWidth(), application.GetHeight(),
			0.0f, 1.0f
		};
		mContext->RSSetViewports(1, &viewPort);

		// 렌더타겟 설정(추후 여러개의렌더타겟도 설정 가능하다, 디퍼드렌더링등에서 활용)
		mContext->OMSetRenderTargets(1, mRenderTargetView.GetAddressOf(), mDepthStencilView.Get());
		
		// 인풋레이아웃 설정
		mContext->IASetInputLayout(renderer::inputLayouts);
		mContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY::D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
		
		// 셰이더 설정
		UINT vertexSize = sizeof(renderer::Vertex);
		UINT offset = 0;
		mContext->IASetVertexBuffers(0, 1, &renderer::vertexBuffer, &vertexSize, &offset);

		mContext->VSSetShader(renderer::vsShader, 0, 0);
		mContext->PSSetShader(renderer::psShader, 0, 0);
		

		// 렌더타겟에 물체를 그려준다.
		mContext->Draw(3, 0);

		// 렌더타겟에 있는 이미지를 모니터에 띄어준다.
		mSwapChain->Present(1, 0);
	}

primitive 데이터란?

렌더링이 되는 도형의 최소단위

primitve의 여러 종류이다.

<출처>
얌얌 코딩

0개의 댓글