1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-23 18:17:41 +00:00

LibGL+LibSoftGPU: Support generation of multiple texture coordinates

This commit is contained in:
Stephan Unverwerth 2022-01-15 21:08:57 +01:00 committed by Andreas Kling
parent bc17a87450
commit 12f63df329
4 changed files with 101 additions and 93 deletions

View file

@ -83,6 +83,21 @@ SoftwareGLContext::SoftwareGLContext(Gfx::Bitmap& frontbuffer)
for (auto& tex_coord : m_current_vertex_tex_coord) for (auto& tex_coord : m_current_vertex_tex_coord)
tex_coord = { 0.0f, 0.0f, 0.0f, 1.0f }; 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(); build_extension_string();
} }
@ -191,7 +206,7 @@ Optional<ContextParameter> SoftwareGLContext::get_context_parameter(GLenum name)
case GL_TEXTURE_GEN_R: case GL_TEXTURE_GEN_R:
case GL_TEXTURE_GEN_S: case GL_TEXTURE_GEN_S:
case GL_TEXTURE_GEN_T: { 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 } }; return ContextParameter { .type = GL_BOOL, .is_capability = true, .value = { .boolean_value = generation_enabled } };
} }
case GL_UNPACK_ALIGNMENT: case GL_UNPACK_ALIGNMENT:
@ -748,7 +763,7 @@ void SoftwareGLContext::gl_enable(GLenum capability)
case GL_TEXTURE_GEN_R: case GL_TEXTURE_GEN_R:
case GL_TEXTURE_GEN_S: case GL_TEXTURE_GEN_S:
case GL_TEXTURE_GEN_T: 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; m_texcoord_generation_dirty = true;
break; break;
default: default:
@ -850,7 +865,7 @@ void SoftwareGLContext::gl_disable(GLenum capability)
case GL_TEXTURE_GEN_R: case GL_TEXTURE_GEN_R:
case GL_TEXTURE_GEN_S: case GL_TEXTURE_GEN_S:
case GL_TEXTURE_GEN_T: 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; m_texcoord_generation_dirty = true;
break; break;
default: 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); 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); 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; 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_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); 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; break;
} }
case GL_OBJECT_PLANE: 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; break;
case GL_EYE_PLANE: { case GL_EYE_PLANE: {
auto const& inverse_model_view = m_model_view_matrix.inverse(); 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 // "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." // 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; break;
} }
default: default:
@ -3162,55 +3177,58 @@ void SoftwareGLContext::sync_device_texcoord_config()
auto options = m_rasterizer.options(); auto options = m_rasterizer.options();
u8 enabled_coordinates = SoftGPU::TexCoordGenerationCoordinate::None; for (size_t i = 0; i < m_device_info.num_texture_units; ++i) {
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;
SoftGPU::TexCoordGenerationConfig* texcoord_generation_config; u8 enabled_coordinates = SoftGPU::TexCoordGenerationCoordinate::None;
switch (capability) { for (GLenum capability = GL_TEXTURE_GEN_S; capability <= GL_TEXTURE_GEN_Q; ++capability) {
case GL_TEXTURE_GEN_S: auto const context_coordinate_config = texture_coordinate_generation(i, capability);
enabled_coordinates |= SoftGPU::TexCoordGenerationCoordinate::S; if (!context_coordinate_config.enabled)
texcoord_generation_config = &options.texcoord_generation_config[0]; continue;
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();
}
switch (context_coordinate_config.generation_mode) { SoftGPU::TexCoordGenerationConfig* texcoord_generation_config;
case GL_OBJECT_LINEAR: switch (capability) {
texcoord_generation_config->mode = SoftGPU::TexCoordGenerationMode::ObjectLinear; case GL_TEXTURE_GEN_S:
texcoord_generation_config->coefficients = context_coordinate_config.object_plane_coefficients; enabled_coordinates |= SoftGPU::TexCoordGenerationCoordinate::S;
break; texcoord_generation_config = &options.texcoord_generation_config[i][0];
case GL_EYE_LINEAR: break;
texcoord_generation_config->mode = SoftGPU::TexCoordGenerationMode::EyeLinear; case GL_TEXTURE_GEN_T:
texcoord_generation_config->coefficients = context_coordinate_config.eye_plane_coefficients; enabled_coordinates |= SoftGPU::TexCoordGenerationCoordinate::T;
break; texcoord_generation_config = &options.texcoord_generation_config[i][1];
case GL_SPHERE_MAP: break;
texcoord_generation_config->mode = SoftGPU::TexCoordGenerationMode::SphereMap; case GL_TEXTURE_GEN_R:
break; enabled_coordinates |= SoftGPU::TexCoordGenerationCoordinate::R;
case GL_REFLECTION_MAP: texcoord_generation_config = &options.texcoord_generation_config[i][2];
texcoord_generation_config->mode = SoftGPU::TexCoordGenerationMode::ReflectionMap; break;
break; case GL_TEXTURE_GEN_Q:
case GL_NORMAL_MAP: enabled_coordinates |= SoftGPU::TexCoordGenerationCoordinate::Q;
texcoord_generation_config->mode = SoftGPU::TexCoordGenerationMode::NormalMap; texcoord_generation_config = &options.texcoord_generation_config[i][3];
break; 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); m_rasterizer.set_options(options);
} }

View file

@ -270,36 +270,15 @@ private:
struct TextureCoordinateGeneration { struct TextureCoordinateGeneration {
bool enabled { false }; bool enabled { false };
GLenum generation_mode { GL_EYE_LINEAR }; GLenum generation_mode { GL_EYE_LINEAR };
FloatVector4 object_plane_coefficients; FloatVector4 object_plane_coefficients { 0.0f, 0.0f, 0.0f, 0.0f };
FloatVector4 eye_plane_coefficients; FloatVector4 eye_plane_coefficients { 0.0f, 0.0f, 0.0f, 0.0f };
};
Array<TextureCoordinateGeneration, 4> 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 },
},
}; };
Vector<Array<TextureCoordinateGeneration, 4>> m_texture_coordinate_generation;
bool m_texcoord_generation_dirty { true }; 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; SoftGPU::Device m_rasterizer;

View file

@ -612,16 +612,16 @@ DeviceInfo Device::info() const
static void generate_texture_coordinates(Vertex& vertex, RasterizerOptions const& options) static void generate_texture_coordinates(Vertex& vertex, RasterizerOptions const& options)
{ {
auto generate_coordinate = [&](size_t config_index) -> float { auto generate_coordinate = [&](size_t texcoord_index, size_t config_index) -> float {
auto mode = options.texcoord_generation_config[config_index].mode; auto mode = options.texcoord_generation_config[texcoord_index][config_index].mode;
switch (mode) { switch (mode) {
case TexCoordGenerationMode::ObjectLinear: { 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); return coefficients.dot(vertex.position);
} }
case TexCoordGenerationMode::EyeLinear: { 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); return coefficients.dot(vertex.eye_coordinates);
} }
case TexCoordGenerationMode::SphereMap: { 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; for (size_t i = 0; i < vertex.tex_coords.size(); ++i) {
vertex.tex_coords[0] = { auto& tex_coord = vertex.tex_coords[i];
((enabled_coords & TexCoordGenerationCoordinate::S) > 0) ? generate_coordinate(0) : vertex.tex_coords[0].x(), auto const enabled_coords = options.texcoord_generation_enabled_coordinates[i];
((enabled_coords & TexCoordGenerationCoordinate::T) > 0) ? generate_coordinate(1) : vertex.tex_coords[0].y(), tex_coord = {
((enabled_coords & TexCoordGenerationCoordinate::R) > 0) ? generate_coordinate(2) : vertex.tex_coords[0].z(), ((enabled_coords & TexCoordGenerationCoordinate::S) > 0) ? generate_coordinate(i, 0) : tex_coord.x(),
((enabled_coords & TexCoordGenerationCoordinate::Q) > 0) ? generate_coordinate(3) : vertex.tex_coords[0].w(), ((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, 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) { for (auto& triangle : m_processed_triangles) {
// Let's calculate the (signed) area of the triangle // Let's calculate the (signed) area of the triangle
// https://cp-algorithms.com/geometry/oriented-triangle-area.html // 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(); triangle.vertices[2].normal.normalize();
} }
// Generate texture coordinates if at least one coordinate is enabled if (texture_coordinate_generation_enabled) {
if (m_options.texcoord_generation_enabled_coordinates != TexCoordGenerationCoordinate::None) {
generate_texture_coordinates(triangle.vertices[0], m_options); generate_texture_coordinates(triangle.vertices[0], m_options);
generate_texture_coordinates(triangle.vertices[1], m_options); generate_texture_coordinates(triangle.vertices[1], m_options);
generate_texture_coordinates(triangle.vertices[2], m_options); generate_texture_coordinates(triangle.vertices[2], m_options);

View file

@ -70,8 +70,8 @@ struct RasterizerOptions {
WindingOrder front_face { WindingOrder::CounterClockwise }; WindingOrder front_face { WindingOrder::CounterClockwise };
bool cull_back { true }; bool cull_back { true };
bool cull_front { false }; bool cull_front { false };
u8 texcoord_generation_enabled_coordinates { TexCoordGenerationCoordinate::None }; Array<u8, NUM_SAMPLERS> texcoord_generation_enabled_coordinates {};
Array<TexCoordGenerationConfig, 4> texcoord_generation_config {}; Array<Array<TexCoordGenerationConfig, 4>, NUM_SAMPLERS> texcoord_generation_config {};
Gfx::IntRect viewport; Gfx::IntRect viewport;
bool lighting_enabled { false }; bool lighting_enabled { false };
bool color_material_enabled { false }; bool color_material_enabled { false };