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에 갯수별로 만들어 주게 되면
여러개의 텍스처가 만들어진다.