From 91fe3c6e8ca6583fff6a3c71feed0e0af9fd8637 Mon Sep 17 00:00:00 2001 From: portersky <24420859+portersky@users.noreply.github.com> Date: Wed, 6 May 2026 00:01:17 +0200 Subject: [PATCH] style: color-code sphere faces to visualize seams Each of the 6 cube-to-sphere faces now has a distinct color (red, green, blue, yellow, magenta, cyan) passed via a vertex color attribute. The fragment shader multiplies lighting by this color instead of a uniform blue. This makes the cube-face seams clearly visible when inspecting the mapped sphere. --- scenes/sphere.cpp | 47 +++++++++++++++++++++++++++++++++-------------- 1 file changed, 33 insertions(+), 14 deletions(-) diff --git a/scenes/sphere.cpp b/scenes/sphere.cpp index d8514ac..37d4276 100644 --- a/scenes/sphere.cpp +++ b/scenes/sphere.cpp @@ -53,15 +53,26 @@ auto sphere::build_mesh() -> void { glm::vec3 position; glm::vec3 normal; glm::vec2 uv; + glm::vec3 color; }; std::uint32_t const div = 32; std::vector vertices; std::vector indices; + // Distinct colors for each cube face so seams are visible + glm::vec3 const face_colors[6] = { + {1.0f, 0.2f, 0.2f}, // +X red + {0.2f, 1.0f, 0.2f}, // -X green + {0.2f, 0.2f, 1.0f}, // +Y blue + {1.0f, 1.0f, 0.2f}, // -Y yellow + {1.0f, 0.2f, 1.0f}, // +Z magenta + {0.2f, 1.0f, 1.0f}, // -Z cyan + }; + // Generate 6 cube faces, each with div x div vertices auto add_face = [&](glm::vec3 const& center, glm::vec3 const& u_axis, - glm::vec3 const& v_axis) -> void { + glm::vec3 const& v_axis, std::uint32_t face_idx) -> void { for (std::uint32_t i = 0; i < div; ++i) { for (std::uint32_t j = 0; j < div; ++j) { float const s = float(i) / float(div - 1) * 2.0f - 1.0f; @@ -75,23 +86,23 @@ auto sphere::build_mesh() -> void { float const len = glm::length(pos); glm::vec3 normal = pos / len; - vertices.push_back({normal, normal, {float(i) / float(div - 1), float(j) / float(div - 1)}}); + vertices.push_back({normal, normal, {float(i) / float(div - 1), float(j) / float(div - 1)}, face_colors[face_idx]}); } } }; // +X face (right) - add_face(glm::vec3{1.0f, 0.0f, 0.0f}, glm::vec3{0.0f, 1.0f, 0.0f}, glm::vec3{0.0f, 0.0f, 1.0f}); + add_face(glm::vec3{1.0f, 0.0f, 0.0f}, glm::vec3{0.0f, 1.0f, 0.0f}, glm::vec3{0.0f, 0.0f, 1.0f}, 0); // -X face (left) - add_face(glm::vec3{-1.0f, 0.0f, 0.0f}, glm::vec3{0.0f, 1.0f, 0.0f}, glm::vec3{0.0f, 0.0f, -1.0f}); + add_face(glm::vec3{-1.0f, 0.0f, 0.0f}, glm::vec3{0.0f, 1.0f, 0.0f}, glm::vec3{0.0f, 0.0f, -1.0f}, 1); // +Y face (top) - add_face(glm::vec3{0.0f, 1.0f, 0.0f}, glm::vec3{1.0f, 0.0f, 0.0f}, glm::vec3{0.0f, 0.0f, -1.0f}); + add_face(glm::vec3{0.0f, 1.0f, 0.0f}, glm::vec3{1.0f, 0.0f, 0.0f}, glm::vec3{0.0f, 0.0f, -1.0f}, 2); // -Y face (bottom) - add_face(glm::vec3{0.0f, -1.0f, 0.0f}, glm::vec3{1.0f, 0.0f, 0.0f}, glm::vec3{0.0f, 0.0f, 1.0f}); + add_face(glm::vec3{0.0f, -1.0f, 0.0f}, glm::vec3{1.0f, 0.0f, 0.0f}, glm::vec3{0.0f, 0.0f, 1.0f}, 3); // +Z face (front) - add_face(glm::vec3{0.0f, 0.0f, 1.0f}, glm::vec3{1.0f, 0.0f, 0.0f}, glm::vec3{0.0f, 1.0f, 0.0f}); + add_face(glm::vec3{0.0f, 0.0f, 1.0f}, glm::vec3{1.0f, 0.0f, 0.0f}, glm::vec3{0.0f, 1.0f, 0.0f}, 4); // -Z face (back) - add_face(glm::vec3{0.0f, 0.0f, -1.0f}, glm::vec3{-1.0f, 0.0f, 0.0f}, glm::vec3{0.0f, 1.0f, 0.0f}); + add_face(glm::vec3{0.0f, 0.0f, -1.0f}, glm::vec3{-1.0f, 0.0f, 0.0f}, glm::vec3{0.0f, 1.0f, 0.0f}, 5); // Generate indices for each face std::uint32_t offset = 0; @@ -132,16 +143,21 @@ auto sphere::build_mesh() -> void { // location 1: normal (vec3) glEnableVertexAttribArray(1); glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(vertex), - reinterpret_cast(offsetof(vertex, normal))); + reinterpret_cast(3 * sizeof(float))); // location 2: uv (vec2) glEnableVertexAttribArray(2); glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(vertex), - reinterpret_cast(3 * sizeof(float) + 3 * sizeof(float))); + reinterpret_cast(6 * sizeof(float))); + + // location 3: color (vec3) + glEnableVertexAttribArray(3); + glVertexAttribPointer(3, 3, GL_FLOAT, GL_FALSE, sizeof(vertex), + reinterpret_cast(8 * sizeof(float))); - m_ebo.unbind(); - m_vbo.unbind(); m_vao.unbind(); + m_vbo.unbind(); + m_ebo.unbind(); } auto sphere::build_shader() -> bool { @@ -150,17 +166,20 @@ auto sphere::build_shader() -> bool { layout(location = 0) in vec3 a_pos; layout(location = 1) in vec3 a_normal; layout(location = 2) in vec2 a_uv; + layout(location = 3) in vec3 a_color; uniform mat4 u_model; uniform mat4 u_view; uniform mat4 u_proj; out vec3 v_normal; out vec3 v_world_pos; out vec2 v_uv; + out vec3 v_color; void main() { gl_Position = u_proj * u_view * u_model * vec4(a_pos, 1.0); v_normal = mat3(u_model) * a_normal; v_world_pos = (u_model * vec4(a_pos, 1.0)).xyz; v_uv = a_uv; + v_color = a_color; } )glsl"; @@ -169,14 +188,14 @@ auto sphere::build_shader() -> bool { in vec3 v_normal; in vec3 v_world_pos; in vec2 v_uv; + in vec3 v_color; out vec4 frag_color; void main() { vec3 light_dir = normalize(vec3(1.0, 1.0, 2.0)); vec3 normal = normalize(v_normal); float diff = max(dot(normal, light_dir), 0.0); vec3 ambient = vec3(0.2); - vec3 color = vec3(0.4, 0.6, 1.0); - vec3 result = (ambient + diff * 0.8) * color; + vec3 result = (ambient + diff * 0.8) * v_color; frag_color = vec4(result, 1.0); } )glsl";