1. GlobalShader
0 ~ 7.fx를 보면 매번 동일하게 선언되던 Matrix와 Texture, Sampler를 하나의 00.Global.fx로 묶기
#ifndef #define #endif를 통해서 #pragma once와 동일하게 사용
- 자주 바뀌지 않는 전역변수(
View, Projection), 그렇지않는 변수(World)를 위한 상수버퍼를 각각 만들기
- 추가로
VertexData, VertexOutput, Sampler, Rasterizer,Macro를 설정해주기
00.Global.fx
#ifndef _GLOBAL_FX_
#define _GLOBAL_FX_
cbuffer GlobalBuffer
{
matrix V;
matrix P;
matrix VP;
};
cbuffer TransformBuffer
{
matrix W;
};
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;
};
struct MeshOutput
{
float4 position : SV_POSITION;
float2 uv : TEXCOORD;
float3 normal : NORMAL;
};
SamplerState LinearSampler
{
Filter = MIN_MAG_MIP_LINEAR;
AddressU = Wrap;
AddressV = Wrap;
};
SamplerState PointSampler
{
Filter = MIN_MAG_MIP_POINT;
AddressU = Wrap;
AddressV = Wrap;
};
RasterizerState FillModeWireFrame
{
FillMode = Wireframe;
};
#define PASS_VP(name, vs, ps) \
pass name \
{ \
SetVertexShader( CompileShader( vs_5_0, vs() ) ); \
SetPixelShader( CompileShader( ps_5_0, ps() ) ); \
}
#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
- 싱글턴으로 만든
RENDER의 Init()과 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 = make_shared<GameObject>();
_camera->GetOrAddTransform();
_camera->AddComponent(make_shared<Camera>());
_camera->AddComponent(make_shared<CameraScript>());
_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