• Home
  • About
    • 게임 개발자 유정룡 photo

      게임 개발자 유정룡

      포트폴리오

    • Learn More
    • Email
    • Github
    • Bitbucket
  • Projects
    • All Projects
    • All Tags

Direct3D11 공부 40일차(Texture2D Array)

02 Aug 2021

Reading time ~2 minutes

Texture2D Array

게임에서 보면 Billboard를 활용하는 오브젝트가 2개 이상의 오브젝트로 만들어 자연스러운 효과를 주는 것을 볼 수 있다.

또한 각 오브젝트가 카메라를 바라보는것이 아닌 90나 45도 각도로 여러개가 틀어져 있는 것도 볼 수 있다.

Shader

96_Billboard.h
struct VertexBillboard
{
    float4 Position : Position;
    float2 Scale : Scale;
    uint MapIndex : MapIndex;
};

struct VertexOutput
{
    float4 Position : Position;
    float2 Scale : Scale;
    uint MapIndex : MapIndex;
};

VertexOutput VS(VertexBillboard input)
{
    VertexOutput output;
    
    output.Position = WorldPosition(input.Position);
    output.Scale = input.Scale;
    output.MapIndex = input.MapIndex;
    
    return output;
}

struct GeometryOutput
{
    float4 Position : SV_Position;
    float2 Uv : Uv;
    uint MapIndex : MapIndex;
};

[maxvertexcount(8)]
void GS_Cross(point VertexOutput input[1], inout TriangleStream<GeometryOutput> stream)
{
    float3 up = float3(0, 1, 0);
    float3 forward = float3(0, 0, 1);
    float3 right = normalize(cross(up, forward));
    
    float2 size = input[0].Scale * 0.5f;
    
    
    float4 position[8];
    position[0] = float4(input[0].Position.xyz - size.x * right - size.y * up, 1);
    position[1] = float4(input[0].Position.xyz - size.x * right + size.y * up, 1);
    position[2] = float4(input[0].Position.xyz + size.x * right - size.y * up, 1);
    position[3] = float4(input[0].Position.xyz + size.x * right + size.y * up, 1);
    
    position[4] = float4(input[0].Position.xyz - size.x * forward - size.y * up, 1);
    position[5] = float4(input[0].Position.xyz - size.x * forward + size.y * up, 1);
    position[6] = float4(input[0].Position.xyz + size.x * forward - size.y * up, 1);
    position[7] = float4(input[0].Position.xyz + size.x * forward + size.y * up, 1);
    
    float2 uv[4] =
    {
        float2(0, 1), float2(0, 0), float2(1, 1), float2(1, 0)
    };
    
    
    GeometryOutput output;
    
    [unroll(8)]
    for (int i = 0; i < 8; i++)
    {
        output.Position = ViewProjection(position[i]);
        output.Uv = uv[i % 4];
        output.MapIndex = input[0].MapIndex;
        
        stream.Append(output);
        
        [flatten]
        if (i == 3)
            stream.RestartStrip();
    }
}


Texture2DArray BillboardMap;
float4 PS_Billboard(GeometryOutput input) : SV_Target
{
    return BillboardMap.Sample(LinearSampler, float3(input.Uv, input.MapIndex)) * 1.75f;
}

이렇게 추가하고 변경해주자.

Texture2DArray로 받아오고 그 값들을 받아온 Index를 사용해서 랜더링 해준다.

Billboard Class

Billboard.h
#pragma once
#define MAX_BILLBOARD_COUNT 10000

class Billboard : public Renderer
{
public:
	Billboard(Shader* shader);
	~Billboard();

	void Update();
	void Render();

	void Add(Vector3& position, Vector2& scale, UINT mapIndex);
	void AddTexture(wstring file);

private:
	struct VertexBillboard
	{
		Vector3 Position;
		Vector2 Scale;
		UINT MapIndex;
	};

private:
	vector<VertexBillboard> vertices;
	
	vector<wstring> textureNames;
	TextureArray* textureArray;
	ID3DX11EffectShaderResourceVariable* sDiffuseMap;
};

텍스쳐를 유동적이게 받아올 수 있게 Vector로 만들어주고 받아온다.

Billboard.cpp
#include "Framework.h"
#include "Billboard.h"

Billboard::Billboard(Shader* shader)
	: Renderer(shader)
{
	Topology(D3D11_PRIMITIVE_TOPOLOGY_POINTLIST);

	sDiffuseMap = shader->AsSRV("BillboardMap");
}

Billboard::~Billboard()
{
	SafeDelete(textureArray);
}

void Billboard::Update()
{
	Super::Update();
}

void Billboard::Render()
{
	if (textureNames.size() > 0 && textureArray == NULL)
	{
		SafeDelete(textureArray);
		textureArray = new TextureArray(textureNames);
	}

	if (vertexCount != vertices.size())
	{
		vertexCount = vertices.size();

		SafeDelete(vertexBuffer);
		vertexBuffer = new VertexBuffer(&vertices[0], vertices.size(), sizeof(VertexBillboard));
	}

	Super::Render();

	sDiffuseMap->SetResource(textureArray->SRV());
	shader->Draw(0, Pass(), vertexCount);
}

void Billboard::Add(Vector3 & position, Vector2 & scale, UINT mapIndex)
{
	VertexBillboard vertex =
	{
		position, scale, mapIndex
	};

	vertices.push_back(vertex);
}

void Billboard::AddTexture(wstring file)
{
	textureNames.push_back(file);
}

이름으로 받아온 뒤 추가해준다.

그런 뒤 이 Billboard를 만들 때 텍스쳐 여러개워 각 MapIndex에 갯수별로 만들어 주게 되면

여러개의 텍스처가 만들어진다.



DirectX Share Tweet +1