From 865e7bbe5e76c701cfdbdbc917b496a0c26c8216 Mon Sep 17 00:00:00 2001 From: Jesse Buhagiar Date: Sat, 15 Jan 2022 16:16:01 +1100 Subject: [PATCH] LibGL+LibSoftGPU+3DFileViewer: Implement Specular highlighting :^) --- Userland/Applications/3DFileViewer/main.cpp | 10 +++++++++ Userland/Libraries/LibGL/GL/gl.h | 1 + .../Libraries/LibGL/SoftwareGLContext.cpp | 6 +++++ Userland/Libraries/LibSoftGPU/Device.cpp | 22 +++++++++++++++---- 4 files changed, 35 insertions(+), 4 deletions(-) diff --git a/Userland/Applications/3DFileViewer/main.cpp b/Userland/Applications/3DFileViewer/main.cpp index d7171625fe..996018dff1 100644 --- a/Userland/Applications/3DFileViewer/main.cpp +++ b/Userland/Applications/3DFileViewer/main.cpp @@ -187,16 +187,26 @@ void GLContextWidget::timer_event(Core::TimerEvent&) // Disco time ;) GLfloat const light0_position[4] = { -4.0f, 0.0f, 0.0f, 0.0f }; GLfloat const light0_diffuse[4] = { 1.0f, 0.0f, 0.0f, 0.0f }; + GLfloat const light0_specular[4] = { 0.75f, 0.75f, 0.75f }; GLfloat const light1_position[4] = { 4.0f, 0.0f, 0.0f, 0.0f }; GLfloat const light1_diffuse[4] = { 0.0f, 1.0f, 0.0f, 0.0f }; + GLfloat const light1_specular[4] = { 0.75f, 0.75f, 0.75f }; GLfloat const light2_position[4] = { 0.0f, 5.0f, 0.0f, 0.0f }; GLfloat const light2_diffuse[4] = { 0.0f, 0.0f, 1.0f, 0.0f }; + GLfloat const light2_specular[4] = { 0.75f, 0.75f, 0.75f }; glLightfv(GL_LIGHT0, GL_POSITION, &light0_position[0]); glLightfv(GL_LIGHT0, GL_DIFFUSE, &light0_diffuse[0]); + glLightfv(GL_LIGHT0, GL_SPECULAR, &light0_specular[0]); glLightfv(GL_LIGHT1, GL_POSITION, &light1_position[0]); glLightfv(GL_LIGHT1, GL_DIFFUSE, &light1_diffuse[0]); + glLightfv(GL_LIGHT1, GL_SPECULAR, &light1_specular[0]); glLightfv(GL_LIGHT2, GL_POSITION, &light2_position[0]); glLightfv(GL_LIGHT2, GL_DIFFUSE, &light2_diffuse[0]); + glLightfv(GL_LIGHT2, GL_SPECULAR, &light2_specular[0]); + + GLfloat const material_specular_color[4] = { 1.0f, 1.0f, 1.0f, 1.0f }; + glMaterialf(GL_FRONT, GL_SHININESS, 45.0f); + glMaterialfv(GL_FRONT, GL_SPECULAR, &material_specular_color[0]); glPopMatrix(); if (m_texture_enabled) { diff --git a/Userland/Libraries/LibGL/GL/gl.h b/Userland/Libraries/LibGL/GL/gl.h index af297e3740..1112866de7 100644 --- a/Userland/Libraries/LibGL/GL/gl.h +++ b/Userland/Libraries/LibGL/GL/gl.h @@ -260,6 +260,7 @@ extern "C" { // Lighting related defines #define GL_LIGHTING 0x0B50 +#define GL_LIGHT_MODEL_LOCAL_VIEWER 0x0B51 #define GL_LIGHT_MODEL_TWO_SIDE 0x0B52 #define GL_LIGHT_MODEL_AMBIENT 0x0B53 diff --git a/Userland/Libraries/LibGL/SoftwareGLContext.cpp b/Userland/Libraries/LibGL/SoftwareGLContext.cpp index df13f30e15..1186d4faf4 100644 --- a/Userland/Libraries/LibGL/SoftwareGLContext.cpp +++ b/Userland/Libraries/LibGL/SoftwareGLContext.cpp @@ -2764,6 +2764,12 @@ void SoftwareGLContext::gl_light_model(GLenum pname, GLfloat x, GLfloat y, GLflo lighting_params.two_sided_lighting = x; update_lighting_model = true; break; + case GL_LIGHT_MODEL_LOCAL_VIEWER: + // 0 means the viewer is at infinity + // 1 means they're in local (eye) space + lighting_params.viewer_at_infinity = (x != 1.0f); + update_lighting_model = true; + break; default: VERIFY_NOT_REACHED(); } diff --git a/Userland/Libraries/LibSoftGPU/Device.cpp b/Userland/Libraries/LibSoftGPU/Device.cpp index 19ecf5348c..3db2d7320e 100644 --- a/Userland/Libraries/LibSoftGPU/Device.cpp +++ b/Userland/Libraries/LibSoftGPU/Device.cpp @@ -856,9 +856,6 @@ void Device::draw_primitives(PrimitiveType primitive_type, FloatMatrix4x4 const& spotlight_factor = 0.0f; } - // FIXME: Specular. The math for it doesn't quite make sense... - (void)m_lighting_model.viewer_at_infinity; - // FIXME: The spec allows for splitting the colors calculated here into multiple different colors (primary/secondary color). Investigate what this means. (void)m_lighting_model.single_color; @@ -870,10 +867,27 @@ void Device::draw_primitives(PrimitiveType primitive_type, FloatMatrix4x4 const& // Diffuse auto const normal_dot_vertex_to_light = sgi_dot_operator(vertex.normal, vertex_to_light); - auto const diffuse_component = ((diffuse * light.diffuse_intensity) * normal_dot_vertex_to_light).clamped(0.0f, 1.0f); + auto const diffuse_component = ((diffuse * light.diffuse_intensity) * normal_dot_vertex_to_light); + + // Specular + FloatVector4 specular_component = { 0.0f, 0.0f, 0.0f, 0.0f }; + if (normal_dot_vertex_to_light > 0.0f) { + FloatVector3 half_vector_normalized; + if (!m_lighting_model.viewer_at_infinity) { + half_vector_normalized = (vertex_to_light + FloatVector3(0.0f, 0.0f, 1.0f)).normalized(); + } else { + auto const vertex_to_eye_point = sgi_arrow_operator(vertex.eye_coordinates.normalized(), FloatVector4(0.0f, 0.0f, 0.0f, 1.0f), vector_length); + half_vector_normalized = vertex_to_light + vertex_to_eye_point; + } + + auto const normal_dot_half_vector = sgi_dot_operator(vertex.normal.normalized(), half_vector_normalized); + auto const specular_coefficient = AK::pow(normal_dot_half_vector, material.shininess); + specular_component = (specular * light.specular_intensity) * specular_coefficient; + } FloatVector4 color = ambient_component; color += diffuse_component; + color += specular_component; color = color * light_attenuation_factor * spotlight_factor; result_color += color; }