Skip to content
This repository was archived by the owner on Mar 11, 2025. It is now read-only.

Commit 6e169e4

Browse files
authored
Add Transform, view and projection matrices (#20)
1 parent c87092f commit 6e169e4

File tree

10 files changed

+169
-13
lines changed

10 files changed

+169
-13
lines changed

App/Src/Main.cpp

+10-10
Original file line numberDiff line numberDiff line change
@@ -50,20 +50,20 @@ namespace
5050
const auto& renderDevice = engine.RenderDevice();
5151
if (!shader.Load(renderDevice.get_device(), vertexSpirV, fragmentSpirV)) { throw std::runtime_error{"Failed to load shaders"}; }
5252

53-
constexpr auto vertices = std::array{
54-
Tkge::Graphics::Vertex{.position = {-0.5f, -0.5f}, .colour = kvf::red_v.to_vec4()},
55-
Tkge::Graphics::Vertex{.position = {0.5f, -0.5f}, .colour = kvf::green_v.to_vec4()},
56-
Tkge::Graphics::Vertex{.position = {0.5f, 0.5f}, .colour = kvf::blue_v.to_vec4()},
57-
Tkge::Graphics::Vertex{.position = {-0.5f, 0.5f}, .colour = kvf::yellow_v.to_vec4()},
53+
static constexpr auto Vertices = std::array{
54+
Tkge::Graphics::Vertex{.position = {-200.0f, -200.0f}, .colour = kvf::red_v.to_vec4()},
55+
Tkge::Graphics::Vertex{.position = {200.0f, -200.0f}, .colour = kvf::green_v.to_vec4()},
56+
Tkge::Graphics::Vertex{.position = {200.0f, 200.0f}, .colour = kvf::blue_v.to_vec4()},
57+
Tkge::Graphics::Vertex{.position = {-200.0f, 200.0f}, .colour = kvf::yellow_v.to_vec4()},
5858
};
5959

60-
constexpr auto indices = std::array{
60+
static constexpr auto Indices = std::array{
6161
0u, 1u, 2u, 2u, 3u, 0u,
6262
};
6363

64-
const auto primitive = Tkge::Graphics::Primitive{
65-
.vertices = vertices,
66-
.indices = indices,
64+
static constexpr auto Primitive = Tkge::Graphics::Primitive{
65+
.vertices = Vertices,
66+
.indices = Indices,
6767
};
6868

6969
auto wireframe = false;
@@ -85,7 +85,7 @@ namespace
8585
renderer.BindShader(shader);
8686
renderer.SetLineWidth(lineWidth);
8787
renderer.SetWireframe(wireframe);
88-
renderer.Draw(primitive);
88+
renderer.Draw(Primitive);
8989
}
9090

9191
engine.Present();

Assets/Shaders/Default.vert

280 Bytes
Binary file not shown.

Lib/Include/Tkge/Graphics/Renderer.hpp

+6
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#pragma once
22
#include <Tkge/Graphics/Primitive.hpp>
33
#include <Tkge/Graphics/ResourcePool.hpp>
4+
#include <Tkge/Transform.hpp>
45
#include <kvf/render_pass.hpp>
56

67
namespace Tkge::Graphics
@@ -29,12 +30,17 @@ namespace Tkge::Graphics
2930

3031
explicit operator bool() const { return IsRendering(); }
3132

33+
Transform view{};
34+
3235
private:
36+
[[nodiscard]] bool WriteSets() const;
3337
void BindVboAndDraw(const Primitive& primitive) const;
3438

3539
kvf::RenderPass* _renderPass{};
3640
IResourcePool* _resourcePool{};
3741

42+
vk::Viewport _viewport{};
43+
3844
const Shader* _shader{};
3945
vk::Pipeline _pipeline{};
4046
vk::PolygonMode _polygonMode{vk::PolygonMode::eFill};

Lib/Include/Tkge/Graphics/ResourcePool.hpp

+1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ namespace Tkge::Graphics
1111
{
1212
public:
1313
[[nodiscard]] virtual vk::PipelineLayout PipelineLayout() const = 0;
14+
[[nodiscard]] virtual std::span<const vk::DescriptorSetLayout> SetLayouts() const = 0;
1415

1516
/// \brief Get the Pipeline identified by the input parameters.
1617
/// \param shader Shader that will be used in draw calls (dynamic Pipeline state).

Lib/Include/Tkge/Transform.hpp

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
#pragma once
2+
#include <glm/mat4x4.hpp>
3+
4+
namespace Tkge
5+
{
6+
struct Transform
7+
{
8+
static constexpr auto IdentityMat = glm::mat4{1.0f};
9+
10+
[[nodiscard]] auto ToModel() const -> glm::mat4;
11+
[[nodiscard]] auto ToView() const -> glm::mat4;
12+
[[nodiscard]] auto ToInverseView() const -> glm::mat4;
13+
14+
[[nodiscard]] static constexpr auto Accumulate(const Transform& a, const Transform& b) -> Transform
15+
{
16+
return Transform{
17+
.position = a.position + b.position,
18+
.orientation = a.orientation + b.orientation,
19+
.scale = a.scale * b.scale,
20+
};
21+
}
22+
23+
glm::vec2 position{};
24+
float orientation{};
25+
glm::vec2 scale{1.0f};
26+
};
27+
} // namespace Tkge

Lib/Src/Detail/PipelinePool.hpp

+32-2
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,14 @@ namespace Tkge::Detail
1919
explicit PipelinePool(gsl::not_null<const kvf::RenderDevice*> renderDevice, vk::SampleCountFlagBits framebufferSamples)
2020
: _renderDevice(renderDevice), _framebufferSamples(framebufferSamples)
2121
{
22-
// TODO: descriptor set layouts
23-
_pipelineLayout = renderDevice->get_device().createPipelineLayoutUnique({});
22+
CreateSetLayouts();
23+
CreatePipelineLayout();
2424
}
2525

2626
[[nodiscard]] vk::PipelineLayout PipelineLayout() const { return *_pipelineLayout; }
2727

28+
[[nodiscard]] std::span<const vk::DescriptorSetLayout> SetLayouts() const { return _setLayouts; }
29+
2830
/// \brief Get the Pipeline identified by the input parameters.
2931
/// \param shader Shader that will be used in draw calls (dynamic Pipeline state).
3032
/// \param state Fixed Pipeline state.
@@ -69,10 +71,38 @@ namespace Tkge::Detail
6971
}
7072

7173
private:
74+
void CreateSetLayouts()
75+
{
76+
static constexpr auto StageFlags = vk::ShaderStageFlagBits::eAllGraphics;
77+
// set 0: builtin
78+
auto set0 = std::array<vk::DescriptorSetLayoutBinding, 1>{};
79+
// set 0, binding 0: view
80+
set0[0].setBinding(0).setDescriptorCount(1).setDescriptorType(vk::DescriptorType::eUniformBuffer).setStageFlags(StageFlags);
81+
// TODO: instances, texture bindings
82+
83+
// TODO: set 1: user data
84+
85+
auto dslci = std::array<vk::DescriptorSetLayoutCreateInfo, 1>{};
86+
dslci[0].setBindings(set0);
87+
88+
for (const auto& createInfo : dslci) { _setLayoutStorage.push_back(_renderDevice->get_device().createDescriptorSetLayoutUnique(createInfo)); }
89+
for (const auto& setLayout : _setLayoutStorage) { _setLayouts.push_back(*setLayout); }
90+
}
91+
92+
void CreatePipelineLayout()
93+
{
94+
auto plci = vk::PipelineLayoutCreateInfo{};
95+
plci.setSetLayouts(_setLayouts);
96+
_pipelineLayout = _renderDevice->get_device().createPipelineLayoutUnique(plci);
97+
}
98+
7299
gsl::not_null<const kvf::RenderDevice*> _renderDevice;
73100
vk::SampleCountFlagBits _framebufferSamples;
74101

75102
vk::UniquePipelineLayout _pipelineLayout{};
103+
std::vector<vk::UniqueDescriptorSetLayout> _setLayoutStorage{};
104+
std::vector<vk::DescriptorSetLayout> _setLayouts{};
105+
76106
std::unordered_map<std::size_t, vk::UniquePipeline> _pipelines{};
77107
};
78108
} // namespace Tkge::Detail

Lib/Src/Engine.cpp

+2
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ namespace Tkge
2020

2121
[[nodiscard]] vk::PipelineLayout PipelineLayout() const final { return _pipelinePool.PipelineLayout(); }
2222

23+
[[nodiscard]] std::span<const vk::DescriptorSetLayout> SetLayouts() const final { return _pipelinePool.SetLayouts(); }
24+
2325
[[nodiscard]] vk::Pipeline GetPipeline(const Graphics::Shader& shader, const Graphics::PipelineFixedState& state) final
2426
{
2527
return _pipelinePool.GetPipeline(shader, state);

Lib/Src/Glsl/Default.vert

+5-1
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,15 @@ layout (location = 0) in vec2 aPos;
44
layout (location = 1) in vec4 aColour;
55
layout (location = 2) in vec2 aUv;
66

7+
layout (set = 0, binding = 0) uniform View {
8+
mat4 matVP;
9+
};
10+
711
layout (location = 0) out vec4 outColour;
812

913
void main()
1014
{
1115
outColour = aColour;
1216

13-
gl_Position = vec4(aPos, 0.0, 1.0);
17+
gl_Position = matVP * vec4(aPos, 0.0, 1.0);
1418
}

Lib/Src/Graphics/Renderer.cpp

+45
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
#include <Tkge/Graphics/Renderer.hpp>
2+
#include <glm/gtc/matrix_transform.hpp>
3+
#include <klib/assert.hpp>
4+
#include <klib/flex_array.hpp>
25
#include <kvf/render_device.hpp>
36
#include <kvf/util.hpp>
47
#include <algorithm>
@@ -9,6 +12,7 @@ namespace Tkge::Graphics
912
: _renderPass(renderPass), _resourcePool(resourcePool)
1013
{
1114
_renderPass->begin_render(commandBuffer, kvf::util::to_vk_extent(framebufferSize));
15+
_viewport = _renderPass->to_viewport(kvf::uv_rect_v);
1216
}
1317

1418
void Renderer::EndRender()
@@ -52,9 +56,50 @@ namespace Tkge::Graphics
5256
_renderPass->bind_pipeline(_pipeline);
5357
}
5458

59+
if (!WriteSets()) { return; }
60+
61+
_renderPass->get_command_buffer().setViewport(0, _viewport);
62+
5563
BindVboAndDraw(primitive);
5664
}
5765

66+
bool Renderer::WriteSets() const
67+
{
68+
auto& renderDevice = _renderPass->get_render_device();
69+
70+
const auto setLayouts = _resourcePool->SetLayouts();
71+
auto descriptorSets = std::array<vk::DescriptorSet, 1>{};
72+
KLIB_ASSERT(setLayouts.size() == descriptorSets.size()); // expected set count will change until render flow is stable
73+
if (!renderDevice.allocate_sets(descriptorSets, setLayouts)) { return false; }
74+
75+
auto bufferInfos = klib::FlexArray<vk::DescriptorBufferInfo, 4>{};
76+
auto descriptorWrites = klib::FlexArray<vk::WriteDescriptorSet, 8>{};
77+
const auto pushBufferWrite = [&](vk::DescriptorSet set, std::uint32_t binding, const Buffer& buffer, const vk::DescriptorType type)
78+
{
79+
bufferInfos.push_back({});
80+
auto& dbi = bufferInfos.back();
81+
dbi.setBuffer(buffer.get_buffer()).setRange(buffer.get_size());
82+
auto wds = vk::WriteDescriptorSet{};
83+
wds.setBufferInfo(dbi).setDescriptorCount(1).setDescriptorType(type).setDstSet(set).setDstBinding(binding);
84+
descriptorWrites.push_back(wds);
85+
};
86+
87+
auto& ubo00 = _resourcePool->AllocateBuffer(vk::BufferUsageFlagBits::eUniformBuffer, sizeof(glm::mat4));
88+
const auto halfRenderArea = 0.5f * glm::vec2{_viewport.width, -_viewport.height};
89+
const auto matProj = glm::ortho(-halfRenderArea.x, halfRenderArea.x, -halfRenderArea.y, halfRenderArea.y);
90+
const auto matVP = matProj * view.ToView();
91+
kvf::util::overwrite(ubo00, matVP);
92+
pushBufferWrite(descriptorSets[0], 0, ubo00, vk::DescriptorType::eUniformBuffer);
93+
94+
const auto writeSpan = std::span{descriptorWrites.data(), descriptorWrites.size()};
95+
renderDevice.get_device().updateDescriptorSets(writeSpan, {});
96+
97+
const auto setSpan = std::span{descriptorSets.data(), descriptorSets.size()};
98+
_renderPass->get_command_buffer().bindDescriptorSets(vk::PipelineBindPoint::eGraphics, _resourcePool->PipelineLayout(), 0, setSpan, {});
99+
100+
return true;
101+
}
102+
58103
void Renderer::BindVboAndDraw(const Primitive& primitive) const
59104
{
60105
const auto vertSize = primitive.vertices.size_bytes();

Lib/Src/Transform.cpp

+41
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
#include <Tkge/Transform.hpp>
2+
#include <glm/gtc/matrix_transform.hpp>
3+
4+
namespace Tkge
5+
{
6+
namespace
7+
{
8+
struct Trs
9+
{
10+
glm::mat4 t;
11+
glm::mat4 r;
12+
glm::mat4 s;
13+
14+
explicit Trs(const glm::vec2 position, const float orientation, const glm::vec2 scale)
15+
: t(glm::translate(Transform::IdentityMat, glm::vec3{position, 0.0f})),
16+
r(glm::rotate(Transform::IdentityMat, glm::radians(orientation), glm::vec3{0.0f, 0.0f, 1.0f})),
17+
s(glm::scale(Transform::IdentityMat, glm::vec3{scale, 1.0f}))
18+
{
19+
}
20+
};
21+
} // namespace
22+
23+
auto Transform::ToModel() const -> glm::mat4
24+
{
25+
const auto trs = Trs{position, orientation, scale};
26+
return trs.t * trs.r * trs.s;
27+
}
28+
29+
auto Transform::ToView() const -> glm::mat4
30+
{
31+
const auto trs = Trs{-position, -orientation, scale};
32+
return trs.s * trs.r * trs.t;
33+
}
34+
35+
auto Transform::ToInverseView() const -> glm::mat4
36+
{
37+
if (scale == glm::vec2{0.0f}) { return {}; }
38+
const auto trs = Trs{position, orientation, 1.0f / scale};
39+
return trs.t * trs.r * trs.s;
40+
}
41+
} // namespace Tkge

0 commit comments

Comments
 (0)