From 55756fbd95eec12818b4eeec1641bc23d3ccbf2a Mon Sep 17 00:00:00 2001 From: Sophomore <17792626+WSQS@users.noreply.github.com> Date: Sat, 15 Nov 2025 18:50:24 +0800 Subject: [PATCH 01/12] feat: add camera uniform --- main.cpp | 27 ++++++++++++++++++++++++++- sdl_wrapper/sdl_wrapper.gpu.ixx | 4 ++-- sdl_wrapper/sdl_wrapper.pipeline.cpp | 4 ++-- 3 files changed, 30 insertions(+), 5 deletions(-) diff --git a/main.cpp b/main.cpp index fe41282..5d85b6f 100644 --- a/main.cpp +++ b/main.cpp @@ -21,6 +21,11 @@ struct Vertex auto position() { return &x; } }; +struct CameraUniform +{ + float m[16]; +}; + class UserApp : public sopho::App { std::shared_ptr gpu_wrapper{std::make_shared()}; @@ -34,6 +39,8 @@ class UserApp : public sopho::App Vertex{0.5F, -0.5F, 0.0F, 1.0F, 0.0F, 1.0F, 1.0F} // bottom right vertex }; + CameraUniform cam{}; + std::string vertex_source = R"WSQ(#version 460 @@ -41,9 +48,14 @@ layout (location = 0) in vec3 a_position; layout (location = 1) in vec4 a_color; layout (location = 0) out vec4 v_color; +layout(std140, set = 0, binding = 0) uniform Camera +{ + mat4 uView; +}; + void main() { - gl_Position = vec4(a_position, 1.0f); + gl_Position = uView * vec4(a_position, 1.0f); v_color = a_color; })WSQ"; std::string fragment_source = @@ -77,6 +89,15 @@ void main() vertex_buffer.upload(&vertices, sizeof(vertices), 0); + { + // identity + cam.m[0] = cam.m[5] = cam.m[10] = cam.m[15] = 1.0f; + cam.m[1] = cam.m[2] = cam.m[3] = 0.0f; + cam.m[4] = cam.m[6] = cam.m[7] = 0.0f; + cam.m[8] = cam.m[9] = cam.m[11] = 0.0f; + cam.m[12] = cam.m[13] = cam.m[14] = 0.0f; + } + // Setup Dear ImGui context IMGUI_CHECKVERSION(); @@ -236,6 +257,10 @@ void main() // draw calls go here SDL_BindGPUGraphicsPipeline(renderPass, pipeline_wrapper.data()); + { + SDL_PushGPUVertexUniformData(commandBuffer, 0,cam.m,sizeof(cam.m)); + } + // bind the vertex buffer SDL_GPUBufferBinding bufferBindings[1]; bufferBindings[0].buffer = vertex_buffer.data(); // index 0 is slot 0 in this example diff --git a/sdl_wrapper/sdl_wrapper.gpu.ixx b/sdl_wrapper/sdl_wrapper.gpu.ixx index 8ab15fe..23592ca 100644 --- a/sdl_wrapper/sdl_wrapper.gpu.ixx +++ b/sdl_wrapper/sdl_wrapper.gpu.ixx @@ -48,7 +48,7 @@ export namespace sopho PipelineWrapper create_pipeline(); - auto create_shader(const std::vector& p_shader, SDL_GPUShaderStage p_stage) + auto create_shader(const std::vector& p_shader, SDL_GPUShaderStage p_stage,uint32_t p_num_uniform_buffers) { SDL_GPUShaderCreateInfo vertexInfo{}; vertexInfo.code = p_shader.data(); @@ -59,7 +59,7 @@ export namespace sopho vertexInfo.num_samplers = 0; vertexInfo.num_storage_buffers = 0; vertexInfo.num_storage_textures = 0; - vertexInfo.num_uniform_buffers = 0; + vertexInfo.num_uniform_buffers = p_num_uniform_buffers; return SDL_CreateGPUShader(m_device, &vertexInfo); } diff --git a/sdl_wrapper/sdl_wrapper.pipeline.cpp b/sdl_wrapper/sdl_wrapper.pipeline.cpp index 56ac8da..95fd6e5 100644 --- a/sdl_wrapper/sdl_wrapper.pipeline.cpp +++ b/sdl_wrapper/sdl_wrapper.pipeline.cpp @@ -125,7 +125,7 @@ namespace sopho auto code_size = static_cast(result.cend() - result.cbegin()) * sizeof(uint32_t); auto ptr = reinterpret_cast(result.cbegin()); std::vector code{ptr, ptr + code_size}; - m_vertex_shader = m_device->create_shader(code, SDL_GPU_SHADERSTAGE_VERTEX); + m_vertex_shader = m_device->create_shader(code, SDL_GPU_SHADERSTAGE_VERTEX, 1); m_pipeline_info.vertex_shader = m_vertex_shader; m_modified = true; } @@ -154,7 +154,7 @@ namespace sopho auto code_size = static_cast(result.cend() - result.cbegin()) * sizeof(uint32_t); auto ptr = reinterpret_cast(result.cbegin()); std::vector code{ptr, ptr + code_size}; - m_fragment_shader = m_device->create_shader(code, SDL_GPU_SHADERSTAGE_FRAGMENT); + m_fragment_shader = m_device->create_shader(code, SDL_GPU_SHADERSTAGE_FRAGMENT, 0); m_pipeline_info.fragment_shader = m_fragment_shader; m_modified = true; } From b695abd20a0a4225b7406e39e0f64cd8e7f1849d Mon Sep 17 00:00:00 2001 From: Sophomore <17792626+WSQS@users.noreply.github.com> Date: Sat, 15 Nov 2025 19:03:42 +0800 Subject: [PATCH 02/12] fix: set uniform to 1 to avoid crash --- main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main.cpp b/main.cpp index 5d85b6f..2ae4f5e 100644 --- a/main.cpp +++ b/main.cpp @@ -48,7 +48,7 @@ layout (location = 0) in vec3 a_position; layout (location = 1) in vec4 a_color; layout (location = 0) out vec4 v_color; -layout(std140, set = 0, binding = 0) uniform Camera +layout(std140, set = 1, binding = 0) uniform Camera { mat4 uView; }; From 725429c2750501cffe2851b9bc74c4bd4805ee18 Mon Sep 17 00:00:00 2001 From: Sophomore <17792626+WSQS@users.noreply.github.com> Date: Sat, 15 Nov 2025 19:07:34 +0800 Subject: [PATCH 03/12] fix: using std:array --- main.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/main.cpp b/main.cpp index 2ae4f5e..486726b 100644 --- a/main.cpp +++ b/main.cpp @@ -23,7 +23,7 @@ struct Vertex struct CameraUniform { - float m[16]; + std::array m{}; }; class UserApp : public sopho::App @@ -91,11 +91,11 @@ void main() { // identity - cam.m[0] = cam.m[5] = cam.m[10] = cam.m[15] = 1.0f; - cam.m[1] = cam.m[2] = cam.m[3] = 0.0f; - cam.m[4] = cam.m[6] = cam.m[7] = 0.0f; - cam.m[8] = cam.m[9] = cam.m[11] = 0.0f; - cam.m[12] = cam.m[13] = cam.m[14] = 0.0f; + cam.m[0] = cam.m[5] = cam.m[10] = cam.m[15] = 1.0F; + cam.m[1] = cam.m[2] = cam.m[3] = 0.0F; + cam.m[4] = cam.m[6] = cam.m[7] = 0.0F; + cam.m[8] = cam.m[9] = cam.m[11] = 0.0F; + cam.m[12] = cam.m[13] = cam.m[14] = 0.0F; } @@ -258,7 +258,7 @@ void main() SDL_BindGPUGraphicsPipeline(renderPass, pipeline_wrapper.data()); { - SDL_PushGPUVertexUniformData(commandBuffer, 0,cam.m,sizeof(cam.m)); + SDL_PushGPUVertexUniformData(commandBuffer, 0,cam.m.data(),sizeof(cam.m)); } // bind the vertex buffer From 69cc71fc0e39e12b06a3ede54785460b5fd9584d Mon Sep 17 00:00:00 2001 From: Sophomore <17792626+WSQS@users.noreply.github.com> Date: Sat, 15 Nov 2025 19:43:34 +0800 Subject: [PATCH 04/12] fix: implement pitch and yaw for camera --- main.cpp | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 50 insertions(+), 2 deletions(-) diff --git a/main.cpp b/main.cpp index 486726b..82ce018 100644 --- a/main.cpp +++ b/main.cpp @@ -1,4 +1,5 @@ #include +#include #include #include #include "shaderc/shaderc.hpp" @@ -23,7 +24,7 @@ struct Vertex struct CameraUniform { - std::array m{}; + std::array m{}; }; class UserApp : public sopho::App @@ -32,6 +33,9 @@ class UserApp : public sopho::App sopho::BufferWrapper vertex_buffer{gpu_wrapper->create_buffer(SDL_GPU_BUFFERUSAGE_VERTEX, sizeof(vertices))}; sopho::PipelineWrapper pipeline_wrapper{gpu_wrapper->create_pipeline()}; + float yaw = 0.0f; + float pitch = 0.0f; + // a list of vertices std::array vertices{ Vertex{0.0F, 0.5F, 0.0F, 1.0F, 0.0F, 0.0F, 1.0F}, // top vertex @@ -258,7 +262,31 @@ void main() SDL_BindGPUGraphicsPipeline(renderPass, pipeline_wrapper.data()); { - SDL_PushGPUVertexUniformData(commandBuffer, 0,cam.m.data(),sizeof(cam.m)); + + float cy = std::cos(yaw); + float sy = std::sin(yaw); + float cp = std::cos(pitch); + float sp = std::sin(pitch); + + float Ry[16] = {cy, 0.0f, sy, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, -sy, 0.0f, cy, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}; + + float Rx[16] = {1.0f, 0.0f, 0.0f, 0.0f, 0.0f, cp, sp, 0.0f, 0.0f, -sp, cp, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}; + + auto mulMat4 = [](const float* A, const float* B, float* C) + { + for (int col = 0; col < 4; ++col) + { + for (int row = 0; row < 4; ++row) + { + C[col * 4 + row] = A[0 * 4 + row] * B[col * 4 + 0] + A[1 * 4 + row] * B[col * 4 + 1] + + A[2 * 4 + row] * B[col * 4 + 2] + A[3 * 4 + row] * B[col * 4 + 3]; + } + } + }; + + // uView = Rx * Ry + mulMat4(Rx, Ry, cam.m.data()); + SDL_PushGPUVertexUniformData(commandBuffer, 0, cam.m.data(), sizeof(cam.m)); } // bind the vertex buffer @@ -308,6 +336,26 @@ void main() virtual SDL_AppResult event(SDL_Event* event) override { ImGui_ImplSDL3_ProcessEvent(event); + if (event->type == SDL_EVENT_KEY_DOWN) + { + switch (reinterpret_cast(event)->key) + { + case SDLK_UP: + pitch += 0.1f; + break; + case SDLK_DOWN: + pitch -= 0.1f; + break; + case SDLK_LEFT: + yaw += 0.1f; + break; + case SDLK_RIGHT: + yaw -= 0.1f; + break; + default: + break; + } + } // close the window on request if (event->type == SDL_EVENT_WINDOW_CLOSE_REQUESTED) { From e222c3b2bb9ab9ebc2af4ceafa6383bb197d96e0 Mon Sep 17 00:00:00 2001 From: Sophomore <17792626+WSQS@users.noreply.github.com> Date: Sat, 15 Nov 2025 19:43:58 +0800 Subject: [PATCH 05/12] fix: Remove unused header file --- main.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/main.cpp b/main.cpp index 82ce018..d70263b 100644 --- a/main.cpp +++ b/main.cpp @@ -1,7 +1,6 @@ #include #include #include -#include #include "shaderc/shaderc.hpp" #include "imgui.h" @@ -11,7 +10,6 @@ #include #include -#include "SDL3/SDL_log.h" import sdl_wrapper; // the vertex input layout From c7c2a5f756c40d6c1ead260706cf518a9d066a6b Mon Sep 17 00:00:00 2001 From: Sophomore <17792626+WSQS@users.noreply.github.com> Date: Sat, 15 Nov 2025 19:58:19 +0800 Subject: [PATCH 06/12] fix: Remove unnecessary reinterpret_cast --- main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main.cpp b/main.cpp index d70263b..a57b56a 100644 --- a/main.cpp +++ b/main.cpp @@ -336,7 +336,7 @@ void main() ImGui_ImplSDL3_ProcessEvent(event); if (event->type == SDL_EVENT_KEY_DOWN) { - switch (reinterpret_cast(event)->key) + switch (event->key.key) { case SDLK_UP: pitch += 0.1f; From a3e8d2dba96d38d8b32d6cbda628bfb3bc8181ae Mon Sep 17 00:00:00 2001 From: Sophomore <17792626+WSQS@users.noreply.github.com> Date: Sun, 16 Nov 2025 09:50:47 +0800 Subject: [PATCH 07/12] feat: add clamp for pitch --- main.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/main.cpp b/main.cpp index a57b56a..1ba148b 100644 --- a/main.cpp +++ b/main.cpp @@ -340,9 +340,11 @@ void main() { case SDLK_UP: pitch += 0.1f; + pitch = std::clamp(pitch, -M_PI_2, M_PI_2); break; case SDLK_DOWN: pitch -= 0.1f; + pitch = std::clamp(pitch, -M_PI_2, M_PI_2); break; case SDLK_LEFT: yaw += 0.1f; From b97f81b6aed1476b5d866349de8a3e565bff3a69 Mon Sep 17 00:00:00 2001 From: "coderabbitai[bot]" <136622811+coderabbitai[bot]@users.noreply.github.com> Date: Sun, 16 Nov 2025 09:53:06 +0800 Subject: [PATCH 08/12] =?UTF-8?q?=F0=9F=93=9D=20Add=20docstrings=20to=20`c?= =?UTF-8?q?amera`=20(#31)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * 📝 Add docstrings to `camera` Docstrings generation was requested by @WSQS. * https://github.com/WSQS/sdl_test/pull/30#issuecomment-3536425889 The following files were modified: * `main.cpp` * style: format code with ClangFormat This commit fixes the style issues introduced in 10bd2e2 according to the output from ClangFormat. Details: https://github.com/WSQS/sdl_test/pull/31 --------- Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> Co-authored-by: deepsource-autofix[bot] <62050782+deepsource-autofix[bot]@users.noreply.github.com> --- main.cpp | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/main.cpp b/main.cpp index 1ba148b..5245c88 100644 --- a/main.cpp +++ b/main.cpp @@ -16,7 +16,12 @@ import sdl_wrapper; struct Vertex { float x, y, z; // vec3 position - float r, g, b, a; // vec4 color + float r, g, b, a; /** + * @brief Get a pointer to the vertex position's first component. + * + * @return float* Pointer to the `x` member; can be used to access the contiguous position + * components `(x, y, z)`. + */ auto position() { return &x; } }; @@ -72,12 +77,11 @@ void main() })WSQ"; /** - * @brief Initialize the application: create the window, configure GPU pipeline and resources, upload initial vertex - * data, and initialize ImGui. + * @brief Initialize application resources, GPU pipeline, vertex data, and Dear ImGui. * - * Performs window creation and GPU device claim, configures vertex input and color target state, sets vertex and - * fragment shaders on the pipeline wrapper and submits pipeline creation, uploads initial vertex data to the vertex - * buffer, and initializes Dear ImGui (context, style scaling, and SDL3/SDLGPU backends). + * Configures the graphics pipeline and vertex input, uploads the initial vertex buffer contents, + * initializes the camera uniform to the identity matrix, and sets up Dear ImGui (context, style/DPI + * scaling, and SDL3/SDLGPU backends). * * @return SDL_AppResult `SDL_APP_CONTINUE` to enter the main loop, `SDL_APP_SUCCESS` to request immediate * termination. @@ -211,12 +215,11 @@ void main() } /** - * @brief Render ImGui draw data and the application's triangle to the GPU, then present the swapchain texture. + * @brief Render the application's triangle and ImGui UI to the GPU and present the current swapchain frame. * - * Prepares ImGui draw data, submits the graphics pipeline, acquires a GPU command buffer and the current - * swapchain texture, records rendering commands (including binding the pipeline and vertex buffer and issuing - * a draw call), executes ImGui rendering into the render pass, and submits the command buffer for presentation. - * If no swapchain texture is available the function still submits the command buffer and continues. + * Records and submits GPU commands for drawing the triangle, uploads the per-frame camera uniform, + * renders ImGui draw data into the same render pass, and presents the swapchain texture. + * If no swapchain texture is available, the function still submits any recorded command buffer and continues. * * @return SDL_AppResult `SDL_APP_CONTINUE` to continue the application main loop. */ From 5b02e1e0c05a9340a93760255fd000ad9727a4bd Mon Sep 17 00:00:00 2001 From: Sophomore <17792626+WSQS@users.noreply.github.com> Date: Sun, 16 Nov 2025 10:00:41 +0800 Subject: [PATCH 09/12] feat: change float literal and switch to std::array --- main.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/main.cpp b/main.cpp index 5245c88..f3dc0db 100644 --- a/main.cpp +++ b/main.cpp @@ -269,9 +269,9 @@ void main() float cp = std::cos(pitch); float sp = std::sin(pitch); - float Ry[16] = {cy, 0.0f, sy, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, -sy, 0.0f, cy, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}; + std::array Ry = {cy, 0.0F, sy, 0.0F, 0.0F, 1.0F, 0.0F, 0.0F, -sy, 0.0F, cy, 0.0F, 0.0F, 0.0F, 0.0F, 1.0F}; - float Rx[16] = {1.0f, 0.0f, 0.0f, 0.0f, 0.0f, cp, sp, 0.0f, 0.0f, -sp, cp, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}; + std::array Rx = {1.0F, 0.0F, 0.0F, 0.0F, 0.0F, cp, sp, 0.0F, 0.0F, -sp, cp, 0.0F, 0.0F, 0.0F, 0.0F, 1.0F}; auto mulMat4 = [](const float* A, const float* B, float* C) { @@ -286,7 +286,7 @@ void main() }; // uView = Rx * Ry - mulMat4(Rx, Ry, cam.m.data()); + mulMat4(Rx.data(), Ry.data(), cam.m.data()); SDL_PushGPUVertexUniformData(commandBuffer, 0, cam.m.data(), sizeof(cam.m)); } @@ -342,18 +342,18 @@ void main() switch (event->key.key) { case SDLK_UP: - pitch += 0.1f; + pitch += 0.1F; pitch = std::clamp(pitch, -M_PI_2, M_PI_2); break; case SDLK_DOWN: - pitch -= 0.1f; + pitch -= 0.1F; pitch = std::clamp(pitch, -M_PI_2, M_PI_2); break; case SDLK_LEFT: - yaw += 0.1f; + yaw += 0.1F; break; case SDLK_RIGHT: - yaw -= 0.1f; + yaw -= 0.1F; break; default: break; From c433140937b1438ea01801b681a2390ca416893e Mon Sep 17 00:00:00 2001 From: Sophomore <17792626+WSQS@users.noreply.github.com> Date: Sun, 16 Nov 2025 10:04:26 +0800 Subject: [PATCH 10/12] feat: change tt std::numbers --- main.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/main.cpp b/main.cpp index f3dc0db..fd66eb0 100644 --- a/main.cpp +++ b/main.cpp @@ -1,6 +1,8 @@ #include #include #include +#include +#include #include "shaderc/shaderc.hpp" #include "imgui.h" @@ -8,8 +10,8 @@ #include "imgui_impl_sdlgpu3.h" #include "misc/cpp/imgui_stdlib.h" -#include -#include +#include "SDL3/SDL.h" +#include "SDL3/SDL_gpu.h" import sdl_wrapper; // the vertex input layout @@ -343,11 +345,11 @@ void main() { case SDLK_UP: pitch += 0.1F; - pitch = std::clamp(pitch, -M_PI_2, M_PI_2); + pitch = std::clamp(pitch, -std::numbers::pi / 2, std::numbers::pi / 2); break; case SDLK_DOWN: pitch -= 0.1F; - pitch = std::clamp(pitch, -M_PI_2, M_PI_2); + pitch = std::clamp(pitch, -std::numbers::pi / 2, std::numbers::pi / 2); break; case SDLK_LEFT: yaw += 0.1F; From f3eca94a7df3ab4bf3ba76deaec13239f86a180e Mon Sep 17 00:00:00 2001 From: "deepsource-autofix[bot]" <62050782+deepsource-autofix[bot]@users.noreply.github.com> Date: Sun, 16 Nov 2025 02:04:42 +0000 Subject: [PATCH 11/12] style: format code with ClangFormat This commit fixes the style issues introduced in c433140 according to the output from ClangFormat. Details: https://github.com/WSQS/sdl_test/pull/30 --- main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main.cpp b/main.cpp index fd66eb0..3def8e3 100644 --- a/main.cpp +++ b/main.cpp @@ -1,7 +1,7 @@ +#include #include #include #include -#include #include #include "shaderc/shaderc.hpp" From 38efee332afcb303531218a628033cb49b110aa5 Mon Sep 17 00:00:00 2001 From: Sophomore <17792626+WSQS@users.noreply.github.com> Date: Sun, 16 Nov 2025 10:24:03 +0800 Subject: [PATCH 12/12] fix: add header file --- main.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/main.cpp b/main.cpp index 3def8e3..b053b87 100644 --- a/main.cpp +++ b/main.cpp @@ -12,6 +12,7 @@ #include "SDL3/SDL.h" #include "SDL3/SDL_gpu.h" +#include "SDL3/SDL_keycode.h" import sdl_wrapper; // the vertex input layout