Skip to content

Commit 80c230e

Browse files
committed
Fix billboards.
1 parent 2752faa commit 80c230e

6 files changed

Lines changed: 104 additions & 27 deletions

File tree

3DRadSpace/3DRadSpace_Editor_WindowsDX11/Editor/EditorGame.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,12 @@ void EditorGame::Load()
152152
RectangleF(btnSize * 8, 0.0f, btnSize, btnSize),
153153
RectangleF(0.0f, 0.5f, 0.25f, 0.25f)
154154
);
155+
156+
billboard = std::make_unique<CilindricalBillboard>(Device.get());
157+
billboard->Texture = _btnSpritesheet.get();
158+
billboard->Axis = Vector3::UnitY();
159+
billboard->Scale = Vector2(1.0f, 1.0f);
160+
billboard->Transform = Matrix4x4::CreateScale(1.5f) * Matrix4x4::CreateTranslation(Vector3(2, 2, 0));
155161
}
156162

157163
void EditorGame::_controlCamera()
@@ -401,6 +407,10 @@ void EditorGame::Draw3D()
401407
axis->Projection = Projection;
402408
axis->Draw3D();
403409

410+
billboard->View = View;
411+
billboard->Projection = Projection;
412+
billboard->Draw3D();
413+
404414
if (Settings::ShowGrid.Value)
405415
{
406416
grid->View = View;

3DRadSpace/3DRadSpace_Editor_WindowsDX11/Editor/EditorGame.hpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include <Engine3DRadSpace/Graphics/Primitives/LineList.hpp>
99
#include <Engine3DRadSpace/Graphics/Primitives/Arrow.hpp>
1010
#include <Engine3DRadSpace/Graphics/Font.hpp>
11+
#include <Engine3DRadSpace/Graphics/Primitives/CilindricalBillboard.hpp>
1112

1213
//Despite using namespaces are ill-advised to be used in headers, this header is not meant to be included in other files.
1314
using namespace Engine3DRadSpace;
@@ -42,7 +43,7 @@ class EditorGame : public Engine3DRadSpace::Game
4243
IObject* _selectedObject = nullptr;
4344

4445
std::unique_ptr<ITexture2D> _btnSpritesheet;
45-
//std::unique_ptr<CilindricalBillboard> billboard;
46+
std::unique_ptr<CilindricalBillboard> billboard;
4647

4748
Button btnMvX;
4849
Button btnMvY;
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
cbuffer Data : register(b0)
2+
{
3+
row_major matrix matWorldViewProj; // MVP transformation
4+
}
5+
6+
Texture2D TextureModel : register(t0);
7+
SamplerState TextureSampler : register(s0);
8+
9+
struct VertexIn
10+
{
11+
float3 Position : POSITION;
12+
float2 UV : TEXCOORD;
13+
};
14+
15+
struct VertexOut
16+
{
17+
float4 Position : SV_POSITION;
18+
float2 UV: TEXCOORD;
19+
};
20+
21+
VertexOut VS_Main(VertexIn v)
22+
{
23+
VertexOut r;
24+
r.Position = mul(float4(v.Position.xyz,1), matWorldViewProj);
25+
r.UV = v.UV;
26+
return r;
27+
}
28+
29+
float4 PS_Main(VertexOut v) : SV_TARGET
30+
{
31+
return TextureModel.Sample(TextureSampler, v.UV);
32+
}
Lines changed: 45 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
#include "CilindricalBillboard.hpp"
22
#include "Plane.hpp"
33
#include "../IGraphicsCommandList.hpp"
4+
#include "../IShaderCompiler.hpp"
5+
#include "../../Logging/Exception.hpp"
46

57
using namespace Engine3DRadSpace;
68
using namespace Engine3DRadSpace::Graphics;
@@ -13,50 +15,76 @@ CilindricalBillboard::CilindricalBillboard(IGraphicsDevice *device) :
1315
{
1416
auto vertices = CreateVertices();
1517
_vertices = device->CreateVertexBuffer<VertexPositionUV>(vertices, BufferUsage::ReadOnlyGPU);
16-
17-
auto indices = Plane::CreateIndices();
18+
19+
auto indices = CreateIndices();
1820
_indices = device->CreateIndexBuffer(indices);
21+
22+
ShaderDescFile vtx("Data\\Shaders\\PositionUV.hlsl", "VS_Main", ShaderType::Vertex);
23+
ShaderDescFile frg("Data\\Shaders\\PositionUV.hlsl", "PS_Main", ShaderType::Fragment);
24+
25+
std::array<ShaderDesc*, 2> shaders = { &vtx, &frg };
26+
27+
auto effect = device->ShaderCompiler()->CompileEffect(shaders);
28+
if (effect.first)
29+
{
30+
_shader = effect.first;
31+
}
32+
else
33+
{
34+
throw Logging::Exception(std::format("Failed to compile effect for CilindricalBillboard: {}", effect.second.Log));
35+
}
1936
}
2037

2138
Matrix4x4 CilindricalBillboard::_mvp() const noexcept
2239
{
2340
auto v = View;
41+
auto v_inv = v;
42+
v_inv.Invert();
2443

25-
Vector3 cam_pos(v.M41, v.M42, v.M43);
44+
Vector3 cam_pos(v_inv.M41, v_inv.M42, v_inv.M43);
2645
Vector3 x_axis(v.M11, v.M21, v.M31);
27-
Vector3 y_axis(v.M11, v.M21, v.M31);
28-
Vector3 z_axis(v.M11, v.M21, v.M31);
29-
30-
Vector3 fwd = cam_pos + z_axis;
46+
Vector3 y_axis(v.M12, v.M22, v.M32);
47+
Vector3 z_axis(v.M13, v.M23, v.M33);
48+
3149
Vector3 up = cam_pos + y_axis;
32-
Vector3 right = cam_pos + x_axis;
50+
Vector3 fwd = cam_pos - z_axis;
3351

34-
auto model = Matrix4x4::CreateCylindricalBillboard(Position, cam_pos, up, fwd, Axis, std::nullopt);
35-
return model * View * Projection;
52+
// Use Position field if set, otherwise extract from Transform
53+
Vector3 objectPos = (Position != Vector3::Zero()) ? Position : Vector3(Transform.M41, Transform.M42, Transform.M43);
54+
auto model = Matrix4x4::CreateCylindricalBillboard(objectPos, cam_pos, up, fwd, Axis, std::nullopt);
55+
return model * v * Projection;
3656
}
3757

3858
std::array<VertexPositionUV, 4> CilindricalBillboard::CreateVertices()
3959
{
4060
std::array<VertexPositionUV, 4> plane;
4161

42-
Vector2 s(0.5f);
62+
Vector2 s(0.5f, 0.5f);
4363

44-
//See Plane.cpp
45-
plane[0] = VertexPositionUV(Vector3(-s.X, 0, -s.Y), Vector2(0,1));
46-
plane[1] = VertexPositionUV(Vector3(-s.X, 0, +s.Y), Vector2(0,0));
47-
plane[2] = VertexPositionUV(Vector3(+s.X, 0, +s.Y), Vector2(0,1));
48-
plane[3] = VertexPositionUV(Vector3(+s.X, 0, -s.Y), Vector2(1,1));
64+
//Billboard in XY plane, will be rotated by cylindrical billboard matrix
65+
plane[0] = VertexPositionUV(Vector3(-s.X, -s.Y, 0), Vector2(0, 1));
66+
plane[1] = VertexPositionUV(Vector3(-s.X, +s.Y, 0), Vector2(0, 0));
67+
plane[2] = VertexPositionUV(Vector3(+s.X, +s.Y, 0), Vector2(1, 0));
68+
plane[3] = VertexPositionUV(Vector3(+s.X, -s.Y, 0), Vector2(1, 1));
4969

5070
return plane;
5171
}
5272

73+
std::array<unsigned, 6> CilindricalBillboard::CreateIndices()
74+
{
75+
//Counter-clockwise winding for camera-facing billboard (reversed from Plane for proper facing).
76+
return { 0, 2, 1, 0, 3, 2 };
77+
}
78+
5379
void CilindricalBillboard::Draw3D()
5480
{
5581
auto mat = _mvp();
5682

5783
_shader->SetAll();
5884
_shader->operator[](0)->SetData(0, &mat, sizeof(mat));
5985
_shader->operator[](1)->SetTexture(0, Texture);
60-
_device->ImmediateContext()->DrawVertexBufferWithindices(_vertices.get(), _indices.get());
86+
auto cmdList = _device->ImmediateContext();
87+
cmdList->SetTopology(VertexTopology::TriangleList);
88+
cmdList->DrawVertexBufferWithindices(_vertices.get(), _indices.get());
6189
}
6290

3DRadSpace/Engine3DRadSpace/Graphics/Primitives/CilindricalBillboard.hpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,15 @@ namespace Engine3DRadSpace::Graphics::Primitives
1919
/// Camera projection matrix.
2020
/// </summary>
2121
Math::Matrix4x4 Projection;
22-
23-
Math::Vector3 Position;
22+
23+
Math::Vector3 Position = Math::Vector3::Zero();
2424
Math::Vector2 Scale = Math::Vector2::One();
2525
Math::Vector3 Axis = Math::Vector3::UnitY();
26-
26+
2727
ITexture2D* Texture;
2828

2929
static std::array<VertexPositionUV, 4> CreateVertices();
30+
static std::array<unsigned, 6> CreateIndices();
3031

3132
void Draw3D() override;
3233

3DRadSpace/Engine3DRadSpace/Graphics/Primitives/SphericalBillboard.cpp

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,20 @@ SphericalBillboard::SphericalBillboard(IGraphicsDevice* device) : CilindricalBil
1111

1212
Matrix4x4 SphericalBillboard::_mvp() const noexcept
1313
{
14-
Vector3 cam_pos(-View.M41, -View.M42, -View.M43);
15-
Vector3 x_axis(View.M11, View.M21, View.M31);
16-
Vector3 y_axis(View.M11, View.M21, View.M31);
17-
Vector3 z_axis(View.M11, View.M21, View.M31);
14+
auto v = View;
15+
auto v_inv = v;
16+
v_inv.Invert();
17+
18+
Vector3 cam_pos(v_inv.M41, v_inv.M42, v_inv.M43);
19+
Vector3 x_axis(v.M11, v.M21, v.M31);
20+
Vector3 y_axis(v.M12, v.M22, v.M32);
21+
Vector3 z_axis(v.M13, v.M23, v.M33);
1822

1923
Vector3 fwd = cam_pos + z_axis;
2024
Vector3 up = cam_pos + y_axis;
21-
Vector3 right = cam_pos + x_axis;
2225

23-
auto model = Matrix4x4::CreateSphericalBillboard(Position, cam_pos, up, fwd);
26+
// Use Position field if set, otherwise extract from Transform
27+
Vector3 objectPos = (Position != Vector3::Zero()) ? Position : Vector3(Transform.M41, Transform.M42, Transform.M43);
28+
auto model = Matrix4x4::CreateSphericalBillboard(objectPos, cam_pos, up, fwd);
2429
return model * View * Projection;
2530
}

0 commit comments

Comments
 (0)