[D3D] Global Shader

vector·2025년 11월 21일

1. GlobalShader

  • 0 ~ 7.fx를 보면 매번 동일하게 선언되던 MatrixTexture, Sampler를 하나의 00.Global.fx로 묶기
  • #ifndef #define #endif를 통해서 #pragma once와 동일하게 사용
  • 자주 바뀌지 않는 전역변수(View, Projection), 그렇지않는 변수(World)를 위한 상수버퍼를 각각 만들기
  • 추가로 VertexData, VertexOutput, Sampler, Rasterizer,Macro를 설정해주기

00.Global.fx

#ifndef _GLOBAL_FX_ // if not define
#define _GLOBAL_FX_

/////////////////
// ConstBuffer //
/////////////////

// 자주 바뀌지 않는 전역 변수들을 위한 상수 버퍼
cbuffer GlobalBuffer
{
    matrix V;
    matrix P;
    matrix VP;
};

// 자주 바뀌는 개체별 전역 변수들을 위한 상수 버퍼
cbuffer TransformBuffer
{
    matrix W;
};


////////////////
// VertexData //
////////////////

struct Vertex
{
    float4 position : POSITION;
};

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

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

struct VertexTetrueNormal
{
    float4 position : POSITION;
    float2 uv : TEXCOORD;
    float3 normal : NOERMAL;
};


//////////////////
// VertexOutput //
//////////////////

struct MeshOutput
{
    float4 position : SV_POSITION; //SV : System Value
    float2 uv : TEXCOORD;
    float3 normal : NORMAL;
};


//////////////////
// SamplerState //
//////////////////

SamplerState LinearSampler
{
    Filter = MIN_MAG_MIP_LINEAR;
    AddressU = Wrap;
    AddressV = Wrap;
};

SamplerState PointSampler
{
    Filter = MIN_MAG_MIP_POINT;
    AddressU = Wrap;
    AddressV = Wrap;
};


/////////////////////
// RasterizerState //
/////////////////////

RasterizerState FillModeWireFrame
{
    FillMode = Wireframe;
};


///////////
// Macro //
///////////

#define PASS_VP(name, vs, ps)                               \
pass name                                                   \
    {                                                       \
        SetVertexShader( CompileShader( vs_5_0, vs() ) );   \
        SetPixelShader( CompileShader( ps_5_0, ps() ) );    \
    }


//////////////
// Function //
//////////////


#endif

08.GlobalTest.fx

  • 00.Global.fx#include한 쉐이터
#include "00.Global.fx"

MeshOutput VS(VertexTetrueNormal input)
{
    MeshOutput output;
    output.position = mul(input.position, W);
    output.position = mul(output.position, VP);
    
    
    output.uv = input.uv;
    output.normal = mul(input.normal, (float3x3) W);
    
    return output;
}

Texture2D Texture0;

float4 PS(MeshOutput input) : SV_TARGET
{
    return Texture0.Sample(LinearSampler, input.uv);
}

technique11 T0
{
    PASS_VP(P0, VS, PS)
}

RenderManager

  • Globla쉐이더를 활용해서 데이터를 버퍼에 저장하고 남겨주는 RenderManager 생성
  • ID3DX11EffectContantBuffer를 활용

RenderManager.h

#pragma once
#include "ConstantBuffer.h"

class Shader;

struct GlobalDesc
{
	Matrix V = Matrix::Identity;
	Matrix P = Matrix::Identity;
	Matrix VP = Matrix::Identity;
};

struct TransformDesc
{
	Matrix W = Matrix::Identity;
};

class RenderManager
{
	DECLARE_SINGLE(RenderManager);

public:
	void Init(shared_ptr<Shader> shader);
	void Update();

	void PushGlobalData(const Matrix& view, const Matrix& projection);
	void PushTransformData(const TransformDesc& desc);


private:
	shared_ptr<Shader> _shader;

	GlobalDesc _globalDesc;
	shared_ptr<ConstantBuffer<GlobalDesc>> _globalBuffer;
	ComPtr<ID3DX11EffectConstantBuffer> _globalEffectBuffer;

	TransformDesc _transformDesc;
	shared_ptr<ConstantBuffer<TransformDesc>> _transformBuffer;
	ComPtr<ID3DX11EffectConstantBuffer> _transformEffectBuffer;
};

RenderManager.cpp

#include "pch.h"
#include "RenderManager.h"
#include "Camera.h"

void RenderManager::Init(shared_ptr<Shader> shader)
{
	_shader = shader;

	_globalBuffer = make_shared<ConstantBuffer<GlobalDesc>>();
	_globalBuffer->Create();
	_globalEffectBuffer = _shader->GetConstantBuffer("GlobalBuffer");

	_transformBuffer = make_shared<ConstantBuffer<TransformDesc>>();
	_transformBuffer->Create();
	_transformEffectBuffer = _shader->GetConstantBuffer("TransformBuffer");
}

void RenderManager::Update()
{
	PushGlobalData(Camera::S_MatView, Camera::S_MatProjection);
}

void RenderManager::PushGlobalData(const Matrix& view, const Matrix& projection)
{
	_globalDesc.V = view;
	_globalDesc.P = projection;
	_globalDesc.VP = view * projection;
	_globalBuffer->CopyData(_globalDesc);

	_globalEffectBuffer->SetConstantBuffer(_globalBuffer->GetComPtr().Get());
}

void RenderManager::PushTransformData(const TransformDesc& desc)
{
	_transformDesc = desc;
	_transformBuffer->CopyData(_transformDesc);

	_transformEffectBuffer->SetConstantBuffer(_transformBuffer->GetComPtr().Get());
}

RenderManager를 활용할 수 있도록 MeshRenderer의 Update() 수정하기

MeshRenderer.cpp

void MeshRenderer::Update()
{
	if (_mesh == nullptr || _texture == nullptr || _shader == nullptr)
		return;

	_shader->GetSRV("Texture0")->SetResource(_texture->GetComPtr().Get());

	auto world = GetTransform()->GetWorldMatrix();
	RENDER->PushTransformData(TransformDesc{ world });

	uint32 stride = _mesh->GetVertexBuffer()->GetStride();
	uint32 offset = _mesh->GetVertexBuffer()->GetOffset();

	DC->IASetVertexBuffers(0, 1, _mesh->GetVertexBuffer()->GetComPtr().GetAddressOf(), &stride, &offset);
	DC->IASetIndexBuffer(_mesh->GetIndexBuffer()->GetComPtr().Get(), DXGI_FORMAT_R32_UINT, 0);

	_shader->DrawIndexed(0, 0, _mesh->GetIndexBuffer()->GetCount(), 0, 0);
}

10. GlobalTestDemo

  • 싱글턴으로 만든 RENDERInit()Update() 추가
#include "pch.h"
#include "10. GlobalTestDemo.h"
#include "GeometryHelper.h"
#include "Camera.h"
#include "GameObject.h"
#include "CameraScript.h"
#include "MeshRenderer.h"
#include "Mesh.h"

void GlobalTestDemo::Init()
{
	auto shader = make_shared<Shader>(L"08.GlobalTest.fx");

	// Camera
	_camera = make_shared<GameObject>();
	_camera->GetOrAddTransform();
	_camera->AddComponent(make_shared<Camera>());
	_camera->AddComponent(make_shared<CameraScript>());

	// Object
	_obj = make_shared<GameObject>();
	_obj->GetOrAddTransform();
	_obj->AddComponent(make_shared<MeshRenderer>());
	{
		
		_obj->GetMeshRenderer()->SetShader(shader);
	}
	{
		RESOURCES->Init();
		auto mesh = RESOURCES->Get<Mesh>(L"Sphere");
		_obj->GetMeshRenderer()->SetMesh(mesh);
	}
	{
		auto texture = RESOURCES->Load<Texture>(L"Veigar", L"../Resources/Textures/veigar.jpg");
		_obj->GetMeshRenderer()->SetTexture(texture);
	}

	RENDER->Init(shader);
}

void GlobalTestDemo::Update()
{
	_camera->Update();
	RENDER->Update();
	_obj->Update();
}

결과

  • 이전과 동일하게 출력

참고 강의

https://www.inflearn.com/courses/lecture?courseId=329791&type=LECTURE&unitId=161127&subtitleLanguage=ko&tab=curriculum

profile
게임 클라이언트 프로그래머 준비중 (공부 및 기록용)

0개의 댓글