diff options
author | Jesse Buhagiar <jooster669@gmail.com> | 2021-08-25 18:10:44 +1000 |
---|---|---|
committer | Ali Mohammad Pur <Ali.mpfard@gmail.com> | 2021-08-25 23:50:54 +0430 |
commit | 924d890bfed5095c1b27fa71a338b63661400b09 (patch) | |
tree | 7b5258a3f029045ef5956e1a32dc5105ecacb37e /Userland | |
parent | d73cc3d0ebf2421c80b524dc27d01fd7f1802d69 (diff) | |
download | serenity-924d890bfed5095c1b27fa71a338b63661400b09.zip |
LibGL: Implement fog effect in Software Rasterizer
We support three of the possible fog modes, EXP, EXP2 and LINEAR.
Diffstat (limited to 'Userland')
-rw-r--r-- | Userland/Libraries/LibGL/SoftwareGLContext.cpp | 4 | ||||
-rw-r--r-- | Userland/Libraries/LibGL/SoftwareRasterizer.cpp | 43 | ||||
-rw-r--r-- | Userland/Libraries/LibGL/SoftwareRasterizer.h | 3 |
3 files changed, 41 insertions, 9 deletions
diff --git a/Userland/Libraries/LibGL/SoftwareGLContext.cpp b/Userland/Libraries/LibGL/SoftwareGLContext.cpp index c7cd5b5922..009b8e7512 100644 --- a/Userland/Libraries/LibGL/SoftwareGLContext.cpp +++ b/Userland/Libraries/LibGL/SoftwareGLContext.cpp @@ -545,6 +545,10 @@ void SoftwareGLContext::gl_enable(GLenum capability) rasterizer_options.enable_alpha_test = true; update_rasterizer_options = true; break; + case GL_FOG: + rasterizer_options.fog_enabled = true; + update_rasterizer_options = true; + break; default: RETURN_WITH_ERROR_IF(true, GL_INVALID_ENUM); } diff --git a/Userland/Libraries/LibGL/SoftwareRasterizer.cpp b/Userland/Libraries/LibGL/SoftwareRasterizer.cpp index 5a326fa567..cfd5513476 100644 --- a/Userland/Libraries/LibGL/SoftwareRasterizer.cpp +++ b/Userland/Libraries/LibGL/SoftwareRasterizer.cpp @@ -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(); } +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) { 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, 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) { - 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 // Construct a vector for the texel we want to sample 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); } + // 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; }); } diff --git a/Userland/Libraries/LibGL/SoftwareRasterizer.h b/Userland/Libraries/LibGL/SoftwareRasterizer.h index cfdd4b20c9..8a1a8d8166 100644 --- a/Userland/Libraries/LibGL/SoftwareRasterizer.h +++ b/Userland/Libraries/LibGL/SoftwareRasterizer.h @@ -41,6 +41,9 @@ struct RasterizerOptions { }; GLfloat fog_density { 1.0f }; GLenum fog_mode { GL_EXP }; + GLboolean fog_enabled { false }; + GLfloat fog_start { 0.0f }; + GLfloat fog_end { 1.0f }; }; class SoftwareRasterizer final { |