├── .git-blame-ignore-revs
├── src
├── framework
│ ├── ui
│ │ ├── ui_utils.cpp
│ │ ├── imgui_timeline.cpp
│ │ ├── gizmo_2d.h
│ │ ├── gizmo_2d.cpp
│ │ ├── ui_utils.h
│ │ └── io.h
│ ├── camera
│ │ ├── camera_2d.cpp
│ │ ├── camera_2d.h
│ │ ├── flyover_camera.h
│ │ ├── orbit_camera.h
│ │ ├── camera_3d.h
│ │ ├── flyover_camera.cpp
│ │ ├── orbit_camera.cpp
│ │ ├── camera_3d.cpp
│ │ └── camera.h
│ ├── utils
│ │ ├── json_utils.h
│ │ ├── timer.h
│ │ ├── hash.cpp
│ │ ├── json_utils.cpp
│ │ ├── timer.cpp
│ │ ├── utils.h
│ │ └── hash.h
│ ├── nodes
│ │ ├── camera.cpp
│ │ ├── node_binary_format.h
│ │ ├── node_factory.cpp
│ │ ├── camera.h
│ │ ├── environment_3d.h
│ │ ├── node_factory.h
│ │ ├── skeleton_helper_3d.h
│ │ ├── viewport_3d.h
│ │ ├── directional_light_3d.h
│ │ ├── omni_light_3d.h
│ │ ├── joint_3d.h
│ │ ├── mesh_instance_3d.h
│ │ ├── viewport_3d.cpp
│ │ ├── spot_light_3d.h
│ │ ├── text_3d.h
│ │ ├── skeleton_instance_3d.h
│ │ ├── look_at_ik_3d.h
│ │ ├── environment_3d.cpp
│ │ ├── skeleton_helper_3d.cpp
│ │ ├── animation_player.h
│ │ ├── node_3d.h
│ │ ├── light_3d.h
│ │ ├── gs_node.h
│ │ ├── slider_2d.h
│ │ └── container_2d.h
│ ├── parsers
│ │ ├── parse_ply.h
│ │ ├── parse_vdb.h
│ │ ├── parse_obj.h
│ │ ├── parse_scene.h
│ │ ├── parser.cpp
│ │ ├── parse_gltf.h
│ │ ├── parse_scene.cpp
│ │ └── parser.h
│ ├── animation
│ │ ├── solvers
│ │ │ ├── ccd_solver.h
│ │ │ ├── fabrik_solver.h
│ │ │ ├── jacobian_solver.h
│ │ │ └── ik_solver.h
│ │ ├── blend_animation.h
│ │ ├── pose.h
│ │ ├── skeleton.h
│ │ ├── animation.h
│ │ ├── pose.cpp
│ │ ├── track.h
│ │ └── interpolator.h
│ ├── colors.h
│ ├── math
│ │ ├── frustum_cull.h
│ │ ├── aabb.h
│ │ └── transform.h
│ ├── resources
│ │ ├── resource.h
│ │ └── resource.cpp
│ └── input_xr.h
├── graphics
│ ├── graphics_utils.h
│ ├── backend_include.h
│ ├── debug
│ │ ├── renderdoc_capture.h
│ │ └── renderdoc_capture.cpp
│ ├── uniform.h
│ ├── primitives
│ │ ├── primitive_mesh.h
│ │ ├── primitive_mesh.cpp
│ │ ├── box_mesh.h
│ │ ├── cone_mesh.h
│ │ ├── sphere_mesh.h
│ │ ├── capsule_mesh.h
│ │ ├── torus_mesh.h
│ │ ├── quad_mesh.h
│ │ ├── cylinder_mesh.h
│ │ ├── cone_mesh.cpp
│ │ ├── box_mesh.cpp
│ │ ├── sphere_mesh.cpp
│ │ ├── capsule_mesh.cpp
│ │ └── torus_mesh.cpp
│ ├── font_common.h
│ ├── graphics_utils.cpp
│ ├── kernels
│ │ ├── prefix_sum_kernel.h
│ │ └── radix_sort_kernel.h
│ ├── uniforms_structs.h
│ ├── font.h
│ ├── uniform.cpp
│ ├── mesh.h
│ ├── hdre.h
│ └── pipeline.h
├── .editorconfig
├── engine
│ ├── scene_binary_format.h
│ ├── scene.h
│ └── engine.h
├── includes.h
└── xr
│ ├── xr_context.cpp
│ └── webxr
│ └── webxr_context.h
├── docs
├── images
│ ├── upf.png
│ ├── Node_scheme.png
│ ├── logo_maxr_main_sRGB.png
│ ├── logo_maxr_main_sRGB_light.png
│ └── miciu-cofinanciadoUE-aei.png
├── ui.html
├── xr.html
├── support.html
├── reference
│ ├── rendering-pipeline-desc.html
│ ├── scene.html
│ ├── uniform.html
│ ├── mesh.html
│ ├── pipeline.html
│ ├── shader.html
│ └── mesh-instance-3d.html
├── js-bindings.html
├── disk-storage.html
└── materials.html
├── .gitignore
├── data
└── shaders
│ ├── mipmaps.wgsl
│ ├── quad_mirror.wgsl
│ ├── pbr_material.wgsl
│ ├── mesh_includes.wgsl
│ ├── AABB_shader.wgsl
│ ├── mesh_transparent.wgsl
│ ├── kernels
│ └── radix_sort_reorder.wgsl
│ ├── mesh_shadow.wgsl
│ ├── ui
│ ├── ui_panel.wgsl
│ ├── ui_texture.wgsl
│ ├── ui_ray_pointer.wgsl
│ ├── ui_group.wgsl
│ ├── ui_text_shadow.wgsl
│ └── ui_includes.wgsl
│ ├── mesh_texture_cube.wgsl
│ ├── sdf_fonts.wgsl
│ ├── brdf_lut_gen.wgsl
│ ├── tonemappers.wgsl
│ ├── gaussian_splatting
│ ├── gs_render.wgsl
│ └── gs_covariance.wgsl
│ └── mesh_grid.wgsl
├── LICENSE
├── libraries
└── glfw3webgpu
│ ├── CMakeLists.txt
│ └── glfw3webgpu.hpp
├── .gitmodules
└── glsl_builder.py
/.git-blame-ignore-revs:
--------------------------------------------------------------------------------
1 | # .git-blame-ignore-revs
--------------------------------------------------------------------------------
/src/framework/ui/ui_utils.cpp:
--------------------------------------------------------------------------------
1 | #include "ui_utils.h"
2 |
--------------------------------------------------------------------------------
/src/framework/ui/imgui_timeline.cpp:
--------------------------------------------------------------------------------
1 | #include "imgui_timeline.h"
2 |
--------------------------------------------------------------------------------
/docs/images/upf.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/upf-gti/wgpuEngine/HEAD/docs/images/upf.png
--------------------------------------------------------------------------------
/docs/images/Node_scheme.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/upf-gti/wgpuEngine/HEAD/docs/images/Node_scheme.png
--------------------------------------------------------------------------------
/docs/images/logo_maxr_main_sRGB.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/upf-gti/wgpuEngine/HEAD/docs/images/logo_maxr_main_sRGB.png
--------------------------------------------------------------------------------
/docs/ui.html:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/docs/images/logo_maxr_main_sRGB_light.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/upf-gti/wgpuEngine/HEAD/docs/images/logo_maxr_main_sRGB_light.png
--------------------------------------------------------------------------------
/docs/images/miciu-cofinanciadoUE-aei.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/upf-gti/wgpuEngine/HEAD/docs/images/miciu-cofinanciadoUE-aei.png
--------------------------------------------------------------------------------
/src/framework/camera/camera_2d.cpp:
--------------------------------------------------------------------------------
1 | #include "camera_2d.h"
2 |
3 | Camera2D::Camera2D()
4 | {
5 | view = glm::identity();
6 | }
7 |
--------------------------------------------------------------------------------
/src/framework/camera/camera_2d.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "camera.h"
4 |
5 | class Camera2D : public Camera {
6 |
7 | public:
8 |
9 | Camera2D();
10 | };
11 |
--------------------------------------------------------------------------------
/src/framework/utils/json_utils.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "rapidjson/fwd.h"
4 |
5 | #include
6 |
7 | rapidjson::Document load_json(const std::string& filename);
8 |
--------------------------------------------------------------------------------
/src/graphics/graphics_utils.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "glm/glm.hpp"
4 |
5 | struct WebGPUContext;
6 |
7 | glm::uvec2 find_optimal_dispatch_size(WebGPUContext* webgpu_context, uint32_t workgroup_count);
8 |
--------------------------------------------------------------------------------
/src/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 | [*.{h,cpp,hpp}]
4 | charset = utf-8
5 | indent_style = space
6 | indent_size = 4
7 | tab_width = 4
8 | trim_trailing_whitespace = true
9 | insert_final_newline = true
10 |
--------------------------------------------------------------------------------
/src/framework/nodes/camera.cpp:
--------------------------------------------------------------------------------
1 | #include "camera.h"
2 |
3 | #include "framework/nodes/node_factory.h"
4 |
5 | REGISTER_NODE_CLASS(EntityCamera)
6 |
7 | EntityCamera::EntityCamera() : Node3D()
8 | {
9 |
10 | }
11 |
--------------------------------------------------------------------------------
/src/framework/nodes/node_binary_format.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 |
5 | constexpr uint8_t MAX_NODE_NAME_SIZE = 64;
6 |
7 | struct sNodeBinaryHeader {
8 | uint64_t children_count = 0;
9 | };
10 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | build/
2 | build-web/
3 | .cache/
4 | .vscode/
5 | libraries/tinyobjloader/
6 | libraries/stb/
7 | libraries/nlohmann_json/
8 | libraries/tiny_gltf/
9 | src/xr/dawnxr/
10 | *.gen.h
11 | .DS_Store
12 | **/.DS_Store
--------------------------------------------------------------------------------
/src/engine/scene_binary_format.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 |
5 | constexpr uint8_t MAX_SCENE_NAME_SIZE = 64;
6 |
7 | struct sSceneBinaryHeader {
8 | uint8_t version = 1;
9 | uint64_t node_count = 0;
10 | };
11 |
--------------------------------------------------------------------------------
/src/framework/camera/flyover_camera.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "camera_3d.h"
4 |
5 | class FlyoverCamera : public Camera3D {
6 |
7 | public:
8 |
9 | FlyoverCamera();
10 |
11 | void update(float delta_time) override;
12 | };
13 |
--------------------------------------------------------------------------------
/docs/xr.html:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/framework/parsers/parse_ply.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "parser.h"
4 |
5 | class PlyParser : public Parser {
6 | public:
7 |
8 | bool parse(std::string file_path, std::vector& entities, uint32_t flags = PARSE_DEFAULT) override;
9 | };
10 |
--------------------------------------------------------------------------------
/src/framework/parsers/parse_vdb.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "parser.h"
4 |
5 | class VdbParser : public Parser {
6 | public:
7 |
8 | bool parse(std::string file_path, std::vector& entities, uint32_t flags = PARSE_DEFAULT) override;
9 | };
10 |
--------------------------------------------------------------------------------
/src/graphics/backend_include.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #if defined(BACKEND_DX12)
4 | #include
5 | #elif defined(BACKEND_VULKAN)
6 | #include "dawn/native/VulkanBackend.h"
7 | #elif defined(BACKEND_METAL)
8 | #include "dawn/native/MetalBackend.h"
9 | #endif
--------------------------------------------------------------------------------
/src/framework/parsers/parse_obj.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 |
5 | class MeshInstance3D;
6 |
7 | void parse_obj(const std::string& obj_path, MeshInstance3D* entity_mesh, bool create_aabb = true);
8 | MeshInstance3D* parse_obj(const std::string& obj_path, bool create_aabb = true);
9 |
--------------------------------------------------------------------------------
/src/framework/nodes/node_factory.cpp:
--------------------------------------------------------------------------------
1 | #include "node_factory.h"
2 |
3 | #include "node.h"
4 |
5 | #include "assert.h"
6 |
7 | NodeRegistration::NodeRegistration(const std::string& node_name, NodeFactory node_ctor)
8 | {
9 | NodeRegistry::get_instance()->register_class(node_name, node_ctor);
10 | }
11 |
--------------------------------------------------------------------------------
/src/framework/nodes/camera.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "framework/nodes/node_3d.h"
4 | #include "framework/camera/camera_3d.h"
5 |
6 | class EntityCamera : public Camera3D, public Node3D {
7 |
8 | protected:
9 |
10 |
11 | public:
12 |
13 | EntityCamera();
14 | virtual ~EntityCamera() {};
15 |
16 | // void update(float delta_time) override;
17 | };
18 |
--------------------------------------------------------------------------------
/src/framework/nodes/environment_3d.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "mesh_instance_3d.h"
4 |
5 | class Environment3D : public MeshInstance3D {
6 |
7 | public:
8 |
9 | Environment3D();
10 | virtual ~Environment3D() {};
11 |
12 | void update(float delta_time) override;
13 |
14 | Texture* get_texture() const;
15 | void set_texture(const std::string& texture_path);
16 | };
17 |
--------------------------------------------------------------------------------
/src/framework/parsers/parse_scene.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 |
5 | class Node;
6 | class Node3D;
7 | class MeshInstance3D;
8 |
9 | bool parse_scene(const char* scene_path, std::vector &entities, bool fill_surface_data = false, Node3D* root = nullptr);
10 | MeshInstance3D* parse_mesh(const char* mesh_path, bool create_aabb = true, bool fill_surface_data = false);
11 |
--------------------------------------------------------------------------------
/src/framework/animation/solvers/ccd_solver.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "ik_solver.h"
4 |
5 | class CCDSolver : public IKSolver {
6 | protected:
7 |
8 | Transform aux_parent; // in global
9 |
10 | public:
11 |
12 | bool solve(const Transform& target) override;
13 |
14 | void apply_ball_socket_constraint(int i, float limit_angle);
15 | void apply_hinge_socket_constraint(int i, const glm::vec3& axis);
16 | };
17 |
--------------------------------------------------------------------------------
/docs/support.html:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/framework/nodes/node_factory.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 |
5 | class Node;
6 |
7 | typedef Node* (*NodeFactory)(void);
8 |
9 | class NodeRegistration
10 | {
11 | public:
12 | NodeRegistration(const std::string& node_name, NodeFactory node_ctor);
13 | };
14 |
15 | #define REGISTER_NODE_CLASS(node_ctor) \
16 | NodeRegistration _module_registration_ ## node_ctor(#node_ctor, []() -> Node* { return new node_ctor(); });
17 |
--------------------------------------------------------------------------------
/src/framework/camera/orbit_camera.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "camera_3d.h"
4 |
5 | class OrbitCamera : public Camera3D {
6 |
7 | public:
8 |
9 | OrbitCamera();
10 |
11 | void update(float delta_time) override;
12 |
13 | void look_at(const glm::vec3& eye, const glm::vec3& center, const glm::vec3& up, bool reset_internals = true) override;
14 |
15 | LerpedValue distance_lerp;
16 | float distance = 0.0f;
17 | };
18 |
--------------------------------------------------------------------------------
/src/graphics/debug/renderdoc_capture.h:
--------------------------------------------------------------------------------
1 | #ifndef __EMSCRIPTEN__
2 | #include "renderdoc_app.h"
3 | #endif
4 |
5 | class RenderdocCapture {
6 |
7 | #ifndef __EMSCRIPTEN__
8 | static RENDERDOC_API_1_6_0* rdoc_api;
9 | #endif
10 |
11 | static bool capture_started;
12 |
13 | public:
14 |
15 | static void init();
16 | static void start_capture_frame();
17 | static void end_capture_frame();
18 | static bool is_capture_started();
19 | };
20 |
21 |
--------------------------------------------------------------------------------
/src/graphics/uniform.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "includes.h"
4 |
5 | #include
6 | #include
7 |
8 | struct Uniform {
9 |
10 | Uniform();
11 | ~Uniform();
12 |
13 | void destroy();
14 |
15 | std::variant data;
16 |
17 | uint32_t binding = 0;
18 | uint64_t buffer_size = 0;
19 |
20 | WGPUBindGroupEntry get_bind_group_entry() const;
21 | };
22 |
--------------------------------------------------------------------------------
/src/framework/nodes/skeleton_helper_3d.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "framework/nodes/mesh_instance_3d.h"
4 |
5 | class Skeleton;
6 |
7 | class SkeletonHelper3D : public MeshInstance3D {
8 |
9 | Skeleton* skeleton = nullptr;
10 |
11 | void inner_update();
12 |
13 | public:
14 |
15 | SkeletonHelper3D(Skeleton* new_skeleton, Node3D* parent = nullptr);
16 |
17 | virtual void initialize() override;
18 |
19 | void update(float delta_time) override;
20 | };
21 |
22 |
--------------------------------------------------------------------------------
/src/includes.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #if !defined(__EMSCRIPTEN__)
4 | // NOTE: Uncomment this in order to force the XR Support
5 | // Otherwise only available on Windows
6 | //#define XR_SUPPORT
7 | //#define USE_MIRROR_WINDOW
8 | #endif
9 |
10 | #include
11 |
12 | #ifdef __EMSCRIPTEN__
13 | #include
14 | #endif
15 |
16 | enum eEYE {
17 | EYE_LEFT,
18 | EYE_RIGHT,
19 | EYE_COUNT // Let's assume this will never be different to 2...
20 | };
21 |
--------------------------------------------------------------------------------
/src/graphics/primitives/primitive_mesh.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "graphics/mesh.h"
4 |
5 | class PrimitiveMesh : public Mesh
6 | {
7 | protected:
8 |
9 | Surface* surface = nullptr;
10 |
11 | glm::vec3 color = {1.0f, 1.0f, 1.0f};
12 |
13 | bool dirty = false;
14 |
15 | virtual void build_mesh() {}
16 |
17 | public:
18 |
19 | PrimitiveMesh(const glm::vec3& new_color);
20 |
21 | void render_gui() override;
22 |
23 | void set_color(const glm::vec3& new_color);
24 | };
25 |
--------------------------------------------------------------------------------
/src/graphics/font_common.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "glm/vec2.hpp"
4 | #include "glm/vec3.hpp"
5 |
6 | struct CKerning {
7 | int first;
8 | int second;
9 | int amount;
10 | };
11 |
12 | struct Character {
13 | int id;
14 | int index;
15 | char character;
16 | glm::vec2 size;
17 | glm::vec2 offset;
18 | int xadvance;
19 | int chnl;
20 | glm::vec2 pos;
21 | int page;
22 |
23 | // Mesh properties
24 | glm::vec3 vertices[6];
25 | glm::vec2 uvs[6];
26 | };
27 |
--------------------------------------------------------------------------------
/src/framework/animation/solvers/fabrik_solver.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "ik_solver.h"
4 |
5 | class FABRIKSolver : public IKSolver {
6 | protected:
7 | std::vector world_chain;
8 | std::vector lengths;
9 |
10 | void ik_chain_to_world();
11 | void iterate_forward(const glm::vec3& goal);
12 | void iterate_backward(const glm::vec3& base);
13 | void world_to_ik_chain();
14 |
15 | public:
16 | void resize(size_t new_size) override;
17 | bool solve(const Transform& target) override;
18 | };
19 |
--------------------------------------------------------------------------------
/src/framework/ui/gizmo_2d.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "glm/mat4x4.hpp"
4 |
5 | #include "imgui.h"
6 | #include "framework/utils/ImGuizmo.h"
7 |
8 | class Gizmo2D {
9 | #ifdef __EMSCRIPTEN__
10 | public:
11 | #endif
12 |
13 | ImGuizmo::OPERATION operation = ImGuizmo::TRANSLATE;
14 | ImGuizmo::MODE mode = ImGuizmo::WORLD;
15 |
16 | public:
17 |
18 | void set_mode(ImGuizmo::MODE new_mode);
19 | void set_operation(ImGuizmo::OPERATION new_operation);
20 |
21 | bool render(const glm::mat4x4& m_view, const glm::mat4x4& m_proj, glm::mat4x4& m_model);
22 | };
23 |
--------------------------------------------------------------------------------
/src/framework/utils/timer.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 |
5 | class Timer {
6 | std::chrono::high_resolution_clock::time_point begin;
7 |
8 | template
9 | double get_elapsed_time()
10 | {
11 | std::chrono::high_resolution_clock::time_point end = std::chrono::high_resolution_clock::now();
12 | return std::chrono::duration(end - begin).count();
13 | }
14 |
15 | public:
16 |
17 | void start();
18 |
19 | void print_elapsed_time_s();
20 | void print_elapsed_time_ms();
21 | void print_elapsed_time_ns();
22 | };
23 |
--------------------------------------------------------------------------------
/src/graphics/graphics_utils.cpp:
--------------------------------------------------------------------------------
1 | #include "graphics_utils.h"
2 |
3 | #include "webgpu_context.h"
4 |
5 | glm::uvec2 find_optimal_dispatch_size(WebGPUContext* webgpu_context, uint32_t workgroup_count)
6 | {
7 | glm::uvec2 dispatch_size = { workgroup_count, 1 };
8 |
9 | if (workgroup_count > webgpu_context->supported_limits.maxComputeWorkgroupsPerDimension) {
10 | uint32_t x = static_cast(floor(sqrt(workgroup_count)));
11 | uint32_t y = static_cast(ceil(workgroup_count / x));
12 |
13 | dispatch_size.x = x;
14 | dispatch_size.y = y;
15 | }
16 |
17 | return dispatch_size;
18 | }
19 |
--------------------------------------------------------------------------------
/src/framework/animation/solvers/jacobian_solver.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "ik_solver.h"
4 |
5 | class JacobianSolver : public IKSolver {
6 |
7 | std::vector local_axis_x_joint;
8 | std::vector local_axis_y_joint;
9 | std::vector local_axis_z_joint;
10 |
11 | public:
12 |
13 | float amount = 0.05f;
14 |
15 | Transform& operator[](uint32_t index);
16 |
17 | void add_revolute_joint(const Transform& joint_transform);
18 |
19 | void set_chain(const std::vector& chain);
20 | void set_rotation_axis();
21 |
22 | bool solve(const Transform& target) override;
23 | };
24 |
--------------------------------------------------------------------------------
/src/framework/colors.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "glm/vec4.hpp"
4 |
5 | typedef glm::vec4 Color;
6 |
7 | namespace colors {
8 | const Color WHITE = Color(1.f, 1.f, 1.f, 1.0f);
9 | const Color BLACK = Color(0.f, 0.f, 0.f, 1.0f);
10 | const Color RED = Color(1.f, 0.f, 0.f, 1.0f);
11 | const Color GREEN = Color(0.f, 1.f, 0.f, 1.0f);
12 | const Color BLUE = Color(0.f, 0.f, 1.f, 1.0f);
13 | const Color PURPLE = Color(1.f, 0.f, 1.f, 1.0f);
14 | const Color YELLOW = Color(1.f, 1.f, 0.f, 1.0f);
15 | const Color CYAN = Color(0.f, 1.f, 1.f, 1.0f);
16 | const Color GRAY = Color(0.4f, 0.4f, 0.4f, 1.0f);
17 | const Color RUST = Color(0.82f, 0.35f, 0.15f, 1.0f);
18 | }
19 |
--------------------------------------------------------------------------------
/src/framework/nodes/viewport_3d.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "mesh_instance_3d.h"
4 | #include "graphics/material.h"
5 | #include "graphics/surface.h"
6 |
7 | class Node2D;
8 |
9 | /*
10 | * This 3D Node allows to use a 2D UI in 3D
11 | */
12 |
13 | class Viewport3D : public Node3D {
14 |
15 | bool active = true;
16 |
17 | Node2D* root = nullptr;
18 |
19 | glm::vec2 viewport_size = glm::vec2(0.0f);
20 |
21 | public:
22 |
23 | Viewport3D(Node2D* root_2d);
24 | ~Viewport3D();
25 |
26 | virtual void update(float delta_time) override;
27 |
28 | void set_viewport_size(const glm::vec2& new_size);
29 | void set_active(bool value) { active = value; }
30 | };
31 |
--------------------------------------------------------------------------------
/src/framework/camera/camera_3d.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "camera.h"
4 |
5 | class Node3D;
6 |
7 | class Camera3D : public Camera {
8 |
9 | public:
10 |
11 | Camera3D() = default;
12 |
13 | void apply_movement(const glm::vec2& movement);
14 |
15 | virtual void update(float delta_time);
16 |
17 | virtual void look_at(const glm::vec3& eye, const glm::vec3& center, const glm::vec3& up, bool reset_internals = true);
18 |
19 | void look_at_node(Node3D* entity);
20 |
21 | protected:
22 |
23 | float delta_yaw = 0.0f;
24 | float delta_pitch = 0.0f;
25 |
26 | LerpedValue delta_yaw_lerp;
27 | LerpedValue delta_pitch_lerp;
28 | LerpedValue eye_lerp;
29 | };
30 |
--------------------------------------------------------------------------------
/src/graphics/primitives/primitive_mesh.cpp:
--------------------------------------------------------------------------------
1 | #include "primitive_mesh.h"
2 |
3 | #include "imgui.h"
4 |
5 | PrimitiveMesh::PrimitiveMesh(const glm::vec3& new_color)
6 | : color(new_color)
7 | {
8 | mesh_type = "";
9 |
10 | surface = new Surface();
11 |
12 | add_surface(surface);
13 | }
14 |
15 | void PrimitiveMesh::set_color(const glm::vec3& new_color)
16 | {
17 | color = new_color;
18 |
19 | build_mesh();
20 | }
21 |
22 | void PrimitiveMesh::render_gui()
23 | {
24 | ImGui::Text("Color");
25 | ImGui::SameLine(200);
26 | ImGui::PushItemWidth(ImGui::GetContentRegionAvail().x);
27 | if (ImGui::ColorEdit3("##Color", &color.x)) {
28 | dirty = true;
29 | }
30 |
31 | Mesh::render_gui();
32 | }
33 |
--------------------------------------------------------------------------------
/src/framework/nodes/directional_light_3d.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "light_3d.h"
4 |
5 | class MeshInstance3D;
6 | class Material;
7 |
8 | class DirectionalLight3D : public Light3D {
9 |
10 | MeshInstance3D* debug_mesh_h = nullptr;
11 | MeshInstance3D* debug_mesh_v = nullptr;
12 |
13 | Material* debug_material = nullptr;
14 |
15 | public:
16 |
17 | DirectionalLight3D();
18 | ~DirectionalLight3D();
19 |
20 | virtual void render() override;
21 |
22 | void render_gui() override;
23 |
24 | void set_color(const glm::vec3& color) override;
25 |
26 | void get_uniform_data(sLightUniformData& data) override;
27 |
28 | void parse(std::ifstream& binary_scene_file) override;
29 |
30 | void create_debug_meshes() override;
31 |
32 | };
33 |
--------------------------------------------------------------------------------
/src/framework/nodes/omni_light_3d.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "light_3d.h"
4 |
5 | class MeshInstance3D;
6 | class Material;
7 |
8 | class OmniLight3D : public Light3D {
9 |
10 | MeshInstance3D* debug_mesh_h = nullptr;
11 | MeshInstance3D* debug_mesh_v = nullptr;
12 |
13 | Material* debug_material = nullptr;
14 |
15 | public:
16 |
17 | OmniLight3D();
18 | ~OmniLight3D();
19 |
20 | virtual void render() override;
21 |
22 | void render_gui() override;
23 |
24 | void set_color(const glm::vec3& color) override;
25 | void set_range(float value) override;
26 |
27 | void get_uniform_data(sLightUniformData& data) override;
28 |
29 | void parse(std::ifstream& binary_scene_file) override;
30 |
31 | void create_debug_meshes() override;
32 | };
33 |
--------------------------------------------------------------------------------
/src/framework/ui/gizmo_2d.cpp:
--------------------------------------------------------------------------------
1 | #include "gizmo_2d.h"
2 |
3 | #include "graphics/renderer.h"
4 |
5 | #include "framework/input.h"
6 | #include "framework/camera/camera.h"
7 |
8 | #include
9 |
10 | void Gizmo2D::set_mode(ImGuizmo::MODE new_mode)
11 | {
12 | this->mode = new_mode;
13 | }
14 |
15 | void Gizmo2D::set_operation(ImGuizmo::OPERATION new_operation)
16 | {
17 | this->operation = new_operation;
18 | }
19 |
20 | bool Gizmo2D::render(const glm::mat4x4& m_view, const glm::mat4x4& m_proj, glm::mat4x4& m_model)
21 | {
22 | const ImGuiIO& io = ImGui::GetIO();
23 | ImGuizmo::SetRect(0, 0, io.DisplaySize.x, io.DisplaySize.y);
24 |
25 | return ImGuizmo::Manipulate(glm::value_ptr(m_view), glm::value_ptr(m_proj), operation, mode, glm::value_ptr(m_model));
26 | }
27 |
--------------------------------------------------------------------------------
/src/graphics/primitives/box_mesh.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "graphics/primitives/primitive_mesh.h"
4 |
5 | class BoxMesh : public PrimitiveMesh
6 | {
7 | float width = 1.0f;
8 | float height = 1.0f;
9 | float depth = 1.0f;
10 |
11 | void build_mesh() override;
12 |
13 | public:
14 |
15 | BoxMesh(float width = 1.f, float height = 1.f, float depth = 1.f, const glm::vec3& color = { 1.f, 1.f, 1.f });
16 |
17 | void render_gui() override;
18 |
19 | float get_width() const { return width; }
20 | float get_height() const { return height; }
21 | float get_depth() const { return depth; }
22 |
23 | void set_width(float new_width);
24 | void set_height(float new_height);
25 | void set_depth(float new_depth);
26 | void set_size(const glm::vec3& size);
27 | };
28 |
--------------------------------------------------------------------------------
/src/graphics/primitives/cone_mesh.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "graphics/primitives/primitive_mesh.h"
4 |
5 | class ConeMesh : public PrimitiveMesh
6 | {
7 | float radius = 0.5f;
8 | float height = 2.0f;
9 |
10 | uint32_t segments = 64u;
11 |
12 | void build_mesh() override;
13 |
14 | public:
15 |
16 | ConeMesh(float radius = 0.5f, float height = 2.0f, uint32_t segments = 64u, const glm::vec3& color = { 1.f, 1.f, 1.f });
17 |
18 | void render_gui() override;
19 |
20 | float get_radius() const { return radius; }
21 | float get_height() const { return height; }
22 | uint32_t get_segments() const { return segments; }
23 |
24 | void set_radius(float new_radius);
25 | void set_height(float new_height);
26 | void set_segments(uint32_t new_segments);
27 | };
28 |
--------------------------------------------------------------------------------
/src/framework/parsers/parser.cpp:
--------------------------------------------------------------------------------
1 | #include "parser.h"
2 |
3 | #include
4 | #include
5 |
6 | std::vector Parser::async_parsers;
7 |
8 | void Parser::poll_async_parsers()
9 | {
10 | std::vector::iterator it = async_parsers.begin();
11 | while (it != async_parsers.end())
12 | {
13 | Parser* parser = *it;
14 | if (parser->async_future.valid() && parser->async_future.wait_for(std::chrono::milliseconds(1)) == std::future_status::ready) {
15 |
16 | parser->on_async_finished();
17 |
18 | parser->async_callback(parser->async_nodes, parser->async_future.get());
19 |
20 | delete* it;
21 | it = async_parsers.erase(it);
22 | }
23 | else {
24 | it++;
25 | }
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/src/engine/scene.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 | #include
5 |
6 | class Node;
7 |
8 | class Scene {
9 |
10 | std::vector nodes;
11 |
12 | std::string name;
13 |
14 | public:
15 | Scene();
16 | Scene(const std::string& name);
17 | ~Scene();
18 |
19 | void add_node(Node* node, int idx = -1);
20 | void add_nodes(const std::vector& nodes_to_add, int idx = -1);
21 |
22 | void remove_node(Node* node);
23 |
24 | void set_name(const std::string& name);
25 |
26 | std::vector& get_nodes();
27 | const std::string& get_name() const { return name; }
28 |
29 | void delete_all();
30 |
31 | void serialize(const std::string& path);
32 | void parse(const std::string& path);
33 |
34 | void update(float delta_time);
35 | void render();
36 | };
37 |
--------------------------------------------------------------------------------
/src/graphics/primitives/sphere_mesh.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "graphics/primitives/primitive_mesh.h"
4 |
5 | class SphereMesh : public PrimitiveMesh
6 | {
7 | float radius = 0.5f;
8 |
9 | uint32_t rings = 32u;
10 | uint32_t ring_segments = 64u;
11 |
12 | void build_mesh() override;
13 |
14 | public:
15 |
16 | SphereMesh(float radius = 0.5f, uint32_t rings = 32u, uint32_t ring_segments = 64u, const glm::vec3& color = { 1.f, 1.f, 1.f });
17 |
18 | void render_gui() override;
19 |
20 | float get_radius() const { return radius; }
21 | uint32_t get_rings() const { return rings; }
22 | uint32_t get_ring_segments() const { return ring_segments; }
23 |
24 | void set_radius(float new_radius);
25 | void set_rings(uint32_t new_rings);
26 | void set_ring_segments(uint32_t new_ring_segments);
27 | };
28 |
--------------------------------------------------------------------------------
/src/framework/nodes/joint_3d.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "framework/nodes/node_3d.h"
4 |
5 | class Pose;
6 | class SkeletonInstance3D;
7 | class MeshInstance3D;
8 |
9 | class Joint3D : public Node3D {
10 |
11 | uint32_t index = 0;
12 | Pose* pose = nullptr;
13 |
14 | MeshInstance3D* mesh_instance = nullptr;
15 | MeshInstance3D* selected_mesh_instance = nullptr;
16 |
17 | public:
18 |
19 | static Joint3D* selected_joint;
20 |
21 | Joint3D();
22 | ~Joint3D();
23 |
24 | Transform get_global_transform() override;
25 | uint32_t get_index() { return index; }
26 |
27 | void set_index(int32_t new_index) { index = new_index; }
28 | void set_pose(Pose* ref_pose) { pose = ref_pose; };
29 | void set_global_transform(const Transform& new_transform) override;
30 |
31 | void render() override;
32 | };
33 |
34 |
--------------------------------------------------------------------------------
/src/framework/utils/hash.cpp:
--------------------------------------------------------------------------------
1 | #include "hash.h"
2 |
3 | bool RenderPipelineKey::operator==(const RenderPipelineKey& other) const
4 | {
5 | return (shader == other.shader
6 | && color_target.format == other.color_target.format
7 | && color_target.writeMask == other.color_target.writeMask
8 | && color_target.blend == other.color_target.blend
9 | && description.cull_mode == other.description.cull_mode
10 | && description.topology == other.description.topology
11 | && description.depth_read == other.description.depth_read
12 | && description.depth_write == other.description.depth_write
13 | && description.blending_enabled == other.description.blending_enabled
14 | && description.depth_compare == other.description.depth_compare
15 | && pipeline_layout == other.pipeline_layout);
16 | }
17 |
--------------------------------------------------------------------------------
/data/shaders/mipmaps.wgsl:
--------------------------------------------------------------------------------
1 | @group(0) @binding(0) var previousMipLevel: texture_2d;
2 |
3 | #ifdef RGBA8_UNORM
4 | @group(0) @binding(1) var nextMipLevel: texture_storage_2d;
5 | #endif
6 |
7 | #ifdef RGBA32_FLOAT
8 | @group(0) @binding(1) var nextMipLevel: texture_storage_2d;
9 | #endif
10 |
11 | @group(0) @binding(2) var texture_sampler : sampler;
12 |
13 | // https://www.gamedev.net/forums/topic/709862-downsampling-image-in-compute-shader/
14 | @compute @workgroup_size(8, 8)
15 | fn compute(@builtin(global_invocation_id) id: vec3) {
16 |
17 | let dim : vec2u = textureDimensions(nextMipLevel).xy;
18 |
19 | let uv : vec2f = (vec2f(id.xy) + vec2f(0.5)) / vec2f(dim);
20 | let color : vec4f = textureSampleLevel(previousMipLevel, texture_sampler, uv, 0.0f);
21 |
22 | textureStore(nextMipLevel, id.xy, color);
23 | }
--------------------------------------------------------------------------------
/src/xr/xr_context.cpp:
--------------------------------------------------------------------------------
1 | #include "xr_context.h"
2 |
3 | XRContext::~XRContext()
4 | {
5 | }
6 |
7 | uint32_t XRContext::get_swapchain_image_index(uint8_t eye_idx)
8 | {
9 | return 0;
10 | }
11 |
12 | void XRContext::init_frame()
13 | {
14 | }
15 |
16 | void XRContext::acquire_swapchain(int swapchain_index)
17 | {
18 | }
19 |
20 | void XRContext::release_swapchain(int swapchain_index)
21 | {
22 | }
23 |
24 | void XRContext::end_frame()
25 | {
26 | }
27 |
28 | uint32_t XRContext::get_num_images_per_swapchain()
29 | {
30 | return 2;
31 | }
32 |
33 | glm::mat4x4 XrInputPose_to_glm(const XrInputPose& p) {
34 | glm::mat4 translation = glm::translate(glm::mat4{ 1.f }, glm::vec3(p.position.x, p.position.y, p.position.z));
35 | glm::mat4 orientation = glm::mat4_cast(glm::quat(p.orientation.x, p.orientation.y, p.orientation.z, p.orientation.w));
36 | return translation * orientation;
37 | }
38 |
--------------------------------------------------------------------------------
/src/framework/utils/json_utils.cpp:
--------------------------------------------------------------------------------
1 | #include "json_utils.h"
2 |
3 | #include
4 |
5 | #include "spdlog/spdlog.h"
6 |
7 | #include "rapidjson/document.h"
8 | #include "rapidjson/istreamwrapper.h"
9 |
10 | rapidjson::Document load_json(const std::string& filename) {
11 |
12 | rapidjson::Document j;
13 |
14 | while (true) {
15 |
16 | std::ifstream ifs(filename.c_str());
17 | if (!ifs.is_open()) {
18 | spdlog::error("Failed to open json file {}", filename);
19 | continue;
20 | }
21 |
22 | rapidjson::IStreamWrapper isw(ifs);
23 | rapidjson::Document document;
24 |
25 | j.ParseStream(isw);
26 | if (j.HasParseError()) {
27 | ifs.close();
28 | spdlog::error("Failed to parse json file {}", filename);
29 | continue;
30 | }
31 |
32 | // The json is correct, we can leave the while loop
33 | break;
34 | }
35 |
36 | return j;
37 | }
38 |
--------------------------------------------------------------------------------
/src/framework/utils/timer.cpp:
--------------------------------------------------------------------------------
1 | #include "timer.h"
2 |
3 | #include "spdlog/spdlog.h"
4 |
5 | void Timer::start()
6 | {
7 | begin = std::chrono::steady_clock::now();
8 | }
9 |
10 | void Timer::print_elapsed_time_s()
11 | {
12 | if (begin == std::chrono::steady_clock::time_point()) {
13 | spdlog::error("Timer was not started!");
14 | }
15 |
16 | spdlog::info("Time elapsed: {} [s]", get_elapsed_time>());
17 | }
18 |
19 | void Timer::print_elapsed_time_ms()
20 | {
21 | if (begin == std::chrono::steady_clock::time_point()) {
22 | spdlog::error("Timer was not started!");
23 | }
24 |
25 | spdlog::info("Time elapsed: {} [ms]", get_elapsed_time());
26 | }
27 |
28 | void Timer::print_elapsed_time_ns()
29 | {
30 | if (begin == std::chrono::steady_clock::time_point()) {
31 | spdlog::error("Timer was not started!");
32 | }
33 |
34 | spdlog::info("Time elapsed: {} [ns]", get_elapsed_time());
35 | }
36 |
--------------------------------------------------------------------------------
/data/shaders/quad_mirror.wgsl:
--------------------------------------------------------------------------------
1 | #include mesh_includes.wgsl
2 |
3 | #define GAMMA_CORRECTION
4 |
5 | @vertex
6 | fn vs_main(in: VertexInput) -> VertexOutput {
7 | var out: VertexOutput;
8 | out.position = vec4f(in.position, 1.0);
9 | out.uv = in.uv; // forward to the fragment shader
10 | return out;
11 | }
12 |
13 | @group(0) @binding(0) var left_eye_texture: texture_2d;
14 | @group(0) @binding(1) var texture_sampler : sampler;
15 |
16 | struct FragmentOutput {
17 | @location(0) color: vec4f
18 | }
19 |
20 | @fragment
21 | fn fs_main(in: VertexOutput) -> FragmentOutput {
22 |
23 | let uvs : vec2f = vec2f(in.uv.x, in.uv.y);
24 | let xr_image = textureSample(left_eye_texture, texture_sampler, uvs);
25 |
26 | var out: FragmentOutput;
27 |
28 | if (GAMMA_CORRECTION == 0) {
29 | out.color = vec4f(pow(xr_image.rgb, 1.0 / vec3f(2.2)), 1.0);
30 | } else {
31 | out.color = vec4f(xr_image.rgb, 1.0);
32 | }
33 |
34 | return out;
35 | }
36 |
--------------------------------------------------------------------------------
/src/graphics/primitives/capsule_mesh.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "graphics/primitives/primitive_mesh.h"
4 |
5 | class CapsuleMesh : public PrimitiveMesh
6 | {
7 | float radius = 0.5f;
8 | float height = 2.0f;
9 |
10 | uint32_t rings = 8u;
11 | uint32_t ring_segments = 64u;
12 |
13 | void build_mesh() override;
14 |
15 | public:
16 |
17 | CapsuleMesh(float radius = 0.5f, float height = 2.0f, uint32_t rings = 8u, uint32_t ring_segments = 64u, const glm::vec3& color = { 1.f, 1.f, 1.f });
18 |
19 | void render_gui() override;
20 |
21 | float get_radius() const { return radius; }
22 | float get_height() const { return height; }
23 | uint32_t get_rings() const { return rings; }
24 | uint32_t get_ring_segments() const { return ring_segments; }
25 |
26 | void set_radius(float new_ring_radius);
27 | void set_height(float new_height);
28 | void set_rings(uint32_t new_rings);
29 | void set_ring_segments(uint32_t new_ring_segments);
30 | };
31 |
--------------------------------------------------------------------------------
/data/shaders/pbr_material.wgsl:
--------------------------------------------------------------------------------
1 | struct PbrMaterial
2 | {
3 | pos : vec3f,
4 | normal_g : vec3f,
5 | normal : vec3f,
6 | albedo : vec3f,
7 | emissive : vec3f,
8 | f0 : vec3f,
9 | f0_dielectric : vec3f,
10 | f90 : vec3f,
11 | ior: f32,
12 | diffuse : vec3f,
13 | specular_weight: f32,
14 | metallic : f32,
15 | roughness : f32,
16 | ao : f32,
17 |
18 | // KHR_materials_clearcoat
19 | clearcoat_f0 : vec3f,
20 | clearcoat_f90 : vec3f,
21 | clearcoat_factor : f32,
22 | clearcoat_normal: vec3f,
23 | clearcoat_roughness : f32,
24 | clearcoat_fresnel: vec3f,
25 |
26 | // KHR_materials_iridescence
27 | iridescence_factor : f32,
28 | iridescence_ior : f32,
29 | iridescence_thickness : f32,
30 |
31 | // KHR_materials_anisotropy
32 | anisotropy_factor : f32,
33 | anisotropy_tangent : vec3f,
34 | anisotropy_bitangent : vec3f,
35 |
36 | n_dot_v : f32,
37 | view_dir : vec3f,
38 | reflected_dir : vec3f
39 | };
--------------------------------------------------------------------------------
/src/framework/math/frustum_cull.h:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | // from: https://gist.github.com/podgorskiy/e698d18879588ada9014768e3e82a644
4 | class Frustum
5 | {
6 | public:
7 | Frustum() {}
8 |
9 | // m = ProjectionMatrix * ViewMatrix
10 | Frustum(const glm::mat4& view_projection);
11 |
12 | void set_view_projection(const glm::mat4& view_projection);
13 |
14 | // http://iquilezles.org/www/articles/frustumcorrect/frustumcorrect.htm
15 | bool is_box_visible(const glm::vec3& minp, const glm::vec3& maxp) const;
16 |
17 | private:
18 | enum Planes
19 | {
20 | Left = 0,
21 | Right,
22 | Bottom,
23 | Top,
24 | Near,
25 | Far,
26 | Count,
27 | Combinations = Count * (Count - 1) / 2
28 | };
29 |
30 | template
31 | struct ij2k
32 | {
33 | enum { k = i * (9 - i) / 2 + j - 1 };
34 | };
35 |
36 | template
37 | glm::vec3 intersection(const glm::vec3* crosses) const;
38 |
39 | glm::vec4 m_planes[Count] = {};
40 | glm::vec3 m_points[8] = {};
41 | };
42 |
--------------------------------------------------------------------------------
/src/graphics/primitives/torus_mesh.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "graphics/primitives/primitive_mesh.h"
4 |
5 | class TorusMesh : public PrimitiveMesh
6 | {
7 | float ring_radius = 1.f;
8 | float tube_radius = 0.2f;
9 |
10 | uint32_t rings = 64u;
11 | uint32_t ring_segments = 32u;
12 |
13 | void build_mesh() override;
14 |
15 | public:
16 |
17 | TorusMesh(float ring_radius = 1.f, float tube_radius = 0.2f, uint32_t rings = 64u, uint32_t ring_segments = 32u, const glm::vec3& color = { 1.f, 1.f, 1.f });
18 |
19 | void render_gui() override;
20 |
21 | float get_ring_radius() const { return ring_radius; }
22 | float get_tube_radius() const { return tube_radius; }
23 | uint32_t get_rings() const { return rings; }
24 | uint32_t get_ring_segments() const { return ring_segments; }
25 |
26 | void set_ring_radius(float new_ring_radius);
27 | void set_tube_radius(float new_tube_radius);
28 | void set_rings(uint32_t new_rings);
29 | void set_ring_segments(uint32_t new_ring_segments);
30 | };
31 |
--------------------------------------------------------------------------------
/src/graphics/kernels/prefix_sum_kernel.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "includes.h"
4 | #include "glm/glm.hpp"
5 |
6 | #include "graphics/pipeline.h"
7 |
8 | #include
9 |
10 | class PrefixSumKernel {
11 |
12 | struct PipelineData {
13 | Pipeline pipeline;
14 | Uniform data_uniform;
15 | Uniform block_sum_uniform;
16 | WGPUBindGroup bind_group;
17 | glm::uvec2 dispatch_size;
18 | };
19 |
20 | glm::uvec2 workgroup_size;
21 | uint32_t threads_per_workgroup;
22 | uint32_t items_per_workgroup;
23 |
24 | std::vector pipelines;
25 | Shader* shader;
26 |
27 | void create_pass_recursive(WGPUBuffer data, uint32_t data_byte_size, uint32_t count);
28 |
29 | public:
30 |
31 | PrefixSumKernel(WGPUBuffer data, uint32_t data_byte_size, uint32_t count, glm::uvec2 workgroup_size = glm::uvec2(16, 16));
32 | ~PrefixSumKernel();
33 |
34 | std::vector get_dispatch_chain();
35 |
36 | void dispatch(WGPUComputePassEncoder compute_pass);
37 | };
38 |
--------------------------------------------------------------------------------
/src/framework/resources/resource.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 | #include
5 |
6 | class Resource {
7 |
8 | public:
9 |
10 | Resource();
11 | virtual ~Resource() {}
12 |
13 | void ref();
14 |
15 | // Returns true if last ref
16 | bool unref();
17 |
18 | virtual void on_delete();
19 |
20 | void set_name(const std::string& name);
21 | const std::string& get_name() const;
22 |
23 | bool operator==(const Resource& other) const
24 | {
25 | return scene_unique_id == other.scene_unique_id;
26 | }
27 |
28 | void* get_property(const std::string& name);
29 |
30 | std::string get_scene_unique_id() const { return scene_unique_id; }
31 |
32 | uint32_t get_ref_count() {
33 | return ref_count;
34 | }
35 |
36 | private:
37 |
38 | uint32_t ref_count = 0;
39 | std::string scene_unique_id = "";
40 |
41 | protected:
42 |
43 | std::string name = "";
44 |
45 | // animatable properties
46 | std::unordered_map properties;
47 | };
48 |
--------------------------------------------------------------------------------
/src/framework/resources/resource.cpp:
--------------------------------------------------------------------------------
1 | #include "resource.h"
2 |
3 | #include "framework/utils/utils.h"
4 |
5 | #include "spdlog/spdlog.h"
6 |
7 | #include
8 |
9 | Resource::Resource()
10 | {
11 | // TODO: set proper unique id for project save/load
12 | // id = reinterpret_cast(this);
13 |
14 | scene_unique_id = generate_unique_id();
15 | }
16 |
17 | void Resource::ref()
18 | {
19 | ref_count++;
20 | }
21 |
22 | bool Resource::unref()
23 | {
24 | assert(ref_count > 0u);
25 |
26 | ref_count--;
27 |
28 | if (ref_count == 0u) {
29 | on_delete();
30 | return true;
31 | }
32 |
33 | return false;
34 | }
35 |
36 | void Resource::on_delete()
37 | {
38 | delete this;
39 | }
40 |
41 | void Resource::set_name(const std::string& name)
42 | {
43 | this->name = name;
44 | }
45 |
46 | const std::string& Resource::get_name() const
47 | {
48 | return name;
49 | }
50 |
51 | void* Resource::get_property(const std::string& name)
52 | {
53 | if (properties.contains(name)) {
54 | return properties[name];
55 | }
56 |
57 | return nullptr;
58 | }
59 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2023 UPF-GTI
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/src/graphics/primitives/quad_mesh.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "graphics/primitives/primitive_mesh.h"
4 |
5 | class QuadMesh : public PrimitiveMesh
6 | {
7 | float width = 1.0f;
8 | float height = 1.0f;
9 |
10 | uint32_t subdivisions = 0u;
11 |
12 | bool flip_y = false;
13 | bool centered = true;
14 |
15 | void build_mesh() override;
16 |
17 | public:
18 |
19 | QuadMesh(float width = 1.f, float height = 1.f, bool flip_y = false, bool centered = true, uint32_t subdivisions = 0u, const glm::vec3& color = { 1.f, 1.f, 1.f });
20 |
21 | void render_gui() override;
22 |
23 | float get_width() const { return width; }
24 | float get_height() const { return height; }
25 | uint32_t get_subdivisions() const { return subdivisions; }
26 | bool get_flip_y() const { return flip_y; }
27 | bool get_centered() const { return centered; }
28 |
29 | void set_width(float new_width);
30 | void set_height(float new_height);
31 | void set_subdivisions(uint32_t new_subdivisions);
32 | void set_size(const glm::vec2& size);
33 | void set_centered(bool new_centered);
34 | void set_flip_y(bool new_flip_y);
35 | };
36 |
--------------------------------------------------------------------------------
/data/shaders/mesh_includes.wgsl:
--------------------------------------------------------------------------------
1 |
2 | struct VertexInput {
3 | @builtin(instance_index) instance_id : u32,
4 | @location(0) position: vec3f,
5 | #unique vertex @location(1) uv: vec2f,
6 | #unique vertex @location(2) normal: vec3f,
7 | #unique vertex @location(3) tangent: vec4f,
8 | #unique vertex @location(4) color: vec3f,
9 | #unique vertex @location(5) weights: vec4f,
10 | #unique vertex @location(6) joints: vec4i
11 | };
12 |
13 | struct VertexOutput {
14 | @builtin(position) position: vec4f,
15 | @location(0) uv: vec2f,
16 | @location(1) color: vec4f,
17 | @location(2) world_position: vec3f,
18 | @location(3) normal: vec3f,
19 | @location(4) tangent : vec3f,
20 | @location(5) bitangent : vec3f,
21 | };
22 |
23 | struct RenderMeshData {
24 | model : mat4x4f
25 | };
26 |
27 | struct InstanceData {
28 | data : array
29 | }
30 |
31 | struct CameraData {
32 | view_projection : mat4x4f,
33 | view : mat4x4f,
34 | projection : mat4x4f,
35 | eye : vec3f,
36 | exposure : f32,
37 | right_controller_position : vec3f,
38 | ibl_intensity : f32,
39 | screen_size : vec2f,
40 | dummy : vec2f,
41 | };
--------------------------------------------------------------------------------
/src/framework/nodes/mesh_instance_3d.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "node_3d.h"
4 | #include "graphics/mesh.h"
5 |
6 | class MeshInstance3D : public Node3D {
7 |
8 | protected:
9 | Mesh* mesh = nullptr;
10 |
11 | public:
12 |
13 | bool is_skinned = false;
14 |
15 | MeshInstance3D();
16 | ~MeshInstance3D();
17 |
18 | void update_aabb();
19 | void set_aabb(const AABB& new_aabb) override;
20 | void set_surface_material_override(Surface* surface, Material* material);
21 | void set_frustum_culling_enabled(bool enabled);
22 | void set_receive_shadows(bool new_receive_shadows);
23 | void set_mesh(Mesh* new_mesh);
24 |
25 | Mesh* get_mesh() const { return mesh; }
26 | bool get_frustum_culling_enabled();
27 | Material* get_surface_material(int surface_idx);
28 | Material* get_surface_material_override(Surface* surface);
29 | const std::vector& get_surfaces() const;
30 | Surface* get_surface(int surface_idx) const;
31 | uint32_t get_surface_count() const;
32 |
33 | void add_surface(Surface* surface);
34 |
35 | virtual void render() override;
36 | virtual void update(float delta_time) override;
37 |
38 | void render_gui() override;
39 | };
40 |
--------------------------------------------------------------------------------
/src/framework/nodes/viewport_3d.cpp:
--------------------------------------------------------------------------------
1 | #include "viewport_3d.h"
2 |
3 | #include "graphics/renderer.h"
4 |
5 | #include "framework/nodes/node_2d.h"
6 | #include "framework/parsers/parse_scene.h"
7 | #include "framework/input.h"
8 |
9 | Viewport3D::Viewport3D(Node2D* root_2d) : Node3D(), root(root_2d)
10 | {
11 | root->disable_2d();
12 | }
13 |
14 | Viewport3D::~Viewport3D()
15 | {
16 |
17 | }
18 |
19 | void Viewport3D::set_viewport_size(const glm::vec2& new_size)
20 | {
21 | viewport_size = new_size;
22 | }
23 |
24 | void Viewport3D::update(float delta_time)
25 | {
26 | if (!active) {
27 | return;
28 | }
29 |
30 | // Manage 3d transform data
31 |
32 | glm::vec2 pos_2d = root->get_translation();
33 |
34 | auto webgpu_context = Renderer::instance->get_webgpu_context();
35 |
36 | float width = static_cast(webgpu_context->render_width);
37 | float height = static_cast(webgpu_context->render_height);
38 | float ar = width / height;
39 |
40 | glm::vec2 screen_size(width, height);
41 | pos_2d /= screen_size;
42 |
43 | root->set_position(pos_2d);
44 | root->scale(1.0f / glm::vec2(width, height * ar));
45 |
46 | root->set_viewport_model(get_global_model());
47 | }
48 |
--------------------------------------------------------------------------------
/src/framework/math/aabb.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "glm/vec3.hpp"
4 | #include "glm/mat4x4.hpp"
5 | #include "glm/gtc/quaternion.hpp"
6 |
7 | #include "framework/math/math_utils.h"
8 |
9 | #include
10 |
11 | struct AABB {
12 | glm::vec3 center = {};
13 | glm::vec3 half_size = {};
14 |
15 | bool initialized() const;
16 |
17 | /**
18 | * apply a matrix to a box * note that the resulting box will be axis aligned as well
19 | * therefore the resulting box may be larger than the previous
20 | *
21 | * @param box the box to transform
22 | * @param mat the trnsformation matrix to apply
23 | **/
24 |
25 | AABB transform(const glm::mat4& mat) const;
26 |
27 | AABB rotate(const glm::quat& rotation) const;
28 |
29 | // Returns the index of the longest axis of the bounding box.
30 | int longest_axis() const {
31 | float x_size = abs(half_size.x);
32 | float y_size = abs(half_size.y);
33 | float z_size = abs(half_size.z);
34 |
35 | if (x_size > y_size)
36 | return x_size > z_size ? 0 : 2;
37 | else
38 | return y_size > z_size ? 1 : 2;
39 | }
40 | };
41 |
42 | AABB merge_aabbs(const AABB& AABB_0, const AABB& AABB_1);
43 |
--------------------------------------------------------------------------------
/src/framework/animation/blend_animation.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "animation.h"
4 | #include "pose.h"
5 |
6 | #include "framework/nodes/node.h"
7 |
8 | struct BlendTarget {
9 | Animation* animation = nullptr;
10 | float time = 0.0f;
11 | float duration = 0.0f;
12 | float elapsed = 0.0f;
13 | inline BlendTarget() : animation(0), time(0.0f), duration(0.0f), elapsed(0.0f) { }
14 | inline BlendTarget(Animation* target, float duration) : animation(target), time(target->get_start_time()), duration(duration), elapsed(0.0f) { }
15 | };
16 |
17 | // Fast blend from one animation to another (hide the transition between two animations)
18 | class BlendAnimation {
19 |
20 | protected:
21 | std::vector targets;
22 | Animation* animation = nullptr;
23 | float time = 0.0f;
24 |
25 | public:
26 | BlendAnimation();
27 |
28 | void play(Animation* target);
29 | void stop();
30 | void fade_to(Animation* target, float fade_time);
31 | float update(float current_time, uint8_t loop, std::vector& data);
32 |
33 | void blend(Pose& output, Pose& a, Pose& b, float t);
34 | void add(Pose& output, Pose& in, Pose& add_pose, Pose& base);
35 |
36 | Animation* get_current_animation();
37 | };
38 |
--------------------------------------------------------------------------------
/libraries/glfw3webgpu/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | # This is only meant to be included as a subdirectory in another project.
2 | # It assumes that targets 'glfw' and 'webgpu' exist.
3 | # Loot at examples/CMakeLists.txt to see how to use it in a project.
4 |
5 | # The glfw3webgpu target
6 | add_library(glfw3webgpu STATIC glfw3webgpu.cpp glfw3webgpu.hpp)
7 |
8 | set_property(TARGET glfw3webgpu PROPERTY LANGUAGES CXX)
9 | set_property(TARGET glfw3webgpu PROPERTY CXX_STANDARD 20)
10 |
11 | target_include_directories(glfw3webgpu PUBLIC .)
12 | target_link_libraries(glfw3webgpu PUBLIC glfw webgpu)
13 |
14 | if (APPLE)
15 | target_compile_options(glfw3webgpu PRIVATE -x objective-c++)
16 | target_link_libraries(glfw3webgpu PRIVATE "-framework Cocoa" "-framework CoreVideo" "-framework IOKit" "-framework QuartzCore")
17 | endif ()
18 |
19 | # Copy compile definitions that are PRIVATE in glfw
20 | if (GLFW_BUILD_COCOA)
21 | target_compile_definitions(glfw3webgpu PRIVATE _GLFW_COCOA)
22 | endif()
23 | if (GLFW_BUILD_WIN32)
24 | target_compile_definitions(glfw3webgpu PRIVATE _GLFW_WIN32)
25 | endif()
26 | if (GLFW_BUILD_X11)
27 | target_compile_definitions(glfw3webgpu PRIVATE _GLFW_X11)
28 | endif()
29 | if (GLFW_BUILD_WAYLAND)
30 | target_compile_definitions(glfw3webgpu PRIVATE _GLFW_WAYLAND)
31 | endif()
--------------------------------------------------------------------------------
/src/framework/nodes/spot_light_3d.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "light_3d.h"
4 |
5 | class MeshInstance3D;
6 | class Material;
7 | class Surface;
8 |
9 | class SpotLight3D : public Light3D {
10 |
11 | float inner_cone_angle = 0.0f;
12 | float outer_cone_angle = glm::pi() / 4.0f;
13 |
14 | MeshInstance3D* debug_mesh = nullptr;
15 | Surface* debug_surface = nullptr;
16 |
17 | Material* debug_material = nullptr;
18 |
19 | void create_debug_render_cone();
20 |
21 | public:
22 |
23 | SpotLight3D();
24 | ~SpotLight3D();
25 |
26 | virtual void render() override;
27 |
28 | void clone(Node* new_node, bool copy = true) override;
29 |
30 | void render_gui() override;
31 |
32 | void get_uniform_data(sLightUniformData& data) override;
33 |
34 | float get_inner_cone_angle() const { return inner_cone_angle; };
35 | float get_outer_cone_angle() const { return outer_cone_angle; };
36 |
37 | void set_range(float value) override;
38 | void on_set_range() override;
39 |
40 | void set_inner_cone_angle(float value);
41 | void set_outer_cone_angle(float value);
42 |
43 | void serialize(std::ofstream& binary_scene_file) override;
44 | void parse(std::ifstream& binary_scene_file) override;
45 |
46 | void create_debug_meshes() override;
47 | };
48 |
--------------------------------------------------------------------------------
/data/shaders/AABB_shader.wgsl:
--------------------------------------------------------------------------------
1 | #include mesh_includes.wgsl
2 | #define GAMMA_CORRECTION
3 |
4 | @group(0) @binding(0) var mesh_data : InstanceData;
5 |
6 | #dynamic @group(1) @binding(0) var camera_data : CameraData;
7 |
8 | @group(2) @binding(1) var albedo: vec4f;
9 |
10 | @vertex
11 | fn vs_main(in: VertexInput) -> VertexOutput {
12 | let instance_data : RenderMeshData = mesh_data.data[in.instance_id];
13 |
14 | var out: VertexOutput;
15 | var world_position = instance_data.model * vec4f(in.position, 1.0);
16 | out.world_position = world_position.xyz;
17 | out.position = camera_data.view_projection * world_position;
18 | out.uv = in.uv; // forward to the fragment shader
19 | out.color = vec4(in.color, 1.0);
20 | out.normal = in.normal;
21 | return out;
22 | }
23 |
24 | struct FragmentOutput {
25 | @location(0) color: vec4f
26 | }
27 |
28 | @fragment
29 | fn fs_main(in: VertexOutput) -> FragmentOutput {
30 | var out: FragmentOutput;
31 |
32 | var dummy = camera_data.eye;
33 |
34 | var final_color = in.color.rgb * albedo.xyz;
35 |
36 | if ( in.uv.x < 0.015 || in.uv.y > 0.985 || in.uv.x > 0.985 || in.uv.y < 0.015 ) {
37 | out.color = vec4(final_color, 1.0);
38 | } else {
39 | discard;
40 | }
41 |
42 | return out;
43 | }
--------------------------------------------------------------------------------
/src/graphics/uniforms_structs.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "glm/vec2.hpp"
4 | #include "glm/vec3.hpp"
5 | #include "glm/vec4.hpp"
6 | #include "glm/mat4x4.hpp"
7 |
8 | struct sLightUniformData {
9 | glm::mat4x4 view_proj;
10 | glm::vec3 position;
11 | int type = 0;
12 | glm::vec3 color = { 0.0f, 0.0f, 0.0f };
13 | float intensity = 0.0f;
14 | glm::vec3 direction = { 0.0f, 0.0f, 0.0f };
15 | float range = 0.0f;
16 | float shadow_bias = 0.001f;
17 | int cast_shadows = 0;
18 | float inner_cone_cos = 0.0f;
19 | float outer_cone_cos = 0.0f;
20 | };
21 |
22 | enum sUIDataFlags {
23 | UI_DATA_HOVERED = 1 << 0,
24 | UI_DATA_PRESSED = 1 << 1,
25 | UI_DATA_SELECTED = 1 << 2,
26 | UI_DATA_COLOR_BUTTON = 1 << 3,
27 | UI_DATA_DISABLED = 1 << 4
28 | };
29 |
30 | struct sUIData {
31 | uint32_t flags = 0u;
32 | float hover_time = 0.0f;
33 | float aspect_ratio = 1.f;
34 | float data_value = 0.0f; // generic data, slider value, group num items, combo buttons use this prop by now to the index in combo..
35 |
36 | glm::vec3 data_vec = glm::vec3(1.f); // picker color, slider range(+slider_type at .z)..
37 | float clip_range = 0.f; // inside/outside the node parent.. -1..1
38 |
39 | glm::vec2 xr_size = { 0.0f, 0.0f };
40 | glm::vec2 xr_position = { 0.0f, 0.0f };
41 | };
42 |
--------------------------------------------------------------------------------
/src/graphics/font.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "includes.h"
4 | #include "framework/utils/json_utils.h"
5 | #include "framework/resources/resource.h"
6 |
7 | #include "font_common.h"
8 |
9 | #include