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 position;
|
||||||
glm::vec3 normal;
|
glm::vec3 normal;
|
||||||
glm::vec2 uv;
|
glm::vec2 uv;
|
||||||
|
glm::vec3 color;
|
||||||
};
|
};
|
||||||
|
|
||||||
std::uint32_t const div = 32;
|
std::uint32_t const div = 32;
|
||||||
std::vector<vertex> vertices;
|
std::vector<vertex> vertices;
|
||||||
std::vector<std::uint32_t> indices;
|
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
|
// Generate 6 cube faces, each with div x div vertices
|
||||||
auto add_face = [&](glm::vec3 const& center, glm::vec3 const& u_axis,
|
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 i = 0; i < div; ++i) {
|
||||||
for (std::uint32_t j = 0; j < div; ++j) {
|
for (std::uint32_t j = 0; j < div; ++j) {
|
||||||
float const s = float(i) / float(div - 1) * 2.0f - 1.0f;
|
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);
|
float const len = glm::length(pos);
|
||||||
glm::vec3 normal = pos / len;
|
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)
|
// +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)
|
// -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)
|
// +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)
|
// -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)
|
// +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)
|
// -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
|
// Generate indices for each face
|
||||||
std::uint32_t offset = 0;
|
std::uint32_t offset = 0;
|
||||||
@@ -132,16 +143,21 @@ auto sphere::build_mesh() -> void {
|
|||||||
// location 1: normal (vec3)
|
// location 1: normal (vec3)
|
||||||
glEnableVertexAttribArray(1);
|
glEnableVertexAttribArray(1);
|
||||||
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(vertex),
|
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)
|
// location 2: uv (vec2)
|
||||||
glEnableVertexAttribArray(2);
|
glEnableVertexAttribArray(2);
|
||||||
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(vertex),
|
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_vao.unbind();
|
||||||
|
m_vbo.unbind();
|
||||||
|
m_ebo.unbind();
|
||||||
}
|
}
|
||||||
|
|
||||||
auto sphere::build_shader() -> bool {
|
auto sphere::build_shader() -> bool {
|
||||||
@@ -150,17 +166,20 @@ auto sphere::build_shader() -> bool {
|
|||||||
layout(location = 0) in vec3 a_pos;
|
layout(location = 0) in vec3 a_pos;
|
||||||
layout(location = 1) in vec3 a_normal;
|
layout(location = 1) in vec3 a_normal;
|
||||||
layout(location = 2) in vec2 a_uv;
|
layout(location = 2) in vec2 a_uv;
|
||||||
|
layout(location = 3) in vec3 a_color;
|
||||||
uniform mat4 u_model;
|
uniform mat4 u_model;
|
||||||
uniform mat4 u_view;
|
uniform mat4 u_view;
|
||||||
uniform mat4 u_proj;
|
uniform mat4 u_proj;
|
||||||
out vec3 v_normal;
|
out vec3 v_normal;
|
||||||
out vec3 v_world_pos;
|
out vec3 v_world_pos;
|
||||||
out vec2 v_uv;
|
out vec2 v_uv;
|
||||||
|
out vec3 v_color;
|
||||||
void main() {
|
void main() {
|
||||||
gl_Position = u_proj * u_view * u_model * vec4(a_pos, 1.0);
|
gl_Position = u_proj * u_view * u_model * vec4(a_pos, 1.0);
|
||||||
v_normal = mat3(u_model) * a_normal;
|
v_normal = mat3(u_model) * a_normal;
|
||||||
v_world_pos = (u_model * vec4(a_pos, 1.0)).xyz;
|
v_world_pos = (u_model * vec4(a_pos, 1.0)).xyz;
|
||||||
v_uv = a_uv;
|
v_uv = a_uv;
|
||||||
|
v_color = a_color;
|
||||||
}
|
}
|
||||||
)glsl";
|
)glsl";
|
||||||
|
|
||||||
@@ -169,14 +188,14 @@ auto sphere::build_shader() -> bool {
|
|||||||
in vec3 v_normal;
|
in vec3 v_normal;
|
||||||
in vec3 v_world_pos;
|
in vec3 v_world_pos;
|
||||||
in vec2 v_uv;
|
in vec2 v_uv;
|
||||||
|
in vec3 v_color;
|
||||||
out vec4 frag_color;
|
out vec4 frag_color;
|
||||||
void main() {
|
void main() {
|
||||||
vec3 light_dir = normalize(vec3(1.0, 1.0, 2.0));
|
vec3 light_dir = normalize(vec3(1.0, 1.0, 2.0));
|
||||||
vec3 normal = normalize(v_normal);
|
vec3 normal = normalize(v_normal);
|
||||||
float diff = max(dot(normal, light_dir), 0.0);
|
float diff = max(dot(normal, light_dir), 0.0);
|
||||||
vec3 ambient = vec3(0.2);
|
vec3 ambient = vec3(0.2);
|
||||||
vec3 color = vec3(0.4, 0.6, 1.0);
|
vec3 result = (ambient + diff * 0.8) * v_color;
|
||||||
vec3 result = (ambient + diff * 0.8) * color;
|
|
||||||
frag_color = vec4(result, 1.0);
|
frag_color = vec4(result, 1.0);
|
||||||
}
|
}
|
||||||
)glsl";
|
)glsl";
|
||||||
|
|||||||
Reference in New Issue
Block a user