• 티스토리 홈
  • 프로필사진
    유니얼
  • 방명록
  • 공지사항
  • 태그
  • 블로그 관리
  • 글 작성
유니얼
  • 프로필사진
    유니얼
    • 분류 전체보기 (295)
      • Unity (17)
        • 게임 개발 (5)
      • Unreal (24)
        • 게임 개발 (20)
      • DirectX (36)
      • 코딩테스트 (91)
        • 프로그래머스 (25)
        • 백준 (66)
      • Google Workspace (1)
      • Programing (102)
        • C# (68)
        • C++ (24)
        • JavaScript (10)
      • 게임 서버 프로그래밍 (17)
      • Web (6)
        • 슈퍼코딩 (6)
  • 방문자 수
    • 전체:
    • 오늘:
    • 어제:
  • 최근 댓글
    등록된 댓글이 없습니다.
  • 최근 공지
    등록된 공지가 없습니다.
# Home
# 공지사항
#
# 태그
# 검색결과
# 방명록
  • [DirectX11] Constant Buffer
    2024년 02월 07일
    • 유니얼
    • 작성자
    • 2024.02.07.:05
    728x90

    DirectX 11로 게임 엔진 아키텍처 만들기

    이 블로그 글은 DirectX 11과 그래픽스 프로그래밍 학습 과정을 공유하며, 데이터를 효율적으로 쉐이더에 전달하는 방법 중 하나인 Constant Buffer에 대해 정리하고자 합니다. Constant Buffer를 활용하여 유니티 로고 이미지가 화면에서 이동하는 간단한 시나리오를 구현해보면서 얻은 지식을 바탕으로 해당 내용을 정리하고, 중요한 개념을 추가하여 설명해보겠습니다.

     

    MoveLogo

    참고강의 링크:

    https://www.inflearn.com/course/directx11-%EA%B2%8C%EC%9E%84%EA%B0%9C%EB%B0%9C-%EB%8F%84%EC%95%BD%EB%B0%98/dashboard

     

    [게임 프로그래머 도약반] DirectX11 입문 강의 - 인프런

    게임 프로그래머 공부에 있어서 필수적인 DirectX 11 지식을 초보자들의 눈높이에 맞춰 설명하는 강의입니다., [사진][사진] [사진] 게임 개발자는 Unreal, Unity만 사용할 줄 알면 되는 거 아닌가요? 엔

    www.inflearn.com

    Constant Buffer란?

    Constant Buffer는 DirectX 11에서 쉐이더에 상수 데이터를 전달하기 위해 사용되는 버퍼입니다. 이 버퍼는 주로 변하지 않는 데이터(예: 변환 행렬, 조명 정보 등)를 저장하는 데 사용되며, 한 번 설정하면 여러 쉐이더에서 재사용할 수 있어 효율적인 데이터 관리가 가능합니다.

    Constant Buffer의 장점

    1. 효율성: Constant Buffer를 사용하면 한 번에 많은 양의 데이터를 GPU에 전달할 수 있어, 데이터 전송에 필요한 API 호출 수를 줄일 수 있습니다. 이는 CPU와 GPU 사이의 통신 오버헤드를 최소화하는 데 도움이 됩니다.
    2. 조직성: 관련된 데이터를 하나의 버퍼에 그룹화함으로써 셰이더 코드의 가독성과 유지 보수성이 향상됩니다.

    1. Constant Buffer 정의

    먼저, 이동 정보를 담을 구조체 TransformData를 정의합니다. 여기서 offset은 유니티 로고의 이동 방향과 거리를 정의합니다.

    struct TransformData {
        Vec3 offset;
        float dummy; // 패딩을 위한 더미 변수
    };

    2. Constant Buffer 생성

    TransformData 구조체를 기반으로 Constant Buffer를 생성합니다. D3D11_USAGE_DYNAMIC을 사용하여 CPU에서 버퍼를 동적으로 업데이트할 수 있도록 설정합니다.

    void Game::CreateConstantBuffer() {
        D3D11_BUFFER_DESC desc;
        ZeroMemory(&desc, sizeof(desc));
        desc.Usage = D3D11_USAGE_DYNAMIC; // CPU에서 쓰기, GPU에서 읽기 가능
        desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
        desc.ByteWidth = sizeof(TransformData); // 구조체 크기만큼 할당
        desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; // CPU 접근 권한 설정
    
        HRESULT hr = _device->CreateBuffer(&desc, nullptr, &_constantBuffer.GetAddressOf());
    	CHECK(hr);
    }

    3. Constant Buffer 업데이트

    게임의 메인 루프에서 로고의 위치를 업데이트하는 Update 함수를 구현합니다. 여기서는 간단하게 offset 값을 변경하여 로고를 이동시킵니다.

    void Game::Update() {
        _transformData.offset.x += 0.003f; // x축 방향으로 이동
        _transformData.offset.y += 0.003f; // y축 방향으로 이동
    
        D3D11_MAPPED_SUBRESOURCE subResource;
        _deviceContext->Map(_constantBuffer.Get(), 0, D3D11_MAP_WRITE_DISCARD, 0, &subResource);
        ::memcpy(subResource.pData, &_transformData, sizeof(_transformData));
        _deviceContext->Unmap(_constantBuffer.Get(), 0);
    }

    4. 렌더링

    Render 함수에서는 Constant Buffer를 사용하여 쉐이더에 데이터를 전달합니다. 이 예제에서는 정점 쉐이더(VS)에서 로고의 위치를 변경하는 데 사용됩니다.

    void Game::Render() // 렌더링 함수 구현
    {
    	RenderBegin(); // 렌더링 시작 전 설정
    
    	// 렌더링 할 내용 TODO: 실제 렌더링 로직 추가
    	//IA - VS - RS - PS - OM
    	{
    		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);
    		_deviceContext->VSSetConstantBuffers(0, 1, _constantBuffer.GetAddressOf());
    		//RS
    
    		// 픽셀 쉐이더(PS) 스테이지 설정
    		_deviceContext->PSSetShader(_pixelShader.Get(), nullptr, 0);
    		_deviceContext->PSSetShaderResources(0, 1, _shaderResourceView.GetAddressOf());
    		_deviceContext->PSSetShaderResources(1, 1, _shaderResourceView2.GetAddressOf());
    
    		// 출력 병합(OM) 스테이지 설정
    		//_deviceContext->Draw(_vertices.size(), 0); // 정점들을 그림
    		_deviceContext->DrawIndexed(_indices.size(), 0, 0);
    	}
    
    
    	RenderEnd(); // 렌더링 후 처리
    }

    5. 쉐이더 구현

    정점 쉐이더에서는 Constant Buffer로부터 offset 값을 받아 로고의 위치를 조정합니다.

    cbuffer TransformData : register(b0) {
    	float4 offset;
    }
    
    //VS => Vertex Shader
    //IA - VS - RS - PS - OM
    VS_OUTPUT VS(VS_INPUT input) {
    	VS_OUTPUT output; // 출력 구조체 초기화
    
    	output.position = input.position + offset;  // 로고의 위치 조정
    	//output.color = input.color; // 입력 색상을 출력 색상으로 전달
    	output.uv= input.uv; // 입력 색상을 출력 색상으로 전달
    
    	return output; // 변환된 출력 반환
    }

    결론

    DirectX 11의 Constant Buffer를 사용하는 과정은 고성능 그래픽스 애플리케이션 개발의 핵심 요소로, 예제 코드를 통해 변환 데이터 같은 정보를 쉐이더에 효율적으로 전달하는 방법을 보여줍니다. 이는 CPU와 GPU 간의 데이터 전송을 최적화하고, 쉐이더 프로그램의 유연성을 높이며, 복잡한 그래픽 효과와 애니메이션 구현을 용이하게 합니다.

    반응형
    다음글
    다음 글이 없습니다.
    이전글
    이전 글이 없습니다.
    댓글
조회된 결과가 없습니다.
스킨 업데이트 안내
현재 이용하고 계신 스킨의 버전보다 더 높은 최신 버전이 감지 되었습니다. 최신버전 스킨 파일을 다운로드 받을 수 있는 페이지로 이동하시겠습니까?
("아니오" 를 선택할 시 30일 동안 최신 버전이 감지되어도 모달 창이 표시되지 않습니다.)
목차
표시할 목차가 없습니다.
    • 안녕하세요
    • 감사해요
    • 잘있어요

    티스토리툴바