Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
106 commits
Select commit Hold shift + click to select a range
12f357f
First commit of the new "simple engine" tutorial. This is a VERY ear…
gpx1000 Jul 14, 2025
7e419d5
Refactor GPU optimization sections to generalize vendor-specific reco…
gpx1000 Jul 14, 2025
4644950
Refactor mobile GPU optimization sections and enhance Vulkan extensio…
gpx1000 Jul 14, 2025
2edbd75
Add detailed section on rendergraphs and synchronization in Vulkan
gpx1000 Jul 14, 2025
b476bd1
Add architectural pattern diagrams and refine related sections
gpx1000 Jul 18, 2025
f1d10cf
Add explanatory note on windowing libraries in input handling tutorial
gpx1000 Jul 18, 2025
2a350b2
closer to getting engine working.
gpx1000 Jul 20, 2025
2d46280
address feedback
gpx1000 Jul 22, 2025
3b3dc05
address feedback
gpx1000 Jul 22, 2025
6cf03fc
address feedback
gpx1000 Jul 22, 2025
50d78a7
add the flowchart to the rendering pipeline.
gpx1000 Jul 22, 2025
9b2c781
describe Rendergraphs and Dynamic Rendering
gpx1000 Jul 22, 2025
ddd1177
address comments.
gpx1000 Jul 22, 2025
5ec2035
add the requested appendix.adoc
gpx1000 Jul 22, 2025
31ded49
add the requested appendix.adoc
gpx1000 Jul 23, 2025
659ecb1
address the requested items
gpx1000 Jul 23, 2025
bd98b2d
address the requested items
gpx1000 Jul 23, 2025
8b83ead
address the requested items
gpx1000 Jul 23, 2025
9b2343a
address the requested items
gpx1000 Jul 23, 2025
7734f21
Engine now builds and runs. IMGUI having issues.
gpx1000 Jul 23, 2025
b8a9b39
Engine now renders. Bunch of validation errors and it looks like img…
gpx1000 Jul 23, 2025
e773353
address comments.
gpx1000 Jul 24, 2025
6256f77
address comments.
gpx1000 Jul 24, 2025
e6b8583
It runs now, IMGUI is happier.
gpx1000 Jul 24, 2025
e3f6fc6
everything runs and can close without validation warnings other than …
gpx1000 Jul 24, 2025
4a3b450
everything runs and can close without validation warnings other than …
gpx1000 Jul 24, 2025
0833166
audio HRTF works well and debug switch to turn on CPU only mode vs GP…
gpx1000 Jul 24, 2025
9513597
audio fully works, GPU HRTF works as well as CPU HRTF.
gpx1000 Jul 25, 2025
86c396a
The bistro scene now loads. Still have some issues with PBR but I th…
gpx1000 Jul 25, 2025
a62e4a9
make the hrtf listener sync with the camera location and rotation.
gpx1000 Jul 25, 2025
14fc6b1
Lighting working for non PBR code, and PBR code seems to be relativel…
gpx1000 Jul 25, 2025
b998a13
fix for formating the list.
gpx1000 Jul 29, 2025
8be59f4
PBR is working. KTX2 with BasisU is working.
gpx1000 Jul 29, 2025
be45542
Update 04_rendering_approaches.adoc
gpx1000 Jul 29, 2025
8bdf3d1
Update 04_rendering_approaches.adoc
gpx1000 Jul 30, 2025
e80fd23
address comments
gpx1000 Jul 30, 2025
20a9ade
Merge remote-tracking branch 'origin/Simple-Game-Engine' into Simple-…
gpx1000 Jul 30, 2025
d834c39
address comments
gpx1000 Jul 31, 2025
ea39e65
address comments
gpx1000 Jul 31, 2025
858b792
address comments
gpx1000 Jul 31, 2025
815aa79
Need to investigate a few things, (physics isn't colliding against th…
gpx1000 Jul 31, 2025
bdc1845
add in the dependences install scripts.
gpx1000 Jul 31, 2025
04c8b38
Merge branch 'refs/heads/upstream-main' into Simple-Game-Engine
gpx1000 Jul 31, 2025
cdb01db
attempt to fancy fix the windows install script.
gpx1000 Aug 1, 2025
16019ca
CMake: use PLATFORM_* defines via ANDROID, fix glfw condition, make s…
gpx1000 Aug 8, 2025
4b8198d
Fix the pathing for install_dependencies_windows.bat also fix CMakeLi…
gpx1000 Aug 8, 2025
14dcb35
Add instancing support, remove unused STB dependency, and fetch Bistr…
gpx1000 Aug 10, 2025
dd9713a
Refactor Vulkan memory handling, physics GPU initialization, and coll…
gpx1000 Aug 10, 2025
27715c0
address several comments (more still need to be addressed). And fix …
gpx1000 Aug 10, 2025
067ea74
Move Renderdoc out of the debug_system.h and into a "real world" rend…
gpx1000 Aug 11, 2025
a5edf28
the lighting in the PBR scene *looks* better. There's still a bit th…
gpx1000 Aug 11, 2025
adf461e
Remove shadows for now. We'll concentrate on them in the samples ver…
gpx1000 Aug 12, 2025
e57bc3d
Fix the string lights.
gpx1000 Aug 13, 2025
e1d7059
committing requested changes in stages.
gpx1000 Aug 15, 2025
1f17074
committing requested changes in stages.
gpx1000 Aug 15, 2025
acfbd6e
committing requested changes in stages.
gpx1000 Aug 15, 2025
5e38540
committing requested changes in stages.
gpx1000 Aug 15, 2025
a58b884
committing requested changes in stages.
gpx1000 Aug 15, 2025
4b4a243
committing requested changes in stages.
gpx1000 Aug 15, 2025
6ec7321
committing requested changes in stages.
gpx1000 Aug 15, 2025
8ecae4e
committing requested changes in stages.
gpx1000 Aug 15, 2025
345b137
committing requested changes in stages.
gpx1000 Aug 15, 2025
11e9a65
committing requested changes in stages.
gpx1000 Aug 15, 2025
5e6209c
committing requested changes in stages.
gpx1000 Aug 15, 2025
25e66d5
committing requested changes in stages.
gpx1000 Aug 15, 2025
5849fa5
switch from link to xref.
gpx1000 Aug 15, 2025
f1df3d2
addressing more comments.
gpx1000 Aug 15, 2025
7eaa47e
addressing more comments.
gpx1000 Aug 15, 2025
92c7f7d
addressing more comments.
gpx1000 Aug 15, 2025
625eb71
addressing more comments.
gpx1000 Aug 15, 2025
60ee95d
addressing more comments.
gpx1000 Aug 15, 2025
23952bc
addressing more comments.
gpx1000 Aug 15, 2025
65e5db3
addressing more comments.
gpx1000 Aug 15, 2025
e564b29
addressing more comments.
gpx1000 Aug 15, 2025
7b3e016
addressing more comments.
gpx1000 Aug 15, 2025
7bf9dab
addressing more comments.
gpx1000 Aug 15, 2025
47a6baa
addressing more comments.
gpx1000 Aug 15, 2025
44e7f38
addressing more comments.
gpx1000 Aug 15, 2025
dd51a38
addressing more comments.
gpx1000 Aug 15, 2025
f713e9c
addressing more comments.
gpx1000 Aug 15, 2025
9705b60
addressing more comments.
gpx1000 Aug 15, 2025
921eed4
addressing more comments.
gpx1000 Aug 15, 2025
2a22079
addressing more comments.
gpx1000 Aug 15, 2025
41e336e
addressing more comments.
gpx1000 Aug 15, 2025
b78f8b2
addressing more comments.
gpx1000 Aug 16, 2025
5c7a132
addressing more comments.
gpx1000 Aug 16, 2025
560b9f3
addressing more comments.
gpx1000 Aug 16, 2025
6db6b9d
addressing more comments.
gpx1000 Aug 16, 2025
02baf4d
addressing more comments.
gpx1000 Aug 16, 2025
0b0dddb
addressing more comments.
gpx1000 Aug 16, 2025
ccb5c15
addressing more comments.
gpx1000 Aug 19, 2025
aa321c0
addressing more comments.
gpx1000 Aug 19, 2025
5c4ec27
addressing more comments.
gpx1000 Aug 19, 2025
b4d6226
addressing more comments.
gpx1000 Aug 19, 2025
a8d11c6
addressing more comments.
gpx1000 Aug 19, 2025
b167c70
addressing more comments.
gpx1000 Aug 19, 2025
276d1cb
addressing more comments.
gpx1000 Aug 21, 2025
6e8adb4
implementing Spec-Gloss workflow and transmission materials.
gpx1000 Aug 25, 2025
e1ac508
updating nlohmann_json to v3.12.0.
gpx1000 Aug 25, 2025
bbbae41
update the default screenshot.
gpx1000 Aug 25, 2025
03d05cf
implementing support for asynchronous texture loading and improved Vu…
gpx1000 Aug 26, 2025
0ef0316
Working through some of the PR comments. Concentrating on the text o…
gpx1000 Oct 17, 2025
277a817
Down to 78 comments left outstanding from the PR in the tutorial text…
gpx1000 Oct 17, 2025
ce7c00d
This doesn't currently fix the bugs still in the engine, but it's a c…
gpx1000 Oct 17, 2025
6378bef
Add deferred mesh uploads, batch resource staging, priority-based tex…
gpx1000 Dec 1, 2025
0e9721e
Merge branch 'upstream-main' into Simple-Game-Engine
gpx1000 Dec 1, 2025
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
6 changes: 1 addition & 5 deletions attachments/simple_engine/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -44,11 +44,6 @@ target_sources(VulkanCppModule
)


# Add the vulkan.cppm file directly as a source file
target_sources(VulkanCppModule
PRIVATE
"${Vulkan_INCLUDE_DIR}/vulkan/vulkan.cppm"
)

# Platform-specific settings
if(ANDROID)
Expand Down Expand Up @@ -119,6 +114,7 @@ set(SOURCES
pipeline.cpp
descriptor_manager.cpp
renderdoc_debug_system.cpp
mikktspace.c
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is this used for?

)

# Create executable
Expand Down
1 change: 1 addition & 0 deletions attachments/simple_engine/audio_system.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include <mutex>
#include <utility>
#include <unordered_map>
#include <algorithm>

// OpenAL headers
#ifdef __APPLE__
Expand Down
8 changes: 8 additions & 0 deletions attachments/simple_engine/audio_system.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include <queue>
#include <vulkan/vulkan_raii.hpp>
#include <vulkan/vk_platform.h>
#include <stdexcept>

/**
* @brief Class representing an audio source.
Expand Down Expand Up @@ -148,6 +149,13 @@ class AudioSystem {
*/
AudioSystem() = default;

// Constructor-based initialization to replace separate Initialize() calls
AudioSystem(Engine* engine, Renderer* renderer) {
if (!Initialize(engine, renderer)) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When you call Initialize in the constructor, you should probably make Initialize a private function.

throw std::runtime_error("AudioSystem: initialization failed");
}
}

/**
* @brief Flush audio output: clears pending processing and device buffers so playback restarts cleanly.
*/
Expand Down
68 changes: 31 additions & 37 deletions attachments/simple_engine/engine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,7 @@
// @see en/Building_a_Simple_Engine/Engine_Architecture/02_architectural_patterns.adoc

Engine::Engine()
: resourceManager(std::make_unique<ResourceManager>()),
modelLoader(std::make_unique<ModelLoader>()),
audioSystem(std::make_unique<AudioSystem>()),
physicsSystem(std::make_unique<PhysicsSystem>()),
imguiSystem(std::make_unique<ImGuiSystem>()) {
: resourceManager(std::make_unique<ResourceManager>()) {
}

Engine::~Engine() {
Expand Down Expand Up @@ -64,37 +60,25 @@ bool Engine::Initialize(const std::string& appName, int width, int height, bool
return false;
}

// Initialize model loader
if (!modelLoader->Initialize(renderer.get())) {
return false;
}

// Connect model loader to renderer for light extraction
renderer->SetModelLoader(modelLoader.get());

// Initialize audio system
if (!audioSystem->Initialize(this, renderer.get())) {
return false;
}

// Initialize a physics system
physicsSystem->SetRenderer(renderer.get());
try {
// Model loader via constructor; also wire into renderer
modelLoader = std::make_unique<ModelLoader>(renderer.get());
renderer->SetModelLoader(modelLoader.get());

// Enable GPU acceleration for physics calculations to drastically speed up computations
physicsSystem->SetGPUAccelerationEnabled(true);
// Audio system via constructor
audioSystem = std::make_unique<AudioSystem>(this, renderer.get());

if (!physicsSystem->Initialize()) {
return false;
}
// Physics system via constructor (GPU enabled)
physicsSystem = std::make_unique<PhysicsSystem>(renderer.get(), true);

// Initialize ImGui system
if (!imguiSystem->Initialize(renderer.get(), width, height)) {
// ImGui via constructor, then connect audio system
imguiSystem = std::make_unique<ImGuiSystem>(renderer.get(), width, height);
imguiSystem->SetAudioSystem(audioSystem.get());
} catch (const std::exception& e) {
std::cerr << "Subsystem initialization failed: " << e.what() << std::endl;
return false;
}

// Connect ImGui system to an audio system for UI controls
imguiSystem->SetAudioSystem(audioSystem.get());

// Generate ball material properties once at load time
GenerateBallMaterial();

Expand Down Expand Up @@ -132,9 +116,15 @@ void Engine::Run() {
// Update window title with FPS and frame time every second
if (fpsUpdateTimer >= 1.0f) {
uint64_t framesSinceLastUpdate = frameCount - lastFPSUpdateFrame;
currentFPS = framesSinceLastUpdate / fpsUpdateTimer;
// Average frame time in milliseconds over the last interval
double avgMs = (fpsUpdateTimer / static_cast<double>(framesSinceLastUpdate)) * 1000.0;
double avgMs = 0.0;
if (framesSinceLastUpdate > 0 && fpsUpdateTimer > 0.0f) {
currentFPS = static_cast<float>(static_cast<double>(framesSinceLastUpdate) / static_cast<double>(fpsUpdateTimer));
avgMs = (fpsUpdateTimer / static_cast<double>(framesSinceLastUpdate)) * 1000.0;
} else {
// Avoid divide-by-zero; keep previous FPS and estimate avgMs from last delta
currentFPS = std::max(currentFPS, 1.0f);
avgMs = static_cast<double>(deltaTimeMs.count());
}

// Update window title with frame count, FPS, and frame time
std::string title = "Simple Engine - Frame: " + std::to_string(frameCount) +
Expand Down Expand Up @@ -402,15 +392,19 @@ void Engine::Update(TimeDelta deltaTime) {
UpdateCameraControls(deltaTime);
}

// Update all entities
// Update all entities (guard against null unique_ptrs)
for (auto& entity : entities) {
if (entity->IsActive()) {
entity->Update(deltaTime);
}
if (!entity) { continue; }
if (!entity->IsActive()) { continue; }
entity->Update(deltaTime);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe a bit easier to digest:

if (entity && entity->IsActive())
{
    entity->Update(deltaTime);
}

}
}

void Engine::Render() {
// Ensure renderer is ready
if (!renderer || !renderer->IsInitialized()) {
return;
}

// Check if we have an active camera
if (!activeCamera) {
Expand Down
4 changes: 2 additions & 2 deletions attachments/simple_engine/imgui_system.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,7 @@ void ImGuiSystem::NewFrame() {
}

// Exposure slider
static float exposure = 3.0f; // Higher default for emissive lighting
static float exposure = 1.2f; // Default tuned to avoid washout
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe add some
static const float defaultExposure = 1.2f;

if (ImGui::SliderFloat("Exposure", &exposure, 0.1f, 10.0f, "%.2f")) {
// Update exposure in renderer
if (renderer) {
Expand All @@ -228,7 +228,7 @@ void ImGuiSystem::NewFrame() {
}
ImGui::SameLine();
if (ImGui::Button("Reset##Exposure")) {
exposure = 3.0f; // Reset to higher value for emissive lighting
exposure = 1.2f; // Reset to a sane default to avoid washout
if (renderer) {
renderer->SetExposure(exposure);
}
Expand Down
8 changes: 8 additions & 0 deletions attachments/simple_engine/imgui_system.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include <memory>
#include <vulkan/vulkan_raii.hpp>
#include <vulkan/vk_platform.h>
#include <stdexcept>

// Forward declarations
class Renderer;
Expand All @@ -25,6 +26,13 @@ class ImGuiSystem {
*/
ImGuiSystem();

// Constructor-based initialization to replace separate Initialize() calls
ImGuiSystem(Renderer* renderer, uint32_t width, uint32_t height) {
if (!Initialize(renderer, width, height)) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Initialize should probably be private now.

throw std::runtime_error("ImGuiSystem: initialization failed");
}
}

/**
* @brief Destructor for proper cleanup.
*/
Expand Down
14 changes: 12 additions & 2 deletions attachments/simple_engine/mesh_component.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,13 +36,23 @@ void MeshComponent::CreateSphere(float radius, const glm::vec3& color, int segme
static_cast<float>(lat) / static_cast<float>(segments)
};

// Calculate tangent (derivative with respect to longitude)
// Calculate tangent (derivative with respect to longitude). Handle poles robustly.
glm::vec3 tangent = {
-sinTheta * sinPhi,
0.0f,
sinTheta * cosPhi
};
tangent = glm::normalize(tangent);
float len2 = glm::dot(tangent, tangent);
if (len2 < 1e-12f) {
// At poles sinTheta ~ 0 -> fallback tangent orthogonal to normal
glm::vec3 t = glm::cross(normal, glm::vec3(0.0f, 0.0f, 1.0f));
if (glm::length(t) < 1e-12f) {
t = glm::cross(normal, glm::vec3(1.0f, 0.0f, 0.0f));
}
tangent = glm::normalize(t);
} else {
tangent = glm::normalize(tangent);
}

vertices.push_back({
position,
Expand Down
Loading