From 12f63df329148148f32dc50c4f6cadf6af73a6ac Mon Sep 17 00:00:00 2001 From: Stephan Unverwerth Date: Sat, 15 Jan 2022 21:08:57 +0100 Subject: [PATCH] LibGL+LibSoftGPU: Support generation of multiple texture coordinates --- .../Libraries/LibGL/SoftwareGLContext.cpp | 122 ++++++++++-------- Userland/Libraries/LibGL/SoftwareGLContext.h | 31 +---- Userland/Libraries/LibSoftGPU/Device.cpp | 37 ++++-- Userland/Libraries/LibSoftGPU/Device.h | 4 +- 4 files changed, 101 insertions(+), 93 deletions(-) diff --git a/Userland/Libraries/LibGL/SoftwareGLContext.cpp b/Userland/Libraries/LibGL/SoftwareGLContext.cpp index 4b7e515512..fed22b9269 100644 --- a/Userland/Libraries/LibGL/SoftwareGLContext.cpp +++ b/Userland/Libraries/LibGL/SoftwareGLContext.cpp @@ -83,6 +83,21 @@ SoftwareGLContext::SoftwareGLContext(Gfx::Bitmap& frontbuffer) for (auto& tex_coord : m_current_vertex_tex_coord) tex_coord = { 0.0f, 0.0f, 0.0f, 1.0f }; + // Initialize the texture coordinate generation coefficients + // Indices 0,1,2,3 refer to the S,T,R and Q coordinate of the respective texture + // coordinate generation config. + m_texture_coordinate_generation.resize(m_device_info.num_texture_units); + for (auto& texture_coordinate_generation : m_texture_coordinate_generation) { + texture_coordinate_generation[0].object_plane_coefficients = { 1.0f, 0.0f, 0.0f, 0.0f }; + texture_coordinate_generation[0].eye_plane_coefficients = { 1.0f, 0.0f, 0.0f, 0.0f }; + texture_coordinate_generation[1].object_plane_coefficients = { 0.0f, 1.0f, 0.0f, 0.0f }; + texture_coordinate_generation[1].eye_plane_coefficients = { 0.0f, 1.0f, 0.0f, 0.0f }; + texture_coordinate_generation[2].object_plane_coefficients = { 0.0f, 0.0f, 0.0f, 0.0f }; + texture_coordinate_generation[2].eye_plane_coefficients = { 0.0f, 0.0f, 0.0f, 0.0f }; + texture_coordinate_generation[3].object_plane_coefficients = { 0.0f, 0.0f, 0.0f, 0.0f }; + texture_coordinate_generation[3].eye_plane_coefficients = { 0.0f, 0.0f, 0.0f, 0.0f }; + } + build_extension_string(); } @@ -191,7 +206,7 @@ Optional SoftwareGLContext::get_context_parameter(GLenum name) case GL_TEXTURE_GEN_R: case GL_TEXTURE_GEN_S: case GL_TEXTURE_GEN_T: { - auto generation_enabled = texture_coordinate_generation(name).enabled; + auto generation_enabled = texture_coordinate_generation(m_active_texture_unit_index, name).enabled; return ContextParameter { .type = GL_BOOL, .is_capability = true, .value = { .boolean_value = generation_enabled } }; } case GL_UNPACK_ALIGNMENT: @@ -748,7 +763,7 @@ void SoftwareGLContext::gl_enable(GLenum capability) case GL_TEXTURE_GEN_R: case GL_TEXTURE_GEN_S: case GL_TEXTURE_GEN_T: - texture_coordinate_generation(capability).enabled = true; + texture_coordinate_generation(m_active_texture_unit_index, capability).enabled = true; m_texcoord_generation_dirty = true; break; default: @@ -850,7 +865,7 @@ void SoftwareGLContext::gl_disable(GLenum capability) case GL_TEXTURE_GEN_R: case GL_TEXTURE_GEN_S: case GL_TEXTURE_GEN_T: - texture_coordinate_generation(capability).enabled = false; + texture_coordinate_generation(m_active_texture_unit_index, capability).enabled = false; m_texcoord_generation_dirty = true; break; default: @@ -2888,7 +2903,7 @@ void SoftwareGLContext::gl_tex_gen(GLenum coord, GLenum pname, GLint param) RETURN_WITH_ERROR_IF(coord == GL_Q && (param == GL_REFLECTION_MAP || param == GL_NORMAL_MAP), GL_INVALID_ENUM); GLenum const capability = GL_TEXTURE_GEN_S + (coord - GL_S); - texture_coordinate_generation(capability).generation_mode = param; + texture_coordinate_generation(m_active_texture_unit_index, capability).generation_mode = param; m_texcoord_generation_dirty = true; } @@ -2917,11 +2932,11 @@ void SoftwareGLContext::gl_tex_gen_floatv(GLenum coord, GLenum pname, GLfloat co RETURN_WITH_ERROR_IF((coord == GL_R || coord == GL_Q) && param == GL_SPHERE_MAP, GL_INVALID_ENUM); RETURN_WITH_ERROR_IF(coord == GL_Q && (param == GL_REFLECTION_MAP || param == GL_NORMAL_MAP), GL_INVALID_ENUM); - texture_coordinate_generation(capability).generation_mode = param; + texture_coordinate_generation(m_active_texture_unit_index, capability).generation_mode = param; break; } case GL_OBJECT_PLANE: - texture_coordinate_generation(capability).object_plane_coefficients = { params[0], params[1], params[2], params[3] }; + texture_coordinate_generation(m_active_texture_unit_index, capability).object_plane_coefficients = { params[0], params[1], params[2], params[3] }; break; case GL_EYE_PLANE: { auto const& inverse_model_view = m_model_view_matrix.inverse(); @@ -2933,7 +2948,7 @@ void SoftwareGLContext::gl_tex_gen_floatv(GLenum coord, GLenum pname, GLfloat co // "The returned values are those maintained in eye coordinates. They are not equal to the values // specified using glTexGen, unless the modelview matrix was identity when glTexGen was called." - texture_coordinate_generation(capability).eye_plane_coefficients = inverse_model_view * input_coefficients; + texture_coordinate_generation(m_active_texture_unit_index, capability).eye_plane_coefficients = inverse_model_view * input_coefficients; break; } default: @@ -3162,55 +3177,58 @@ void SoftwareGLContext::sync_device_texcoord_config() auto options = m_rasterizer.options(); - u8 enabled_coordinates = SoftGPU::TexCoordGenerationCoordinate::None; - for (GLenum capability = GL_TEXTURE_GEN_S; capability <= GL_TEXTURE_GEN_Q; ++capability) { - auto const context_coordinate_config = texture_coordinate_generation(capability); - if (!context_coordinate_config.enabled) - continue; + for (size_t i = 0; i < m_device_info.num_texture_units; ++i) { - SoftGPU::TexCoordGenerationConfig* texcoord_generation_config; - switch (capability) { - case GL_TEXTURE_GEN_S: - enabled_coordinates |= SoftGPU::TexCoordGenerationCoordinate::S; - texcoord_generation_config = &options.texcoord_generation_config[0]; - break; - case GL_TEXTURE_GEN_T: - enabled_coordinates |= SoftGPU::TexCoordGenerationCoordinate::T; - texcoord_generation_config = &options.texcoord_generation_config[1]; - break; - case GL_TEXTURE_GEN_R: - enabled_coordinates |= SoftGPU::TexCoordGenerationCoordinate::R; - texcoord_generation_config = &options.texcoord_generation_config[2]; - break; - case GL_TEXTURE_GEN_Q: - enabled_coordinates |= SoftGPU::TexCoordGenerationCoordinate::Q; - texcoord_generation_config = &options.texcoord_generation_config[3]; - break; - default: - VERIFY_NOT_REACHED(); - } + u8 enabled_coordinates = SoftGPU::TexCoordGenerationCoordinate::None; + for (GLenum capability = GL_TEXTURE_GEN_S; capability <= GL_TEXTURE_GEN_Q; ++capability) { + auto const context_coordinate_config = texture_coordinate_generation(i, capability); + if (!context_coordinate_config.enabled) + continue; - switch (context_coordinate_config.generation_mode) { - case GL_OBJECT_LINEAR: - texcoord_generation_config->mode = SoftGPU::TexCoordGenerationMode::ObjectLinear; - texcoord_generation_config->coefficients = context_coordinate_config.object_plane_coefficients; - break; - case GL_EYE_LINEAR: - texcoord_generation_config->mode = SoftGPU::TexCoordGenerationMode::EyeLinear; - texcoord_generation_config->coefficients = context_coordinate_config.eye_plane_coefficients; - break; - case GL_SPHERE_MAP: - texcoord_generation_config->mode = SoftGPU::TexCoordGenerationMode::SphereMap; - break; - case GL_REFLECTION_MAP: - texcoord_generation_config->mode = SoftGPU::TexCoordGenerationMode::ReflectionMap; - break; - case GL_NORMAL_MAP: - texcoord_generation_config->mode = SoftGPU::TexCoordGenerationMode::NormalMap; - break; + SoftGPU::TexCoordGenerationConfig* texcoord_generation_config; + switch (capability) { + case GL_TEXTURE_GEN_S: + enabled_coordinates |= SoftGPU::TexCoordGenerationCoordinate::S; + texcoord_generation_config = &options.texcoord_generation_config[i][0]; + break; + case GL_TEXTURE_GEN_T: + enabled_coordinates |= SoftGPU::TexCoordGenerationCoordinate::T; + texcoord_generation_config = &options.texcoord_generation_config[i][1]; + break; + case GL_TEXTURE_GEN_R: + enabled_coordinates |= SoftGPU::TexCoordGenerationCoordinate::R; + texcoord_generation_config = &options.texcoord_generation_config[i][2]; + break; + case GL_TEXTURE_GEN_Q: + enabled_coordinates |= SoftGPU::TexCoordGenerationCoordinate::Q; + texcoord_generation_config = &options.texcoord_generation_config[i][3]; + break; + default: + VERIFY_NOT_REACHED(); + } + + switch (context_coordinate_config.generation_mode) { + case GL_OBJECT_LINEAR: + texcoord_generation_config->mode = SoftGPU::TexCoordGenerationMode::ObjectLinear; + texcoord_generation_config->coefficients = context_coordinate_config.object_plane_coefficients; + break; + case GL_EYE_LINEAR: + texcoord_generation_config->mode = SoftGPU::TexCoordGenerationMode::EyeLinear; + texcoord_generation_config->coefficients = context_coordinate_config.eye_plane_coefficients; + break; + case GL_SPHERE_MAP: + texcoord_generation_config->mode = SoftGPU::TexCoordGenerationMode::SphereMap; + break; + case GL_REFLECTION_MAP: + texcoord_generation_config->mode = SoftGPU::TexCoordGenerationMode::ReflectionMap; + break; + case GL_NORMAL_MAP: + texcoord_generation_config->mode = SoftGPU::TexCoordGenerationMode::NormalMap; + break; + } } + options.texcoord_generation_enabled_coordinates[i] = enabled_coordinates; } - options.texcoord_generation_enabled_coordinates = enabled_coordinates; m_rasterizer.set_options(options); } diff --git a/Userland/Libraries/LibGL/SoftwareGLContext.h b/Userland/Libraries/LibGL/SoftwareGLContext.h index ff5c794afa..ce4ebd73f5 100644 --- a/Userland/Libraries/LibGL/SoftwareGLContext.h +++ b/Userland/Libraries/LibGL/SoftwareGLContext.h @@ -270,36 +270,15 @@ private: struct TextureCoordinateGeneration { bool enabled { false }; GLenum generation_mode { GL_EYE_LINEAR }; - FloatVector4 object_plane_coefficients; - FloatVector4 eye_plane_coefficients; - }; - Array m_texture_coordinate_generation { - // S - TextureCoordinateGeneration { - .object_plane_coefficients = { 1.0f, 0.0f, 0.0f, 0.0f }, - .eye_plane_coefficients = { 1.0f, 0.0f, 0.0f, 0.0f }, - }, - // T - TextureCoordinateGeneration { - .object_plane_coefficients = { 0.0f, 1.0f, 0.0f, 0.0f }, - .eye_plane_coefficients = { 0.0f, 1.0f, 0.0f, 0.0f }, - }, - // R - TextureCoordinateGeneration { - .object_plane_coefficients = { 0.0f, 0.0f, 0.0f, 0.0f }, - .eye_plane_coefficients = { 0.0f, 0.0f, 0.0f, 0.0f }, - }, - // Q - TextureCoordinateGeneration { - .object_plane_coefficients = { 0.0f, 0.0f, 0.0f, 0.0f }, - .eye_plane_coefficients = { 0.0f, 0.0f, 0.0f, 0.0f }, - }, + FloatVector4 object_plane_coefficients { 0.0f, 0.0f, 0.0f, 0.0f }; + FloatVector4 eye_plane_coefficients { 0.0f, 0.0f, 0.0f, 0.0f }; }; + Vector> m_texture_coordinate_generation; bool m_texcoord_generation_dirty { true }; - ALWAYS_INLINE TextureCoordinateGeneration& texture_coordinate_generation(GLenum capability) + ALWAYS_INLINE TextureCoordinateGeneration& texture_coordinate_generation(size_t texture_unit, GLenum capability) { - return m_texture_coordinate_generation[capability - GL_TEXTURE_GEN_S]; + return m_texture_coordinate_generation[texture_unit][capability - GL_TEXTURE_GEN_S]; } SoftGPU::Device m_rasterizer; diff --git a/Userland/Libraries/LibSoftGPU/Device.cpp b/Userland/Libraries/LibSoftGPU/Device.cpp index 944cbfd226..1268342006 100644 --- a/Userland/Libraries/LibSoftGPU/Device.cpp +++ b/Userland/Libraries/LibSoftGPU/Device.cpp @@ -612,16 +612,16 @@ DeviceInfo Device::info() const static void generate_texture_coordinates(Vertex& vertex, RasterizerOptions const& options) { - auto generate_coordinate = [&](size_t config_index) -> float { - auto mode = options.texcoord_generation_config[config_index].mode; + auto generate_coordinate = [&](size_t texcoord_index, size_t config_index) -> float { + auto mode = options.texcoord_generation_config[texcoord_index][config_index].mode; switch (mode) { case TexCoordGenerationMode::ObjectLinear: { - auto coefficients = options.texcoord_generation_config[config_index].coefficients; + auto coefficients = options.texcoord_generation_config[texcoord_index][config_index].coefficients; return coefficients.dot(vertex.position); } case TexCoordGenerationMode::EyeLinear: { - auto coefficients = options.texcoord_generation_config[config_index].coefficients; + auto coefficients = options.texcoord_generation_config[texcoord_index][config_index].coefficients; return coefficients.dot(vertex.eye_coordinates); } case TexCoordGenerationMode::SphereMap: { @@ -667,13 +667,16 @@ static void generate_texture_coordinates(Vertex& vertex, RasterizerOptions const } }; - auto const enabled_coords = options.texcoord_generation_enabled_coordinates; - vertex.tex_coords[0] = { - ((enabled_coords & TexCoordGenerationCoordinate::S) > 0) ? generate_coordinate(0) : vertex.tex_coords[0].x(), - ((enabled_coords & TexCoordGenerationCoordinate::T) > 0) ? generate_coordinate(1) : vertex.tex_coords[0].y(), - ((enabled_coords & TexCoordGenerationCoordinate::R) > 0) ? generate_coordinate(2) : vertex.tex_coords[0].z(), - ((enabled_coords & TexCoordGenerationCoordinate::Q) > 0) ? generate_coordinate(3) : vertex.tex_coords[0].w(), - }; + for (size_t i = 0; i < vertex.tex_coords.size(); ++i) { + auto& tex_coord = vertex.tex_coords[i]; + auto const enabled_coords = options.texcoord_generation_enabled_coordinates[i]; + tex_coord = { + ((enabled_coords & TexCoordGenerationCoordinate::S) > 0) ? generate_coordinate(i, 0) : tex_coord.x(), + ((enabled_coords & TexCoordGenerationCoordinate::T) > 0) ? generate_coordinate(i, 1) : tex_coord.y(), + ((enabled_coords & TexCoordGenerationCoordinate::R) > 0) ? generate_coordinate(i, 2) : tex_coord.z(), + ((enabled_coords & TexCoordGenerationCoordinate::Q) > 0) ? generate_coordinate(i, 3) : tex_coord.w(), + }; + } } void Device::draw_primitives(PrimitiveType primitive_type, FloatMatrix4x4 const& model_view_transform, FloatMatrix3x3 const& normal_transform, @@ -952,6 +955,15 @@ void Device::draw_primitives(PrimitiveType primitive_type, FloatMatrix4x4 const& } } + // Generate texture coordinates if at least one coordinate is enabled + bool texture_coordinate_generation_enabled = false; + for (auto const coordinates_enabled : m_options.texcoord_generation_enabled_coordinates) { + if (coordinates_enabled != TexCoordGenerationCoordinate::None) { + texture_coordinate_generation_enabled = true; + break; + } + } + for (auto& triangle : m_processed_triangles) { // Let's calculate the (signed) area of the triangle // https://cp-algorithms.com/geometry/oriented-triangle-area.html @@ -987,8 +999,7 @@ void Device::draw_primitives(PrimitiveType primitive_type, FloatMatrix4x4 const& triangle.vertices[2].normal.normalize(); } - // Generate texture coordinates if at least one coordinate is enabled - if (m_options.texcoord_generation_enabled_coordinates != TexCoordGenerationCoordinate::None) { + if (texture_coordinate_generation_enabled) { generate_texture_coordinates(triangle.vertices[0], m_options); generate_texture_coordinates(triangle.vertices[1], m_options); generate_texture_coordinates(triangle.vertices[2], m_options); diff --git a/Userland/Libraries/LibSoftGPU/Device.h b/Userland/Libraries/LibSoftGPU/Device.h index 8d761a49f5..d8de64fe3b 100644 --- a/Userland/Libraries/LibSoftGPU/Device.h +++ b/Userland/Libraries/LibSoftGPU/Device.h @@ -70,8 +70,8 @@ struct RasterizerOptions { WindingOrder front_face { WindingOrder::CounterClockwise }; bool cull_back { true }; bool cull_front { false }; - u8 texcoord_generation_enabled_coordinates { TexCoordGenerationCoordinate::None }; - Array texcoord_generation_config {}; + Array texcoord_generation_enabled_coordinates {}; + Array, NUM_SAMPLERS> texcoord_generation_config {}; Gfx::IntRect viewport; bool lighting_enabled { false }; bool color_material_enabled { false };