프로그래밍 공부
작성일
2023. 12. 22. 16:37
작성자
WDmil
728x90

게임의 이펙트를 표시하고 사용하기 위해 사용하는 방식을 이야기한다.

 

대체적으로 Quad형태로 1차원평면으로 표시하는 경우와 3DObject를 생성하여 Object를 사용해서 이펙트를 표기하는 방법이다.

 

Quad를 사용하는 방법은 대체적으로 과거에 최적화를 위해 사용하는 방식이고, 

 

요즘에는 컴퓨팅 파워가 많이 발전해서, 오브젝트 생성방식을 사용한다.

 

일단, Quad형태로 뒷배경을 사용하는 방법을 사용해보자.

 

#pragma once

class BillboardScene : public Scene
{
private:
	const UINT COUNT = 1000;

public:
	BillboardScene();
	~BillboardScene();

	// Scene을(를) 통해 상속됨
	void Update() override;
	void PreRender() override;
	void Render() override;
	void PostRender() override;
	void GUIRender() override;

private:
	Terrain* terrain;
	vector<Quad*> trees;

	DepthStencilState* depthState[2];
};
#include "Framework.h"

BillboardScene::BillboardScene()
{
	terrain = new Terrain();

    trees.reserve(COUNT);
    FOR(COUNT)
    {
        Float2 size;
        size.x = MATH->Random(3.0f, 10.0f);
        size.y = MATH->Random(3.0f, 10.0f);

        Quad* tree = new Quad(size);
        tree->GetMaterial()->SetDiffuseMap(L"Textures/Landscape/Tree.png");
        Vector3 pos;
        pos.x = MATH->Random(0.0f, terrain->GetSize().x);
        pos.z = MATH->Random(0.0f, terrain->GetSize().y);
        pos.y = terrain->GetOnGrondPosition(pos).y + size.y * 0.5f;
        tree->SetLocalPosition(pos);

        trees.push_back(tree);
    }

    depthState[0] = new DepthStencilState();
    depthState[1] = new DepthStencilState();
    depthState[1]->DepthWriteMask(D3D11_DEPTH_WRITE_MASK_ZERO); // 깊이연산을 하지 마 라고 하는것.
}

BillboardScene::~BillboardScene()
{
    delete terrain;
    for (Quad* tree : trees)
        delete tree;
}

void BillboardScene::Update()
{
    for (Quad* tree : trees)
    {
        //tree->SetLocalRotation(CAM->GetLocalRotation());
        //tree->SetLocalRotation({ 0,CAM->GetLocalRotation().y,0 });
        Vector3 dir = tree->GetLocalPosition() - CAM->GetLocalPosition();
        tree->SetLocalRotation({ 0, atan2(dir.x, dir.z), 0 });
        tree->UpdateWorld();
    }
}

void BillboardScene::PreRender()
{
}

void BillboardScene::Render()
{
    terrain->Render();
    depthState[1]->SetState();
    for (Quad* tree : trees)
        tree->Render();
    depthState[0]->SetState();
}

void BillboardScene::PostRender()
{
}

void BillboardScene::GUIRender()
{
}

 

Billboard를 사용하는 Scene를 사용해서 Terrain과 Treeobject를 생성하여 사용한다.

 

주로 Quad를 표시하는 방법은, Map에 무작위의 Quad를 배치하고, 해당 배치된 Quad를 CamPosition을 참조하여 Rotation하는 방법을 사용하는데,

 

이때 Alpha값을 사용하여 표기한다.

 

그러나, Alpha값을 사용하여 표기하는 방법은 Vector의 3차원표기에 따른 오류가 있는데,

 

Render순서에 따른 뒷배경을 참조하는것 이 Alpha값을 참조하는 방법인데, 이 Render순서에 따라. Quad가 Render가 되었을 때, 이후에 Render된 Object가 해당 Object의 앞에 존재하였을 때, Alpha값에 의해 지워지는 오류이다.

 

위와같이 Alpha값에의해 렌더순서가 바뀌더라도 Position상 뒤에 존재하면, 지워지게 된다.

 

이러한 오류를 해결하기 위해 사용되는 것 이 Alpha값을 사용하지 않는방법이 있는데, 이건 PostFX상 불가능에 가깝고, 점점 투명해지는 방식의 출력과정도 존재하기 때문에 힘들다.

 

그럼으로, 다른방법을 사용해야 하는데,

 

주로 사용하는 방법이 그냥, DepthStencil을 사용하지 않아버리면 된다.

 

어차피 BackGround상 크게 주의깊게 보지 않는 경우가 많기 때문에, 큰 위화감이 없게 생성이 가능하다.

 

다른 방법은, Render전에 Render선언된 모든 Object를 참조하여,

 

카메라와의 거리에 따라 Depth기준으로 Object의 Render순서를 재정렬하고. Render하는 방식이 있는데,

 

우선은 DepthStencil을 사용하지 않는 방법으로 렌더를 해보자.

위와같이 설정한 DepthState를 사용하면 되는데,

 

다음과 렌더시 다음과 같이 렌더된다.

 

뒤에 가려지는 object가 존재하더라도, 그냥 렌더해버리면 된다.

 

그렇게 되면, 가려지는것 과 같은 버그가 없이, 무사히 렌더가 되는것을 확인할 수 있다.

 

주로, 크게 눈에 띄이지 않는 배경을 작업할때 사용하는 방식이다.

728x90