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.
This commit is contained in:
+33
-14
@@ -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<vertex> vertices;
|
||||
std::vector<std::uint32_t> 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<void*>(offsetof(vertex, normal)));
|
||||
reinterpret_cast<void*>(3 * sizeof(float)));
|
||||
|
||||
// location 2: uv (vec2)
|
||||
glEnableVertexAttribArray(2);
|
||||
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(vertex),
|
||||
reinterpret_cast<void*>(3 * sizeof(float) + 3 * sizeof(float)));
|
||||
reinterpret_cast<void*>(6 * sizeof(float)));
|
||||
|
||||
// location 3: color (vec3)
|
||||
glEnableVertexAttribArray(3);
|
||||
glVertexAttribPointer(3, 3, GL_FLOAT, GL_FALSE, sizeof(vertex),
|
||||
reinterpret_cast<void*>(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";
|
||||
|
||||
Reference in New Issue
Block a user