From 3a5f69b6f387464f4e9d625fc8a05e98eccaf80e Mon Sep 17 00:00:00 2001 From: Jelle Raaijmakers Date: Thu, 30 Dec 2021 00:27:17 +0100 Subject: LibGL+LibSoftGPU: Implement normalization of normals * LibGL now supports the `GL_NORMALIZE` capability * LibSoftGPU transforms and normalizes the vertices' normals Normals are heavily used in texture coordinate generation, to be implemented in a future commit. --- Userland/Libraries/LibGL/SoftwareGLContext.cpp | 23 ++++++++++++++++++++++- Userland/Libraries/LibGL/SoftwareGLContext.h | 1 + Userland/Libraries/LibSoftGPU/Device.cpp | 14 ++++++++++++-- Userland/Libraries/LibSoftGPU/Device.h | 4 +++- 4 files changed, 38 insertions(+), 4 deletions(-) (limited to 'Userland') diff --git a/Userland/Libraries/LibGL/SoftwareGLContext.cpp b/Userland/Libraries/LibGL/SoftwareGLContext.cpp index b8eeadc0a5..2e32999aaf 100644 --- a/Userland/Libraries/LibGL/SoftwareGLContext.cpp +++ b/Userland/Libraries/LibGL/SoftwareGLContext.cpp @@ -280,7 +280,16 @@ void SoftwareGLContext::gl_end() VERIFY_NOT_REACHED(); } - m_rasterizer.draw_primitives(primitive_type, m_projection_matrix * m_model_view_matrix, m_texture_matrix, m_vertex_list, enabled_texture_units); + // Set up normals transform by taking the upper left 3x3 elements from the model view matrix + // See section 2.11.3 of the OpenGL 1.5 spec + auto const& mv_elements = m_model_view_matrix.elements(); + auto normal_transform = FloatMatrix3x3( + mv_elements[0][0], mv_elements[0][1], mv_elements[0][2], + mv_elements[1][0], mv_elements[1][1], mv_elements[1][2], + mv_elements[2][0], mv_elements[2][1], mv_elements[2][2]); + normal_transform = normal_transform.inverse(); + + m_rasterizer.draw_primitives(primitive_type, m_projection_matrix * m_model_view_matrix, normal_transform, m_texture_matrix, m_vertex_list, enabled_texture_units); m_vertex_list.clear_with_capacity(); } @@ -619,6 +628,11 @@ void SoftwareGLContext::gl_enable(GLenum capability) case GL_LIGHTING: m_lighting_enabled = true; break; + case GL_NORMALIZE: + m_normalize = true; + rasterizer_options.normalization_enabled = true; + update_rasterizer_options = true; + break; case GL_SCISSOR_TEST: rasterizer_options.scissor_enabled = true; update_rasterizer_options = true; @@ -690,6 +704,11 @@ void SoftwareGLContext::gl_disable(GLenum capability) case GL_LIGHTING: m_lighting_enabled = false; break; + case GL_NORMALIZE: + m_normalize = false; + rasterizer_options.normalization_enabled = false; + update_rasterizer_options = true; + break; case GL_SCISSOR_TEST: rasterizer_options.scissor_enabled = false; update_rasterizer_options = true; @@ -742,6 +761,8 @@ GLboolean SoftwareGLContext::gl_is_enabled(GLenum capability) return rasterizer_options.fog_enabled; case GL_LIGHTING: return m_lighting_enabled; + case GL_NORMALIZE: + return m_normalize; case GL_SCISSOR_TEST: return rasterizer_options.scissor_enabled; case GL_STENCIL_TEST: diff --git a/Userland/Libraries/LibGL/SoftwareGLContext.h b/Userland/Libraries/LibGL/SoftwareGLContext.h index 8ef1452fce..0b893c3a92 100644 --- a/Userland/Libraries/LibGL/SoftwareGLContext.h +++ b/Userland/Libraries/LibGL/SoftwareGLContext.h @@ -206,6 +206,7 @@ private: GLclampf m_alpha_test_ref_value = 0; bool m_dither_enabled { true }; + bool m_normalize { false }; // Stencil configuration bool m_stencil_test_enabled { false }; diff --git a/Userland/Libraries/LibSoftGPU/Device.cpp b/Userland/Libraries/LibSoftGPU/Device.cpp index a3715f7c70..3602dc5752 100644 --- a/Userland/Libraries/LibSoftGPU/Device.cpp +++ b/Userland/Libraries/LibSoftGPU/Device.cpp @@ -524,7 +524,8 @@ DeviceInfo Device::info() const }; } -void Device::draw_primitives(PrimitiveType primitive_type, FloatMatrix4x4 const& transform, FloatMatrix4x4 const& texture_matrix, Vector const& vertices, Vector const& enabled_texture_units) +void Device::draw_primitives(PrimitiveType primitive_type, FloatMatrix4x4 const& transform, FloatMatrix3x3 const& normal_transform, + FloatMatrix4x4 const& texture_transform, Vector const& vertices, Vector const& enabled_texture_units) { // At this point, the user has effectively specified that they are done with defining the geometry // of what they want to draw. We now need to do a few things (https://www.khronos.org/opengl/wiki/Rendering_Pipeline_Overview): @@ -675,8 +676,17 @@ void Device::draw_primitives(PrimitiveType primitive_type, FloatMatrix4x4 const& continue; } - if (area > 0) { + if (area > 0) swap(triangle.vertices[0], triangle.vertices[1]); + + // Transform normals + triangle.vertices[0].normal = normal_transform * triangle.vertices[0].normal; + triangle.vertices[1].normal = normal_transform * triangle.vertices[1].normal; + triangle.vertices[2].normal = normal_transform * triangle.vertices[2].normal; + if (m_options.normalization_enabled) { + triangle.vertices[0].normal.normalize(); + triangle.vertices[1].normal.normalize(); + triangle.vertices[2].normal.normalize(); } submit_triangle(triangle, enabled_texture_units); diff --git a/Userland/Libraries/LibSoftGPU/Device.h b/Userland/Libraries/LibSoftGPU/Device.h index 67c6b83569..1f8ebbdae5 100644 --- a/Userland/Libraries/LibSoftGPU/Device.h +++ b/Userland/Libraries/LibSoftGPU/Device.h @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -47,6 +48,7 @@ struct RasterizerOptions { float fog_start { 0.0f }; float fog_end { 1.0f }; bool scissor_enabled { false }; + bool normalization_enabled { false }; Gfx::IntRect scissor_box; bool enable_color_write { true }; float depth_offset_factor { 0 }; @@ -65,7 +67,7 @@ public: DeviceInfo info() const; - void draw_primitives(PrimitiveType, FloatMatrix4x4 const& transform, FloatMatrix4x4 const& texture_matrix, Vector const& vertices, Vector const& enabled_texture_units); + void draw_primitives(PrimitiveType, FloatMatrix4x4 const& transform, FloatMatrix3x3 const& normal_transform, FloatMatrix4x4 const& texture_transform, Vector const& vertices, Vector const& enabled_texture_units); void resize(const Gfx::IntSize& min_size); void clear_color(const FloatVector4&); void clear_depth(float); -- cgit v1.2.3