mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-09-20 09:49:15 +03:00
LibSoftGPU: Implement 5 bits of subpixel precision
This snaps vertices to 1/32 of a pixel before rasterization resulting in smoother movement and less floaty appearance of moving triangles. This also reduces the severity of the artifacts in the glquake port. 5 bits should allow up to 1024x1024 render targets. Anything larger needs a different implementation.
This commit is contained in:
parent
c00014fa54
commit
8ae3eb6c33
Notes:
sideshowbarker
2024-07-17 21:32:53 +09:00
Author: https://github.com/sunverwerth Commit: https://github.com/SerenityOS/serenity/commit/8ae3eb6c33c Pull-request: https://github.com/SerenityOS/serenity/pull/11510
@ -17,6 +17,7 @@ namespace SoftGPU {
|
|||||||
static constexpr bool ENABLE_STATISTICS_OVERLAY = false;
|
static constexpr bool ENABLE_STATISTICS_OVERLAY = false;
|
||||||
static constexpr int RASTERIZER_BLOCK_SIZE = 8;
|
static constexpr int RASTERIZER_BLOCK_SIZE = 8;
|
||||||
static constexpr int NUM_SAMPLERS = 32;
|
static constexpr int NUM_SAMPLERS = 32;
|
||||||
|
static constexpr int SUBPIXEL_BITS = 5;
|
||||||
|
|
||||||
// See: https://www.khronos.org/opengl/wiki/Common_Mistakes#Texture_edge_color_problem
|
// See: https://www.khronos.org/opengl/wiki/Common_Mistakes#Texture_edge_color_problem
|
||||||
// FIXME: make this dynamically configurable through ConfigServer
|
// FIXME: make this dynamically configurable through ConfigServer
|
||||||
|
@ -130,10 +130,12 @@ static void rasterize_triangle(const RasterizerOptions& options, Gfx::Bitmap& re
|
|||||||
Vertex const vertex1 = triangle.vertices[1];
|
Vertex const vertex1 = triangle.vertices[1];
|
||||||
Vertex const vertex2 = triangle.vertices[2];
|
Vertex const vertex2 = triangle.vertices[2];
|
||||||
|
|
||||||
|
constexpr int subpixel_factor = 1 << SUBPIXEL_BITS;
|
||||||
|
|
||||||
// Calculate area of the triangle for later tests
|
// Calculate area of the triangle for later tests
|
||||||
IntVector2 const v0 { static_cast<int>(vertex0.window_coordinates.x()), static_cast<int>(vertex0.window_coordinates.y()) };
|
IntVector2 const v0 { static_cast<int>(vertex0.window_coordinates.x() * subpixel_factor), static_cast<int>(vertex0.window_coordinates.y() * subpixel_factor) };
|
||||||
IntVector2 const v1 { static_cast<int>(vertex1.window_coordinates.x()), static_cast<int>(vertex1.window_coordinates.y()) };
|
IntVector2 const v1 { static_cast<int>(vertex1.window_coordinates.x() * subpixel_factor), static_cast<int>(vertex1.window_coordinates.y() * subpixel_factor) };
|
||||||
IntVector2 const v2 { static_cast<int>(vertex2.window_coordinates.x()), static_cast<int>(vertex2.window_coordinates.y()) };
|
IntVector2 const v2 { static_cast<int>(vertex2.window_coordinates.x() * subpixel_factor), static_cast<int>(vertex2.window_coordinates.y() * subpixel_factor) };
|
||||||
|
|
||||||
int area = edge_function(v0, v1, v2);
|
int area = edge_function(v0, v1, v2);
|
||||||
if (area == 0)
|
if (area == 0)
|
||||||
@ -204,12 +206,12 @@ static void rasterize_triangle(const RasterizerOptions& options, Gfx::Bitmap& re
|
|||||||
auto render_bounds = render_target.rect();
|
auto render_bounds = render_target.rect();
|
||||||
if (options.scissor_enabled)
|
if (options.scissor_enabled)
|
||||||
render_bounds.intersect(scissor_box_to_window_coordinates(options.scissor_box, render_target.rect()));
|
render_bounds.intersect(scissor_box_to_window_coordinates(options.scissor_box, render_target.rect()));
|
||||||
int const block_padding = RASTERIZER_BLOCK_SIZE - 1;
|
|
||||||
// clang-format off
|
// clang-format off
|
||||||
int const bx0 = max(render_bounds.left(), min(min(v0.x(), v1.x()), v2.x())) / RASTERIZER_BLOCK_SIZE;
|
int const bx0 = max(render_bounds.left(), min(min(v0.x(), v1.x()), v2.x()) / subpixel_factor) / RASTERIZER_BLOCK_SIZE;
|
||||||
int const bx1 = (min(render_bounds.right(), max(max(v0.x(), v1.x()), v2.x())) + block_padding) / RASTERIZER_BLOCK_SIZE;
|
int const bx1 = (min(render_bounds.right(), max(max(v0.x(), v1.x()), v2.x()) / subpixel_factor)) / RASTERIZER_BLOCK_SIZE + 1;
|
||||||
int const by0 = max(render_bounds.top(), min(min(v0.y(), v1.y()), v2.y())) / RASTERIZER_BLOCK_SIZE;
|
int const by0 = max(render_bounds.top(), min(min(v0.y(), v1.y()), v2.y()) / subpixel_factor) / RASTERIZER_BLOCK_SIZE;
|
||||||
int const by1 = (min(render_bounds.bottom(), max(max(v0.y(), v1.y()), v2.y())) + block_padding) / RASTERIZER_BLOCK_SIZE;
|
int const by1 = (min(render_bounds.bottom(), max(max(v0.y(), v1.y()), v2.y()) / subpixel_factor)) / RASTERIZER_BLOCK_SIZE + 1;
|
||||||
// clang-format on
|
// clang-format on
|
||||||
|
|
||||||
u8 pixel_mask[RASTERIZER_BLOCK_SIZE];
|
u8 pixel_mask[RASTERIZER_BLOCK_SIZE];
|
||||||
@ -231,10 +233,10 @@ static void rasterize_triangle(const RasterizerOptions& options, Gfx::Bitmap& re
|
|||||||
|
|
||||||
// Edge values of the 4 block corners
|
// Edge values of the 4 block corners
|
||||||
// clang-format off
|
// clang-format off
|
||||||
auto b0 = calculate_edge_values({ bx * RASTERIZER_BLOCK_SIZE, by * RASTERIZER_BLOCK_SIZE });
|
auto b0 = calculate_edge_values(IntVector2{ bx, by } * RASTERIZER_BLOCK_SIZE * subpixel_factor);
|
||||||
auto b1 = calculate_edge_values({ bx * RASTERIZER_BLOCK_SIZE + RASTERIZER_BLOCK_SIZE, by * RASTERIZER_BLOCK_SIZE });
|
auto b1 = calculate_edge_values(IntVector2{ bx + 1, by } * RASTERIZER_BLOCK_SIZE * subpixel_factor);
|
||||||
auto b2 = calculate_edge_values({ bx * RASTERIZER_BLOCK_SIZE, by * RASTERIZER_BLOCK_SIZE + RASTERIZER_BLOCK_SIZE });
|
auto b2 = calculate_edge_values(IntVector2{ bx, by + 1 } * RASTERIZER_BLOCK_SIZE * subpixel_factor);
|
||||||
auto b3 = calculate_edge_values({ bx * RASTERIZER_BLOCK_SIZE + RASTERIZER_BLOCK_SIZE, by * RASTERIZER_BLOCK_SIZE + RASTERIZER_BLOCK_SIZE });
|
auto b3 = calculate_edge_values(IntVector2{ bx + 1, by + 1 } * RASTERIZER_BLOCK_SIZE * subpixel_factor);
|
||||||
// clang-format on
|
// clang-format on
|
||||||
|
|
||||||
// If the whole block is outside any of the triangle edges we can discard it completely
|
// If the whole block is outside any of the triangle edges we can discard it completely
|
||||||
|
Loading…
Reference in New Issue
Block a user