Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
9125886
feat(graphic): add frontend RenderState value type
YuanSang0512 Aug 4, 2026
a9f72e8
refactor(graphic): hide StateManager inside Device, add apply_state
YuanSang0512 Aug 4, 2026
566854e
feat(graphic): add uniform types (UniformValue/UniformData/UboBlock)
YuanSang0512 Aug 4, 2026
1a65498
feat(graphic): add RenderCommand and RenderQueue
YuanSang0512 Aug 4, 2026
e742184
feat(graphic): sort render queue and apply uniforms
YuanSang0512 Aug 4, 2026
e49f93e
feat(graphic): route Renderer::draw through the render queue
YuanSang0512 Aug 4, 2026
3827ab0
feat(graphic): add RenderObject reusable draw unit
YuanSang0512 Aug 4, 2026
43a0137
refactor(graphic): split graphic headers into resource/ and render/
YuanSang0512 Aug 4, 2026
3432b06
feat(graphic): per-command viewport; cleanup Renderer draw API
YuanSang0512 Aug 4, 2026
fea1e14
feat(graphic): per-command clear of the render target
YuanSang0512 Aug 4, 2026
ee6940a
feat(graphic): add Material struct; move MAX_TEXTURE_SLOTS to config
YuanSang0512 Aug 4, 2026
e3d83dd
refactor(graphic): RenderObject takes data + Material, hides VAO/VBO/IBO
YuanSang0512 Aug 4, 2026
2e4ba19
feat(graphic): default target/viewport args for Renderer::draw
YuanSang0512 Aug 4, 2026
a03cba8
test(graphic): rename test_window to test_render, use default draw args
YuanSang0512 Aug 4, 2026
248b03c
fix(graphic): harden render queue pipeline
YuanSang0512 Aug 4, 2026
f1fdd95
test(graphic): cover blending, depth, and stencil masking in test_render
YuanSang0512 Aug 4, 2026
41fd08e
Merge branch 'main' of https://github.com/gkit-org/libgkit into featu…
YuanSang0512 Aug 4, 2026
8215f40
docs(graphic): translate comments to English
YuanSang0512 Aug 4, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
82 changes: 41 additions & 41 deletions include/gkit/gkit.hpp
Original file line number Diff line number Diff line change
@@ -1,41 +1,41 @@
#pragma once
/** core **/
#include <gkit/core/input/action.hpp>
#include <gkit/core/input/input.hpp>
#include <gkit/core/input/keys.hpp>
#include <gkit/core/input/mouse.hpp>
#include <gkit/core/log.hpp>
#include <gkit/core/object.hpp>
#include <gkit/core/processer.hpp>
#include <gkit/core/reflect/registry.hpp>
#include <gkit/core/templates/singleton.hpp>
#include <gkit/core/value.hpp>
/** graphic **/
#include <gkit/graphic/Renderer.hpp>
#include <gkit/graphic/Shader.hpp>
/** math **/
#include <gkit/math/color.hpp>
#include <gkit/math/constants.hpp>
#include <gkit/math/matrix3.hpp>
#include <gkit/math/matrix4.hpp>
#include <gkit/math/scalar.hpp>
#include <gkit/math/vector2.hpp>
#include <gkit/math/vector3.hpp>
#include <gkit/math/vector4.hpp>
/** resource **/
#include <gkit/resource/metadata.hpp>
#include <gkit/resource/resource.hpp>
#include <gkit/resource/resource_loader.hpp>
#include <gkit/resource/texture.hpp>
/** scene **/
#include <gkit/scene/2d/object2d.hpp>
#include <gkit/scene/2d/renderable2d.hpp>
#include <gkit/scene/2d/transform2d.hpp>
#include <gkit/scene/unit.hpp>
namespace gkit {} // namespace gkit
#pragma once

/** core **/
#include <gkit/core/input/action.hpp>
#include <gkit/core/input/input.hpp>
#include <gkit/core/input/keys.hpp>
#include <gkit/core/input/mouse.hpp>
#include <gkit/core/log.hpp>
#include <gkit/core/object.hpp>
#include <gkit/core/processer.hpp>
#include <gkit/core/reflect/registry.hpp>
#include <gkit/core/templates/singleton.hpp>
#include <gkit/core/value.hpp>

/** graphic **/
#include <gkit/graphic/render/Renderer.hpp>
#include <gkit/graphic/resource/Shader.hpp>

/** math **/
#include <gkit/math/color.hpp>
#include <gkit/math/constants.hpp>
#include <gkit/math/matrix3.hpp>
#include <gkit/math/matrix4.hpp>
#include <gkit/math/scalar.hpp>
#include <gkit/math/vector2.hpp>
#include <gkit/math/vector3.hpp>
#include <gkit/math/vector4.hpp>

/** resource **/
#include <gkit/resource/metadata.hpp>
#include <gkit/resource/resource.hpp>
#include <gkit/resource/resource_loader.hpp>
#include <gkit/resource/texture.hpp>

/** scene **/
#include <gkit/scene/2d/object2d.hpp>
#include <gkit/scene/2d/renderable2d.hpp>
#include <gkit/scene/2d/transform2d.hpp>
#include <gkit/scene/unit.hpp>

namespace gkit {} // namespace gkit
20 changes: 0 additions & 20 deletions include/gkit/graphic/UniformBuffer.hpp

This file was deleted.

8 changes: 8 additions & 0 deletions include/gkit/graphic/config.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,14 @@ namespace gkit::graphic {
*/
const unsigned int SCR_WIDTH = 500;
const unsigned int SCR_HEIGHT = 500;
/**
* @brief Engine-declared texture slot limit (fixed conservative value)
*
* Most shaders fit within 8 slots; not chasing hardware limits
* (GL_MAX_TEXTURE_IMAGE_UNITS varies by GPU, usually >= 32).
* Start up may assert the hardware supports at least this many.
*/
static constexpr uint32_t MAX_TEXTURE_SLOTS = 8;

/**
* @brief Texture pattern
Expand Down
48 changes: 48 additions & 0 deletions include/gkit/graphic/render/RenderCommand.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
#pragma once

#include "gkit/graphic/config.hpp"
#include "gkit/graphic/render/RenderState.hpp"
#include "gkit/graphic/resource/FrameBuffer.hpp"

#include <cstdint>
#include <optional>

namespace gkit::graphic {

/**
* @brief Viewport rectangle for a render command
*
* Each command carries its own viewport so FBO-targeted commands use the
* FBO size while screen commands use the window size (GL viewport is global
* state, so it must be set per command).
*/
struct Viewport {
int x = 0; // Left coordinate
int y = 0; // Bottom coordinate
int width = 0; // Viewport width
int height = 0; // Viewport height
};

class RenderObject;

/**
* @brief A single draw command referencing a render object
*
* Value type; references (not owns) the RenderObject and its target.
* The command carries a snapshot of the geometry's render state (so two
* commands can share one RenderObject with different states) plus per-draw
* controls (target, viewport, clear, sorting metadata).
*/
struct RenderCommand {
const FrameBuffer* target = nullptr; // Render target (nullptr = screen)
RenderObject* object = nullptr; // Geometry + material source (lazily uploaded on execute)
std::optional<Viewport> viewport; // Viewport to set before drawing; empty = target size
RenderState state; // Render state snapshot (applied before drawing)
uint32_t instance_count = 1; // 1 = non-instanced
bool transparent = false; // Sort front-to-back (opaque) or back-to-front (transparent)
float depth_key = 0.0f; // Depth sort key (filled by upper layer)
bool clear = false; // Whether to clear the target before drawing
ClearFlags clear_flags = ClearFlags::All; // What to clear when clear is set
};

} // namespace gkit::graphic
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
#pragma once

#include "gkit/graphic/FrameBuffer.hpp"
#include "gkit/graphic/IndexBuffer.hpp"
#include "gkit/graphic/RenderBuffer.hpp"
#include "gkit/graphic/Shader.hpp"
#include "gkit/graphic/Texture.hpp"
#include "gkit/graphic/VertexArray.hpp"
#include "gkit/graphic/VertexBuffer.hpp"
#include "gkit/graphic/config.hpp"
#include "gkit/graphic/render/RenderCommand.hpp"
#include "gkit/graphic/render/RenderState.hpp"
#include "gkit/graphic/resource/FrameBuffer.hpp"
#include "gkit/graphic/resource/IndexBuffer.hpp"
#include "gkit/graphic/resource/RenderBuffer.hpp"
#include "gkit/graphic/resource/Shader.hpp"
#include "gkit/graphic/resource/Texture.hpp"
#include "gkit/graphic/resource/VertexArray.hpp"
#include "gkit/graphic/resource/VertexBuffer.hpp"

#include <cstdint>
#include <memory>
Expand Down Expand Up @@ -62,6 +64,19 @@ namespace gkit::graphic {
*/
virtual auto clear(ClearFlags flags) -> void = 0;

/**
* @brief Apply a render state snapshot incrementally
*
* Backends compare against the previously applied state and only change
* what differs (see RHI design doc §6 / render queue design §3.4).
*/
virtual auto apply_state(const RenderState& state) -> void = 0;

/**
* @brief Set the viewport (GL viewport is global state, set per command)
*/
virtual auto set_viewport(const Viewport& viewport) -> void = 0;

/**
* @brief Draw indexed geometry
*/
Expand Down
78 changes: 78 additions & 0 deletions include/gkit/graphic/render/RenderObject.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
#pragma once

#include "gkit/graphic/VertexBufferLayout.hpp"
#include "gkit/graphic/config.hpp"
#include "gkit/graphic/render/RenderDevice.hpp"
#include "gkit/graphic/render/RenderState.hpp"
#include "gkit/graphic/resource/IndexBuffer.hpp"
#include "gkit/graphic/resource/Material.hpp"
#include "gkit/graphic/resource/VertexArray.hpp"
#include "gkit/graphic/resource/VertexBuffer.hpp"

#include <cstdint>
#include <memory>
#include <vector>

namespace gkit::graphic {

/**
* @brief A draw unit defined by CPU data (vertices/indices + material + state)
*
* Users provide vertex/index arrays, a vertex layout, a material, and state.
* The VAO/VBO/IBO creation and binding are hidden: GPU resources are lazily
* created and cached on first draw. Only a RenderCommand built from this
* object is enqueued.
*/
class RenderObject {
public:
/**
* @brief Construct from CPU geometry data, layout, and material
* @param vertices interleaved vertex data
* @param indices index data
* @param layout vertex attribute layout (position/color/uv...)
* @param material material (shader + textures + uniforms)
* @note vertices/indices are copied into the object (owned CPU data).
*/
RenderObject(const std::vector<float>& vertices,
const std::vector<uint32_t>& indices,
const VertexBufferLayout& layout,
const Material& material);

// ---- Material (reusable, replaceable) ----
Material material;

// ---- Render state / target ----
RenderState state;
uint32_t instance_count = 1; // 1 = non-instanced
bool transparent = false; // Sorting class
float depth_key = 0.0f; // Depth sort key
bool clear = false; // Whether to clear the target before drawing
ClearFlags clear_flags = ClearFlags::All; // What to clear when clear is set

/**
* @brief Lazily upload vertices/indices to GPU and return the vertex array
* @param device backend device used to create GPU buffers
* @return reference to the cached vertex array
*/
auto ensure_uploaded(RenderDevice& device) -> const VertexArray&;

/// @brief Access the cached index buffer (valid after ensure_uploaded)
[[nodiscard]] auto index_buffer() -> const IndexBuffer&;

/// @brief Whether GPU resources have been created
[[nodiscard]] auto is_uploaded() const -> bool { return this->uploaded; }

private:
// CPU geometry data (provided by the user)
std::vector<float> vertices;
std::vector<uint32_t> indices;
VertexBufferLayout layout;

// Lazily created GPU resources (hidden from the user)
std::unique_ptr<VertexBuffer> vbo;
std::unique_ptr<VertexArray> vao;
std::unique_ptr<IndexBuffer> ibo;
bool uploaded = false;
};

} // namespace gkit::graphic
43 changes: 43 additions & 0 deletions include/gkit/graphic/render/RenderQueue.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
#pragma once

#include "gkit/graphic/render/RenderCommand.hpp"
#include "gkit/graphic/render/RenderDevice.hpp"

#include <vector>

namespace gkit::graphic {

/**
* @brief Render queue: collects commands, sorts, and executes at flush time
*
* Collects RenderCommand values during a frame and executes them in
* `flush()` after sorting. State application and drawing go through the
* frontend RenderDevice abstraction; the queue never touches GL directly.
*/
class RenderQueue {
public:
/**
* @brief Enqueue a command (copied; command is a value type)
*/
// cmd is deliberately taken by value: the command is copied into the queue.
auto submit(RenderCommand cmd) -> void { this->commands.push_back(cmd); }

/**
* @brief Sort and execute all queued commands, then clear
* @param device Backend device used to apply state and draw
*/
auto flush(RenderDevice& device) -> void;

/**
* @brief Drop all queued commands without executing
*/
auto clear() -> void { this->commands.clear(); }

/// @brief Number of queued commands
[[nodiscard]] auto size() const -> size_t { return this->commands.size(); }

private:
std::vector<RenderCommand> commands;
};

} // namespace gkit::graphic
Loading
Loading