mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 16:37:35 +00:00
LibGL: Implement fog effect in Software Rasterizer
We support three of the possible fog modes, EXP, EXP2 and LINEAR.
This commit is contained in:
parent
d73cc3d0eb
commit
924d890bfe
3 changed files with 41 additions and 9 deletions
|
@ -545,6 +545,10 @@ void SoftwareGLContext::gl_enable(GLenum capability)
|
||||||
rasterizer_options.enable_alpha_test = true;
|
rasterizer_options.enable_alpha_test = true;
|
||||||
update_rasterizer_options = true;
|
update_rasterizer_options = true;
|
||||||
break;
|
break;
|
||||||
|
case GL_FOG:
|
||||||
|
rasterizer_options.fog_enabled = true;
|
||||||
|
update_rasterizer_options = true;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
RETURN_WITH_ERROR_IF(true, GL_INVALID_ENUM);
|
RETURN_WITH_ERROR_IF(true, GL_INVALID_ENUM);
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,6 +28,12 @@ constexpr static T interpolate(const T& v0, const T& v1, const T& v2, const Floa
|
||||||
return v0 * barycentric_coords.x() + v1 * barycentric_coords.y() + v2 * barycentric_coords.z();
|
return v0 * barycentric_coords.x() + v1 * barycentric_coords.y() + v2 * barycentric_coords.z();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
constexpr static T mix(const T& x, const T& y, float interp)
|
||||||
|
{
|
||||||
|
return x * (1 - interp) + y * interp;
|
||||||
|
}
|
||||||
|
|
||||||
static Gfx::RGBA32 to_rgba32(const FloatVector4& v)
|
static Gfx::RGBA32 to_rgba32(const FloatVector4& v)
|
||||||
{
|
{
|
||||||
auto clamped = v.clamped(0, 1);
|
auto clamped = v.clamped(0, 1);
|
||||||
|
@ -368,7 +374,11 @@ static void rasterize_triangle(const RasterizerOptions& options, Gfx::Bitmap& re
|
||||||
triangle.vertices[2].tex_coord,
|
triangle.vertices[2].tex_coord,
|
||||||
barycentric);
|
barycentric);
|
||||||
|
|
||||||
*pixel = pixel_shader(uv, vertex_color);
|
// Calculate depth of fragment for fog
|
||||||
|
float z = interpolate(triangle.vertices[0].position.z(), triangle.vertices[1].position.z(), triangle.vertices[2].position.z(), barycentric);
|
||||||
|
z = options.depth_min + (options.depth_max - options.depth_min) * (z + 1) / 2;
|
||||||
|
|
||||||
|
*pixel = pixel_shader(uv, vertex_color, z);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -470,16 +480,9 @@ SoftwareRasterizer::SoftwareRasterizer(const Gfx::IntSize& min_size)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void SoftwareRasterizer::submit_triangle(const GLTriangle& triangle)
|
|
||||||
{
|
|
||||||
rasterize_triangle(m_options, *m_render_target, *m_depth_buffer, triangle, [](const FloatVector2&, const FloatVector4& color) -> FloatVector4 {
|
|
||||||
return color;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
void SoftwareRasterizer::submit_triangle(const GLTriangle& triangle, const Array<TextureUnit, 32>& texture_units)
|
void SoftwareRasterizer::submit_triangle(const GLTriangle& triangle, const Array<TextureUnit, 32>& texture_units)
|
||||||
{
|
{
|
||||||
rasterize_triangle(m_options, *m_render_target, *m_depth_buffer, triangle, [&texture_units](const FloatVector2& uv, const FloatVector4& color) -> FloatVector4 {
|
rasterize_triangle(m_options, *m_render_target, *m_depth_buffer, triangle, [this, &texture_units](const FloatVector2& uv, const FloatVector4& color, float z) -> FloatVector4 {
|
||||||
// TODO: We'd do some kind of multitexturing/blending here
|
// TODO: We'd do some kind of multitexturing/blending here
|
||||||
// Construct a vector for the texel we want to sample
|
// Construct a vector for the texel we want to sample
|
||||||
FloatVector4 texel = color;
|
FloatVector4 texel = color;
|
||||||
|
@ -494,6 +497,28 @@ void SoftwareRasterizer::submit_triangle(const GLTriangle& triangle, const Array
|
||||||
texel = texel * static_ptr_cast<Texture2D>(texture_unit.bound_texture())->sampler().sample(uv);
|
texel = texel * static_ptr_cast<Texture2D>(texture_unit.bound_texture())->sampler().sample(uv);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Calculate fog
|
||||||
|
// Math from here: https://opengl-notes.readthedocs.io/en/latest/topics/texturing/aliasing.html
|
||||||
|
if (m_options.fog_enabled) {
|
||||||
|
float factor = 0.0f;
|
||||||
|
switch (m_options.fog_mode) {
|
||||||
|
case GL_LINEAR:
|
||||||
|
factor = (m_options.fog_end - z) / (m_options.fog_end - m_options.fog_start);
|
||||||
|
break;
|
||||||
|
case GL_EXP:
|
||||||
|
factor = exp(-((m_options.fog_density * z)));
|
||||||
|
break;
|
||||||
|
case GL_EXP2:
|
||||||
|
factor = exp(-((m_options.fog_density * z) * (m_options.fog_density * z)));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mix texel with fog
|
||||||
|
texel = mix(m_options.fog_color, texel, factor);
|
||||||
|
}
|
||||||
|
|
||||||
return texel;
|
return texel;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,6 +41,9 @@ struct RasterizerOptions {
|
||||||
};
|
};
|
||||||
GLfloat fog_density { 1.0f };
|
GLfloat fog_density { 1.0f };
|
||||||
GLenum fog_mode { GL_EXP };
|
GLenum fog_mode { GL_EXP };
|
||||||
|
GLboolean fog_enabled { false };
|
||||||
|
GLfloat fog_start { 0.0f };
|
||||||
|
GLfloat fog_end { 1.0f };
|
||||||
};
|
};
|
||||||
|
|
||||||
class SoftwareRasterizer final {
|
class SoftwareRasterizer final {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue