• 티스토리 홈
  • 프로필사진
    유니얼
  • 방명록
  • 공지사항
  • 태그
  • 블로그 관리
  • 글 작성
유니얼
  • 프로필사진
    유니얼
    • 분류 전체보기 (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] TextureBuffer
    2024년 03월 12일
    • 유니얼
    • 작성자
    • 2024.03.12.:23
    728x90

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

    DirectX11과 같은 고급 그래픽 API를 학습하며 게임 엔진 아키텍처의 구성 요소를 이해하는 것은 게임 개발자에게 필수적인 과정입니다. 이러한 과정을 통해, 개발자들은 복잡한 3D 환경을 생성, 조작, 렌더링하는 데 필요한 다양한 기술과 원리를 배울 수 있습니다. 특히, 효과적인 데이터 관리와 접근 방법을 이해하는 것은 성능 최적화와 높은 품질의 그래픽 출력을 달성하는 데 중요한 역할을 합니다. 이번 블로그 포스팅에서는 DirectX11에서 중요한 데이터 관리 메커니즘 중 하나인 TextureBuffer에 대해 알아보고자 합니다.

     

    Result

    참고강의 링크:

    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

    TextureBuffer 소개

    DirectX11에서 TextureBuffer는 GPU에서의 텍스처 데이터 관리와 접근을 용이하게 하는 중요한 리소스입니다. 이는 텍스처를 통한 복잡한 데이터의 저장과 접근을 가능하게 하며, 그래픽과 컴퓨트 셰이더에서 다양한 형태의 데이터를 활용할 수 있도록 지원합니다. TextureBuffer는 기본적으로 이미지 데이터를 저장하지만, 다양한 형태의 정보를 저장하고 활용하는 데 사용될 수 있습니다.

    TextureBuffer의 특징과 활용

    TextureBuffer는 픽셀 데이터를 다차원 배열로 저장하며, 각 픽셀은 여러 개의 컴포넌트로 구성됩니다. 이러한 구조는 이미지 데이터뿐만 아니라, 다양한 종류의 정보를 효율적으로 저장하고 접근하는 데 유리합니다. 예를 들어, 텍스처 버퍼는 렌더링에 필요한 색상 정보, 노멀 맵, 스페큘러 맵 등 다양한 종류의 텍스처 데이터를 저장할 수 있습니다.

     

    또한, TextureBuffer는 셰이더에서 직접 접근할 수 있으며, GPU의 텍스처 샘플러를 통해 다양한 필터링 방법을 적용하여 데이터를 읽을 수 있습니다. 이는 그래픽 렌더링뿐만 아니라, GPU를 활용한 고급 수치 계산에도 사용될 수 있습니다.

    예제 코드: 텍스처 버퍼의 생성과 사용

    DirectX11에서 RawBuffer를 구현하기 위해서는 ID3D11Buffer 인터페이스를 사용하여 버퍼를 생성하고, 적절한 버퍼 설명자(D3D11_BUFFER_DESC)와 서브리소스 데이터(D3D11_SUBRESOURCE_DATA)를 설정해야 합니다. 다음은 간단한 RawBuffer 생성 예제 코드입니다:

    // 입력 데이터를 저장하는 2D 텍스처 배열
    Texture2DArray<float4> Input;
    // 출력 데이터를 저장할 2D 텍스처 배열로, 읽기와 쓰기가 가능합니다.
    RWTexture2DArray<float4> Output;
    
    // 컴퓨트 셰이더의 각 스레드가 실행할 함수를 정의합니다.
    // numthreads 어트리뷰트는 각 디스패치에서 스레드 그룹의 크기를 지정합니다.
    [numthreads(32, 32, 1)]
    void CS(uint3 id : SV_DispatchThreadID) // 스레드 식별자
    {
    	// 입력 텍스처에서 현재 스레드에 해당하는 픽셀의 색상을 로드합니다.
    	float4 color = Input.Load(int4(id, 0));
    
    	// 아래의 세 가지 방법 중 하나를 선택하여 출력 텍스처에 색상 값을 쓸 수 있습니다.
    
    	// 1. 입력 텍스처의 색상을 그대로 출력 텍스처에 저장합니다.
    	//Output[id] = color;
    
    	// 2. 입력 텍스처의 색상을 반전시켜 출력 텍스처에 저장합니다.
    	Output[id] = 1.0f - color;
    
    	// 3. 입력 텍스처의 색상의 평균 값을 계산하여, 출력 텍스처에 그레이스케일 색상으로 저장합니다.
    	//Output[id] = float4((color.r + color.g + color.b) / 3.0f, (color.r + color.g + color.b) / 3.0f, (color.r + color.g + color.b) / 3.0f, color.a);
    }
    
    // 컴퓨트 셰이더를 사용하는 테크닉을 정의합니다.
    technique11 T0
    {
    	pass P0
    	{
    		// 컴퓨트 셰이더를 제외하고는 버텍스 셰이더나 픽셀 셰이더를 사용하지 않으므로 NULL로 설정합니다.
    		SetVertexShader(NULL);
    		SetPixelShader(NULL);
    		// 컴퓨트 셰이더를 컴파일하여 설정합니다.
    		SetComputeShader(CompileShader(cs_5_0, CS()));
    	}
    };

    이 예제에서는 텍스처 버퍼를 선언하고, 픽셀 셰이더에서 이를 사용하여 텍스처 샘플링을 수행합니다. myTexture는 텍스처 데이터를 저장하는 Texture2D 버퍼이며, mySampler는 텍스처 샘플링 시 적용할 샘플러 상태를 정의합니다. PS 함수는 픽셀 셰이더로, 입력 UV 좌표를 기반으로 텍스처 버퍼에서 색상 값을 샘플링하고 이를 반환합니다.

    TextureBuffer

    TextureBuffer 클래스는 Direct3D 11을 사용하여 텍스처 처리 작업에 필요한 기본적인 구성요소를 제공합니다. TextureBuffer 클래스는 입력 텍스처를 받아 그것을 처리하고 결과를 출력 텍스처로 저장하는 과정을 담당합니다. 이 과정에는 셰이더 리소스 뷰(SRV)와 비순차적 액세스 뷰(UAV) 생성이 포함되며, 이는 GPU에서 텍스처 데이터를 읽고 쓰는 데 사용됩니다.

    TextureBuffer.h

    #pragma once
    
    class TextureBuffer
    {
    public:
    	// 생성자: 원본 텍스처를 인자로 받습니다.
    	TextureBuffer(ComPtr<ID3D11Texture2D> src);
    	// 소멸자: 자원을 해제합니다.
    	~TextureBuffer();
    
    public:
    	// 버퍼를 생성하는 주 함수입니다.
    	void CreateBuffer();
    
    private:
    	// 입력 텍스처를 설정합니다.
    	void CreateInput(ComPtr<ID3D11Texture2D> src);
    	// 입력 텍스처에 대한 셰이더 리소스 뷰(SRV)를 생성합니다.
    	void CreateSRV();
    	// 출력 텍스처를 생성합니다.
    	void CreateOutput();
    	// 출력 텍스처에 대한 비순차적 액세스 뷰(UAV)를 생성합니다.
    	void CreateUAV();
    	// 처리 결과를 저장할 텍스처를 생성합니다.
    	void CreateResult();
    
    public:
    	// 텍스처의 너비, 높이, 배열 크기를 반환하는 접근자 함수들입니다.
    	uint32 GetWidth() { return _width; }
    	uint32 GetHeight() { return _height; }
    	uint32 GetArraySize() { return _arraySize; }
    
    	// 출력 텍스처와 그에 대한 SRV를 반환하는 접근자 함수입니다.
    	ComPtr<ID3D11Texture2D> GetOutput() { return (ID3D11Texture2D*)_output.Get(); }
    	ComPtr<ID3D11ShaderResourceView> GetOutputSRV() { return _outputSRV; }
    
    public:
    	// 입력 및 출력 텍스처에 대한 SRV와 UAV를 반환하는 접근자 함수입니다.
    	ComPtr<ID3D11ShaderResourceView> GetSRV() { return _srv; }
    	ComPtr<ID3D11UnorderedAccessView> GetUAV() { return _uav; }
    
    private:
    	// 입력 및 출력 텍스처와 관련 자원을 저장하는 멤버 변수입니다.
    	ComPtr<ID3D11Texture2D> _input;
    	ComPtr<ID3D11ShaderResourceView> _srv; // 입력 텍스처의 SRV
    	ComPtr<ID3D11Texture2D> _output;
    	ComPtr<ID3D11UnorderedAccessView> _uav; // 출력 텍스처의 UAV
    
    private:
    	// 텍스처의 너비, 높이, 배열 크기 및 포맷을 저장하는 멤버 변수입니다.
    	uint32 _width = 0;
    	uint32 _height = 0;
    	uint32 _arraySize = 0;
    	DXGI_FORMAT _format;
    	ComPtr<ID3D11ShaderResourceView> _outputSRV; // 출력 텍스처의 SRV
    };

    TextureBuffer.cpp

    #include "pch.h" // 프리컴파일 헤더
    #include "TextureBuffer.h" // TextureBuffer 클래스 정의 포함
    
    // 생성자: 소스 텍스처를 받아서 입력 텍스처를 생성하고, 관련 버퍼를 모두 생성합니다.
    TextureBuffer::TextureBuffer(ComPtr<ID3D11Texture2D> src)
    {
    	CreateInput(src); // 입력 텍스처 생성
    	CreateBuffer(); // 나머지 버퍼(SRV, 출력, UAV, 결과) 생성
    }
    
    // 소멸자
    TextureBuffer::~TextureBuffer()
    {
    	// Direct3D 자원 해제는 ComPtr에 의해 자동으로 관리됩니다.
    }
    
    // 전체 버퍼 생성 작업을 수행합니다.
    void TextureBuffer::CreateBuffer()
    {
    	CreateSRV(); // 입력 텍스처에 대한 SRV 생성
    	CreateOutput(); // 출력 텍스처 생성
    	CreateUAV(); // 출력 텍스처에 대한 UAV 생성
    	CreateResult(); // 결과 데이터를 저장할 텍스처 생성 (주로 읽기 전용)
    }
    
    // 입력 텍스처 생성
    void TextureBuffer::CreateInput(ComPtr<ID3D11Texture2D> src)
    {
    	D3D11_TEXTURE2D_DESC srcDesc;
    	src->GetDesc(&srcDesc); // 소스 텍스처의 설명 가져오기
    
    	// 입력 텍스처의 기본 정보를 설정합니다.
    	_width = srcDesc.Width;
    	_height = srcDesc.Height;
    	_arraySize = srcDesc.ArraySize;
    	_format = srcDesc.Format;
    
    	D3D11_TEXTURE2D_DESC desc;
    	ZeroMemory(&desc, sizeof(desc)); // 메모리 초기화
    	desc.Width = _width;
    	desc.Height = _height;
    	desc.ArraySize = _arraySize;
    	desc.Format = _format;
    	desc.BindFlags = D3D11_BIND_SHADER_RESOURCE; // SRV로 사용됨을 명시
    	desc.MipLevels = 1;
    	desc.SampleDesc.Count = 1;
    
    	// 입력 텍스처 생성
    	CHECK(DEVICE->CreateTexture2D(&desc, NULL, _input.GetAddressOf()));
    
    	// 소스 텍스처의 데이터를 입력 텍스처로 복사합니다.
    	DC->CopyResource(_input.Get(), src.Get());
    }
    
    // 입력 텍스처에 대한 SRV 생성
    void TextureBuffer::CreateSRV()
    {
    	D3D11_TEXTURE2D_DESC desc;
    	_input->GetDesc(&desc); // 입력 텍스처의 설명 가져오기
    
    	D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
    	ZeroMemory(&srvDesc, sizeof(D3D11_SHADER_RESOURCE_VIEW_DESC)); // 메모리 초기화
    	srvDesc.Format = desc.Format; // 포맷 설정
    	srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY; // 텍스처 배열로 사용
    	srvDesc.Texture2DArray.MipLevels = 1;
    	srvDesc.Texture2DArray.ArraySize = _arraySize;
    
    	// SRV 생성
    	CHECK(DEVICE->CreateShaderResourceView(_input.Get(), &srvDesc, _srv.GetAddressOf()));
    }
    
    // 출력 텍스처 생성
    void TextureBuffer::CreateOutput()
    {
    	D3D11_TEXTURE2D_DESC desc;
    	ZeroMemory(&desc, sizeof(D3D11_TEXTURE2D_DESC)); // 메모리 초기화
    	desc.Width = _width;
    	desc.Height = _height;
    	desc.ArraySize = _arraySize;
    	desc.Format = _format;
    	desc.BindFlags = D3D11_BIND_UNORDERED_ACCESS | D3D11_BIND_SHADER_RESOURCE; // UAV 및 SRV로 사용됨
    	desc.MipLevels = 1;
    	desc.SampleDesc.Count = 1;
    
    	// 출력 텍스처 생성
    	CHECK(DEVICE->CreateTexture2D(&desc, nullptr, _output.GetAddressOf()));
    }
    
    // 출력 텍스처에 대한 UAV 생성
    void TextureBuffer::CreateUAV()
    {
    	D3D11_TEXTURE2D_DESC desc;
    	_output->GetDesc(&desc); // 출력 텍스처의 설명 가져오기
    
    	D3D11_UNORDERED_ACCESS_VIEW_DESC uavDesc;
    	ZeroMemory(&uavDesc, sizeof(D3D11_UNORDERED_ACCESS_VIEW_DESC)); // 메모리 초기화
    	uavDesc.Format = DXGI_FORMAT_UNKNOWN; // 포맷 자동 결정
    	uavDesc.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE2DARRAY; // 텍스처 배열로 사용
    	uavDesc.Texture2DArray.ArraySize = _arraySize;
    
    	// UAV 생성
    	CHECK(DEVICE->CreateUnorderedAccessView(_output.Get(), &uavDesc, _uav.GetAddressOf()));
    }
    
    // 결과 데이터를 저장할 텍스처 생성 (주로 읽기 전용 SRV를 위해 사용됩니다)
    void TextureBuffer::CreateResult()
    {
    	D3D11_TEXTURE2D_DESC desc;
    	_output->GetDesc(&desc); // 출력 텍스처의 설명 가져오기
    
    	D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
    	ZeroMemory(&srvDesc, sizeof(D3D11_SHADER_RESOURCE_VIEW_DESC)); // 메모리 초기화
    	srvDesc.Format = desc.Format; // 포맷 설정
    	srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY; // 텍스처 배열로 사용
    	srvDesc.Texture2DArray.MipLevels = 1;
    	srvDesc.Texture2DArray.ArraySize = _arraySize;
    
    	// 결과용 SRV 생성
    	CHECK(DEVICE->CreateShaderResourceView(_output.Get(), &srvDesc, _outputSRV.GetAddressOf()));
    }

    프로젝트 호출

    TextureBufferDemo.h

    #pragma once
    #include "IExecute.h"
    class TextureBufferDemo :public IExecute
    {
    public:
    	void Init() override;
    	void Update() override;
    	void Render() override;
    
    private:
    	shared_ptr<Shader> _shader;
    
    private:
    	ComPtr<ID3D11ShaderResourceView> MakeComputeShaderTexture();
    };

    TextureBufferDemo.cpp

    #include "pch.h"
    #include "TextureBufferDemo.h"
    #include "GeometryHelper.h"
    #include "Camera.h"
    #include "GameObject.h"
    #include "CameraScript.h"
    #include "MeshRenderer.h"
    #include "Mesh.h"
    #include "Material.h"
    #include "Model.h"
    #include "ModelRenderer.h"
    #include "ModelAnimator.h"
    #include "Mesh.h"
    #include "Transform.h"
    #include "VertexBuffer.h"
    #include "IndexBuffer.h"
    #include "Light.h"
    #include "TextureBuffer.h"
    
    void TextureBufferDemo::Init()
    {
    	auto newSrv = MakeComputeShaderTexture();
    
    	_shader = make_shared<Shader>(L"23. RenderDemo.fx");
    
    	// Camera
    	{
    		auto camera = make_shared<GameObject>();
    		camera->GetOrAddTransform()->SetPosition(Vec3{ 0.f, 0.f, -5.f });
    		camera->AddComponent(make_shared<Camera>());
    		camera->AddComponent(make_shared<CameraScript>());
    		CUR_SCENE->Add(camera);
    	}
    
    	// Light
    	{
    		auto light = make_shared<GameObject>();
    		light->AddComponent(make_shared<Light>());
    		LightDesc lightDesc;
    		lightDesc.ambient = Vec4(0.4f);
    		lightDesc.diffuse = Vec4(1.f);
    		lightDesc.specular = Vec4(0.1f);
    		lightDesc.direction = Vec3(1.f, 0.f, 1.f);
    		light->GetLight()->SetLightDesc(lightDesc);
    		CUR_SCENE->Add(light);
    	}
    	
    
    	// Mesh
    	// Material
    	{
    		shared_ptr<Material> material = make_shared<Material>();
    		material->SetShader(_shader);
    		auto texture = make_shared<Texture>();
    		texture->SetSRV(newSrv);
    		material->SetDiffuseMap(texture);
    		MaterialDesc& desc = material->GetMaterialDesc();
    		desc.ambient = Vec4(1.f);
    		desc.diffuse = Vec4(1.f);
    		desc.specular = Vec4(1.f);
    		RESOURCES->Add(L"Veigar", material);
    	}
    
    	for (int32 i = 0; i < 100; i++)
    	{
    		auto obj = make_shared<GameObject>();
    		obj->GetOrAddTransform()->SetLocalPosition(Vec3(rand() % 100, 0, rand() % 100));
    		obj->AddComponent(make_shared<MeshRenderer>());
    		{
    			obj->GetMeshRenderer()->SetMaterial(RESOURCES->Get<Material>(L"Veigar"));
    		}
    		{
    			auto mesh = RESOURCES->Get<Mesh>(L"Sphere");
    			obj->GetMeshRenderer()->SetMesh(mesh);
    			obj->GetMeshRenderer()->SetPass(0);
    		}
    
    		CUR_SCENE->Add(obj);
    	}
    
    	//RENDER->Init(_shader);
    }
    
    void TextureBufferDemo::Update()
    {
    
    }
    
    void TextureBufferDemo::Render()
    {
    
    }
    
    Microsoft::WRL::ComPtr<ID3D11ShaderResourceView> TextureBufferDemo::MakeComputeShaderTexture()
    {
    	auto shader = make_shared<Shader>(L"26. TextureBufferDemo.fx");
    	
    	auto texture = RESOURCES->Load<Texture>(L"Veigar", L"..\\Resources\\Textures\\veigar.jpg");
    	shared_ptr<TextureBuffer> textureBuffer = make_shared<TextureBuffer>(texture->GetTexture2D());
    
    	shader->GetSRV("Input")->SetResource(textureBuffer->GetSRV().Get());
    	shader->GetUAV("Output")->SetUnorderedAccessView(textureBuffer->GetUAV().Get());
    
    	uint32 width = textureBuffer->GetWidth();
    	uint32 height = textureBuffer->GetHeight();
    	uint32 arraySize = textureBuffer->GetArraySize();
    
    	uint32 x = max(1, (width + 31) / 32);
    	uint32 y = max(1, (height + 31) / 32);
    	shader->Dispatch(0, 0, x, y, arraySize);
    
    	return textureBuffer->GetOutputSRV();
    }

    결론

    TextureBuffer는 DirectX11에서 중요한 리소스 유형 중 하나로, 이미지 데이터뿐만 아니라 다양한 형태의 데이터를 효율적으로 저장하고 접근하는 데 활용됩니다. 텍스처 버퍼의 사용은 그래픽 렌더링의 품질을 향상시키는 동시에, GPU를 활용한 다양한 계산 작업에도 큰 이점을 제공합니다. TextureBuffer를 통해, 개발자는 GPU의 강력한 처리 능력을 최대한 활용하여 더욱 다채롭고 동적인 그래픽과 계산 애플리케이션을 개발할 수 있습니다.

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

    티스토리툴바