1. SpriteEffect
더보기
#pragma once
class SpriteEffect : public BillBoard
{
class SpriteFrameBuffer : public ConstBuffer
{
public:
struct Data
{
Float2 startPos{};
Float2 size{ 1.0f, 1.0f };
Float2 maxSize{ 1.0f, 1.0f };
float padding[2];
}data;
//
public:
SpriteFrameBuffer() : ConstBuffer(&data, sizeof(Data)) {}
};
//
struct Clip
{
Float2 startPos{};
Float2 size{ 1.0f, 1.0f };
Float2 maxSize{ 1.0f, 1.0f };
//
Clip() {}
};
///////////////////////////////////
public:
bool isActive;
///////////////////////////////////
private:
UINT maxFrameX;
UINT maxFrameY;
float playTime;
float speed;
//
float frameTime;
float totalTime;
UINT currentFrameIdx;
UINT maxFrameCount;
///////////////////////////////////
SpriteFrameBuffer* frameBuffer;
vector<Clip*> clips;
///////////////////////////////////
public:
SpriteEffect(wstring diffuseFile, UINT maxFrameX, UINT maxFrameY, float playTime, float speed);
~SpriteEffect();
///////////////////////////////////
void Update();
void Render();
///////////////////////////////////
void Play(Vector3 value);
void End();
};
///////////////////////////////////////////////////////////////////////////
#include "Framework.h"
SpriteEffect::SpriteEffect(wstring diffuseFile, UINT maxFrameX, UINT maxFrameY,
float playTime, float speed)
:BillBoard(diffuseFile, L"SpriteEffect"),
isActive(false),
maxFrameX(maxFrameX), maxFrameY(maxFrameY), speed(speed), playTime(playTime),
frameTime(0), totalTime(0), currentFrameIdx(0), maxFrameCount(0),
frameBuffer(nullptr), clips{}
{
//
frameBuffer = new SpriteFrameBuffer();
maxFrameCount = maxFrameX * maxFrameY;
Float2 maxSize = { (float)GetMaterial()->diffuseMap->Width(),
(float)GetMaterial()->diffuseMap->Height() };
Float2 size = { maxSize.x / (float)maxFrameX, maxSize.y / (float)maxFrameY };
//
for (UINT y = 0; y < maxFrameY; ++y)
for (UINT x = 0; x < maxFrameX; ++x)
{
Clip* clip = new Clip();
clip->maxSize = maxSize;
clip->size = size;
clip->startPos = { x * size.x, y * size.y };
clips.emplace_back(clip);
}
//
frameBuffer->data.maxSize = maxSize;
frameBuffer->data.size = size;
frameBuffer->data.startPos = clips[0]->startPos;
}
SpriteEffect::~SpriteEffect()
{
delete frameBuffer;
//
for (Clip* clip : clips)
delete clip;
}
void SpriteEffect::Update()
{
if (isActive == false) return;
//
frameTime += DELTA;
if (speed < frameTime)
{
totalTime += frameTime;
frameTime = 0;
(++currentFrameIdx) %= maxFrameCount;
}
if (totalTime > playTime)
{
totalTime = 0;
isActive = false;
}
//
frameBuffer->data.startPos = clips[currentFrameIdx]->startPos;
//
BillBoard::Update();
}
void SpriteEffect::Render()
{
if (isActive == false) return;
//
frameBuffer->SetPSBuffer(6);
BillBoard::Render();
}
void SpriteEffect::Play(Vector3 value)
{
position = value;
isActive = true;
}
void SpriteEffect::End()
{
position = {};
isActive = false;
}
2. SpriteEffect shader
더보기
#include "Header.hlsli"
/* in Header
cbuffer SpriteFrame : register(b6)
{
float2 startPos;
float2 size;
float2 maxSize;
}
*/
struct PixelInput
{
float4 pos : SV_Position;
float2 uv : UV;
};
PixelInput VS(VertexUV input)
{
PixelInput output;
output.pos = mul(input.pos, world);
output.pos = mul(output.pos, view);
output.pos = mul(output.pos, projection);
output.uv = input.uv;
return output;
}
float4 PS(PixelInput input) : SV_Target
{
float2 uv = (startPos / maxSize) + input.uv * (size / maxSize);
//
return diffuseMap.Sample(samp, uv) * mDiffuse;
}
3. EffectManager
더보기
#pragma once
class EffectManager : public Singleton<EffectManager>
{
private:
friend class Singleton;
///////////////////////////////////////////
private:
map<string, vector<SpriteEffect*>> totalEffect;
///////////////////////////////////////////
private:
EffectManager();
~EffectManager();
///////////////////////////////////////////
public:
void Update();
void Render();
//
void Add(string key, UINT poolCount, wstring textureFile,
UINT maxFrameX, UINT maxFrameY,
float playTime = 1.0f, float speed = 0.1f);
void Play(string key, Vector3 pos);
void Stop();
///////////////////////////////////////////
vector<SpriteEffect*> GetSpriteEffect(string key) { return totalEffect[key]; }
};
///////////////////////////////////////////////////////////////////////////
#include "Framework.h"
EffectManager::EffectManager()
{
}
EffectManager::~EffectManager()
{
for (auto effects : totalEffect)
for (SpriteEffect* effect : effects.second)
delete effect;
}
void EffectManager::Update()
{
for (auto effects : totalEffect)
for (SpriteEffect* effect : effects.second)
effect->Update();
}
void EffectManager::Render()
{
for (auto effects : totalEffect)
for (SpriteEffect* effect : effects.second)
effect->Render();
}
void EffectManager::Add(string key, UINT poolCount, wstring textureFile,
UINT maxFrameX, UINT maxFrameY,
float playTime, float speed)
{
if (totalEffect.count(key) > 0)
return;
//
vector<SpriteEffect*> effects;
//
for (UINT i = 0; i < poolCount; ++i)
{
SpriteEffect* effect = new SpriteEffect(textureFile, maxFrameX, maxFrameY, playTime, speed);
effects.emplace_back(effect);
}
totalEffect[key] = effects;
}
void EffectManager::Play(string key, Vector3 pos)
{
if (totalEffect.count(key) == 0)
return;
for (SpriteEffect* effect : totalEffect[key])
{
if (effect->isActive) continue;
//
effect->Play(pos);
return;
}
}
void EffectManager::Stop()
{
for (auto effects : totalEffect)
for (SpriteEffect* effect : effects.second)
effect->End();
}
4. Scene
더보기
#pragma once
class ParticleScene : public Scene
{
private:
Collider* collider;
//
Contact contact;
//
BlendState* blendState[2];
DepthStencilState* depthState[2];
////////////////////////////////
public:
ParticleScene();
~ParticleScene();
// Scene을(를) 통해 상속됨
virtual void Update() override;
virtual void PreRender() override;
virtual void Render() override;
virtual void PostRender() override;
////////////////////////////////
void Pick();
};
///////////////////////////////////////////////////////////////////////////
#include "Framework.h"
#include "ParticleScene.h"
ParticleScene::ParticleScene()
{
collider = new SphereCollider();
collider->scale = { 10.0f, 10.0f, 10.0f };
collider->UpdateWorld();
//
EffectManager::Get()->Add("FX", 100, L"Textures/Effect/Scan.png", 2, 6, 5.0f);
//
blendState[0] = new BlendState();
blendState[1] = new BlendState();
//blendState[1]->Alpha(true);
blendState[1]->AlphaToCoverage(true);
}
ParticleScene::~ParticleScene()
{
delete blendState[0];
delete blendState[1];
//
delete collider;
}
void ParticleScene::Update()
{
collider->UpdateWorld();
Pick();
//
EffectManager::Get()->Update();
}
void ParticleScene::PreRender()
{
}
void ParticleScene::Render()
{
collider->Render();
//
blendState[1]->SetState();
EffectManager::Get()->Render();
blendState[0]->SetState();
}
void ParticleScene::PostRender()
{
ImGui::Begin("[ParticleScene]");
///////////////////////////////
ImGui::Text("HitPoint : ( %.1f , %.1f , %.1f )",
contact.hitPoint.x, contact.hitPoint.y, contact.hitPoint.z);
ImGui::Text("HitDist : %.1f",
contact.distance);
//
Vector3 rot = EffectManager::Get()->GetSpriteEffect("FX")[0]->rotation;
ImGui::Text("EffectRot : ( %.1f , %.1f , %.1f )",
rot.x, rot.y, rot.z);
///////////////////////////////
ImGui::End();
}
void ParticleScene::Pick()
{
if (KEY_UP(VK_LBUTTON))
{
Ray ray = CAMERA->ScreenPointToRay(MOUSEPOS);
if (collider->RayCollision(ray, &contact))
EffectManager::Get()->Play("FX", contact.hitPoint);
}
}
'DX11 3D Game Programming' 카테고리의 다른 글
2020_1208 DX3D 포트폴리오 기획 (0) | 2020.12.08 |
---|---|
2020_1130 Particle Editor (0) | 2020.11.29 |
2020_1123 MiniGame(남극대모험 style) (0) | 2020.11.23 |
2020_1118 Model Anim Instancing & Frustum Culling (0) | 2020.11.18 |
2020_1116 MapTool ( Model Instancing ) (0) | 2020.11.16 |