Commit graph

128 commits

Author SHA1 Message Date
Jelle Raaijmakers
d75135663b LibGfx+LibSoftGPU: Add and use Vector.xy()
Also use `.xyz()` where appropriate.
2022-03-07 11:00:45 +01:00
Jelle Raaijmakers
439617cf6f LibSoftGPU: Use lroundf instead of roundf in rasterization rect
Casting a `float` to `int` might still inadvertently floor the value,
while `lroundf` will return a properly rounded `long`.
2022-03-07 11:00:45 +01:00
Jelle Raaijmakers
37dd10fbbe LibSoftGPU: Use float instead of int for triangle screen coords
This replaces the fixed point subpixel precision logic.

GLQuake now effectively renders artifact-free. Previously white/gray
pixels would sometimes be visible at triangle edges, caused by slightly
misaligned triangle edges as a result of converting the vertex window
coordinates to `int`. These artifacts were reduced by the introduction
of subpixel precision, but not completely eliminated.

Some interesting changes in this commit:

* Applying the top-left rule for our counter-clockwise vertices is now
  done with simpler conditions: every vertex that has a Y coordinate
  lower than or equal to the previous vertex' Y coordinate is counted
  as a top or left edge. A float epsilon is used to emulate a switch
  between `> 0` and `>= 0` comparisons.

* Fog depth calculation into a `f32x4` is now done once per triangle
  instead of once per fragment, and only if fog is enabled.

* The `one_over_area` value was previously calculated as `1.0f / area`,
  where `area` was an `int`. This resulted in a lower quality
  reciprocal value whereas we can now retain floating point precision.
  The effect of this can be seen in Tux Racer, where the ice reflection
  is noticeably smoother.
2022-03-07 11:00:45 +01:00
Jelle Raaijmakers
9fc419395e LibSoftGPU: Use destination alpha for texture decal function
According to the OpenGL spec, the decal function uses the destination
(or texture) alpha instead of the source alpha. This fixes the sky in
GLQuake.
2022-03-06 01:38:01 +01:00
Jelle Raaijmakers
e1c863d99a LibSoftGPU: Use non-normalized light vector for attenuation
There were some issues with the old code: we were saving the length of
the light vector but not actually using it anywhere, if we were dealing
with a zero-vector this could potentially divide by zero resulting in a
black fragment color, and we were erroneously using P2's length instead
of P1's length when P1's W coordinate is zero in the SGI arrow
operation.

This fixes some lighting bugs in Grim Fandango, but this probably
affects all lighting as well.
2022-03-05 21:23:56 +01:00
Jelle Raaijmakers
c3273e9492 LibSoftGPU: Clean up some conditionals in Device
No functional changes.
2022-02-22 23:48:59 +00:00
Jelle Raaijmakers
f28047de73 LibSoftGPU: Round rasterization position to nearest integer
This fixes the issue where e.g. `299.97` would be cast to an integer
value of `299`, whereas the pixel's center would lie at `299.5` and
would then erroneously be excluded.
2022-02-22 23:48:59 +00:00
Jelle Raaijmakers
8c9fa50c61 LibSoftGPU: Apply regular cartesian coordinate system
Currently, LibSoftGPU is still OpenGL-minded in that it uses a
coordinate system with the origin of `(0, 0)` at the lower-left of
textures, buffers and window coordinates. Because we are blitting to a
`Gfx::Bitmap` that has the origin at the top-left, we need to flip the
Y-coordinates somewhere in the rasterization logic.

We used to do this during conversion of NDC-coordinates to window
coordinates. This resulted in some incorrect behavior when
rasterization did not pass through the vertex transformation logic,
e.g. when calling `glDrawPixels`.

This changes the coordinate system to OpenGL's throughout, only to blit
the final color buffer upside down to the target bitmap. This fixes
drawing to the depth buffer directly resulting in upside down images.
2022-02-22 23:48:59 +00:00
Jelle Raaijmakers
971b39ae4f LibSoftGPU: Rename rgba to bgra to reflect actual value 2022-02-22 23:48:59 +00:00
Jelle Raaijmakers
db0616c67a LibSoftGPU: Generalize pixel buffers and standardize on BGRA8888
Between the OpenGL client and server, a lot of data type and color
conversion needs to happen. We are performing these conversions both in
`LibSoftGPU` and `LibGL`, which is not ideal. Additionally, some
concepts like the color, depth and stencil buffers should share their
logic but have separate implementations.

This is the first step towards generalizing our `LibSoftGPU` frame
buffer: a generalized `Typed3DBuffer` is introduced for arbitrary 3D
value storage and retrieval, and `Typed2DBuffer` wraps around it to
provide in an easy-to-use 2D pixel buffer. The color, depth and stencil
buffers are replaced by `Typed2DBuffer` and are now managed by the new
`FrameBuffer` class.

The `Image` class now uses multiple `Typed3DBuffer`s for layers and
mipmap levels. Additionally, the textures are now always stored as
BGRA8888, only converting between formats when reading or writing
pixels.

Ideally this refactor should have no functional changes, but some
graphical glitches in Grim Fandango seem to be fixed and most OpenGL
ports get an FPS boost on my machine. :^)
2022-02-22 23:48:59 +00:00
Jelle Raaijmakers
6318522339 LibSoftGPU: Remove Device::wait_for_all_threads()
This function was added as a FIXME but was then arbitrarily invoked in
the rest of `Device`. We are better off removing this FIXME for now and
reevaluate introducing multithreading later on, so the code is not
littered with useless empty function calls.
2022-02-22 23:48:59 +00:00
Jelle Raaijmakers
4d53a87355 LibSoftGPU: Remove unused AK/Function.h include 2022-02-22 23:48:59 +00:00
Jelle Raaijmakers
a5ad702387 LibSoftGPU: Use fabsf instead of fabs for float
Let's not do a `float -> double -> float` roundtrip. :^)
2022-02-22 23:48:59 +00:00
Lenny Maiorani
d1a87f1219 LibSoftGPU: Use default construction to clear AlphaBlendFactors
Clearing the `m_alpha_blend_factors` is performed manually and in
separate steps. This is error prone for future developers. The
behavior is to reset the entire `struct` to the same state as default
initialization, so this simplifies it to do just that.
2022-01-27 20:39:02 +00:00
Lenny Maiorani
065525aba0 LibSoftGPU: Configure stats overlay period
Problem:
- The statistics overlay period is hardcoded to 500 ms. This time is
  very short and can result in the values being very "jumpy".

Solution:
- Increasing this value can result in more steady values which is
  useful when trying to evaluate the performance impact of a change. A
  new config value is offered in `Config.h` to let the developer
  change to any value desired.
2022-01-22 08:57:31 +03:30
Jelle Raaijmakers
a8655fbf52 LibGL+LibSoftGPU: Clean up some for loops 2022-01-20 10:35:01 +01:00
Jelle Raaijmakers
453f62c935 LibGL+LibSoftGPU: Implement GL_POLYGON_OFFSET_FILL capability 2022-01-20 10:35:01 +01:00
Stephan Unverwerth
12f63df329 LibGL+LibSoftGPU: Support generation of multiple texture coordinates 2022-01-19 19:57:49 +01:00
Stephan Unverwerth
7571ef0343 LibGL+LibSoftGPU: Add multiple texture coordinates to vertex struct
We now have one set of texture coordinates per texture unit.
Texture coordinate generation and texture coordinate assignment is
currently only stubbed. This will be rectified in another commit.
2022-01-19 19:57:49 +01:00
Stephan Unverwerth
5505f353e8 LibSoftGPU: Announce NPOT texture support via DeviceInfo struct 2022-01-19 19:57:49 +01:00
Jesse Buhagiar
865e7bbe5e LibGL+LibSoftGPU+3DFileViewer: Implement Specular highlighting :^) 2022-01-18 01:48:51 +02:00
Jesse Buhagiar
5a735602b0 LibSoftGPU: Add sgi_dot lambda
This function is used quite a bit during the lighting calculations, so
it's a bit cleaner having it in a centralized spot instead of just
arbitrarily calling `dot()` with numerous `FloatVector3` conversions.
2022-01-18 01:48:51 +02:00
Jesse Buhagiar
fc8dd0bf68 LibSoftGPU: Use correct position for vertex_to_light
The spec has a few stipulations on what this value should actually be,
and hence we should follow it accordingly.
2022-01-18 01:48:51 +02:00
Jelle Raaijmakers
8f33e55726 LibSoftGPU: Add stencil statistic to debug overlay 2022-01-17 12:49:00 +01:00
Jelle Raaijmakers
11c807ebd1 LibGL+LibSoftGPU: Implement the stencil buffer
This implements an 8-bit front stencil buffer. Stencil operations are
SIMD optimized. LibGL changes include:

* New `glStencilMask` and `glStencilMaskSeparate` functions
* New context parameter `GL_STENCIL_CLEAR_VALUE`
2022-01-17 12:49:00 +01:00
Jelle Raaijmakers
3609ffc450 LibGL+LibSoftGPU: Enumize material front/back face selection 2022-01-17 12:49:00 +01:00
Jelle Raaijmakers
8efd6bc878 LibGL+LibSoftGPU: Implement glDrawPixels depth buffer support
This enabled writing directly to the depth buffer, and allows games
like Grim Fandango to render their pre-baked depth buffers correctly!
2022-01-14 21:38:09 +01:00
Jelle Raaijmakers
ca78327a96 LibGL+LibSoftGPU: Implement rasterization position
Implements support for `glRasterPos` and updating the raster position's
window coordinates through `glBitmap`. The input for `glRasterPos` is
an object position that needs to go through the same vertex
transformations as our regular triangles.
2022-01-14 21:38:09 +01:00
Jelle Raaijmakers
8e935ad3b1 LibGL+LibSoftGPU: Implement glColorMaterial and GL_COLOR_MATERIAL
When `GL_COLOR_MATERIAL` is enabled, specific material parameters can
be overwritten by the current color per-vertex during the lighting
calculations. Which parameter is controlled by `glColorMaterial`.

Also move the lighting calculations _before_ clipping, because the spec
says so. As a result, we interpolate the resulting vertex color instead
of the input color.
2022-01-13 12:13:58 +01:00
Jelle Raaijmakers
9d4c2f6308 LibGL+LibSoftGPU: Calculate spotlight cutoff angle as degrees
We were storing the radians but never using that value in the GPU. We
now directly use the degrees value.
2022-01-13 12:13:58 +01:00
Luke Wilde
f216df7d0f LibSoftGPU: Don't render triangle strip if there's less than 3 vertices
If there's less than 3 vertices, we cannot do triangle strip otherwise
we will go out-of-bounds of the vertices vector.

Required for Half-Life, which sometimes submits 0 vertices for triangle
strip when drawing the electric disks around the pillars in Xen.
2022-01-12 13:47:26 +01:00
Jesse Buhagiar
9aae648482 LibSoftGPU: Implement per-vertex Lighting during T&L Stage
We now perform per vertex lighting during the Transform and Lighting
stage of the pipeline before the triangles are sent off to be
rasterized.
2022-01-12 13:36:56 +01:00
Jesse Buhagiar
5a1f559ed9 LibSoftGPU: Transform normals during T&L stage
As well as Vertex Positions, the normals also need to be transformed
into eye-space so that lighting can be applied correctly.
2022-01-12 13:36:56 +01:00
Jesse Buhagiar
775ef000e0 LibGL+LibSoftGPU: Move lighting model parameters to SoftGPU
Most of the T&L stuff is, like on an actual GPU, now done inside of
LibSoftGPU. As such, it no longer makes sense to have specific values
like the scene ambient color inside of LibGL as part of the GL context.
These have now been moved into LibSoftGPU and use the same pattern as
the render options to set/get.
2022-01-12 13:36:56 +01:00
Jesse Buhagiar
92373ab0b6 LibGL: Flesh out glMaterialf{v}
These two functions have been turned from stubs into actually doing
something. They now set the correspondingmaterial data member based on
the value passed into the `pname`argument.

Co-authored-by: Stephan Unverwerth <s.unverwerth@serenityos.org>
2022-01-12 13:36:56 +01:00
Jesse Buhagiar
bf294612a7 LibGL: Implement glLightf{v} and fix gl.h prototype
This implements the `glLightf{v}` family of functions used to set
lighting parameters per light in the GL. It also fixes an incorrect
prototype for the user exposed version of `glLightf{v}` in which
`params` was not marked as `const`.
2022-01-12 13:36:56 +01:00
Jesse Buhagiar
192befa84b LibGL+LibSoftGPU: Add GL_MAX_LIGHTS to get_context_parameter
This is required to allow lighting to work properly in the GL. We
currently have the maximum number of lights in the software GL context
set to 8, as this is the minimum that OpenGL mandates according to the
spec.
2022-01-12 13:36:56 +01:00
Jelle Raaijmakers
17ec433326 LibSoftGPU: Only render complete primitives
Previously, we were expecting triangles and quads to consist of
complete sets of vertices. However, a more common behavior is to ignore
all vertices that do not make up a full primitive. For example, OpenGL
specifies for `GL_QUADS`:

  "The total number of vertices between Begin and End is 4n + k, where
   0 ≤ k ≤ 3; if k is not zero, the final k vertices are ignored."

This changes the behavior of `Device::draw_primitives()` to both return
early if no full set of vertices was provided, and to ignore any
additional vertices that are not part of a full set.
2022-01-11 23:47:42 +01:00
Jelle Raaijmakers
29bbf56286 LibGL+LibSoftGPU: Implement viewport support
This implements the `glViewport` API call, the coordinate
transformation and the `GL_VIEWPORT` context parameter.
2022-01-09 20:22:32 +01:00
Jelle Raaijmakers
d236b0ed12 LibSoftGPU: Rename window coordinate transformation function
The name `scissor_box_to_window_coordinates` was wildy inaccurate since
we are actually transforming window coordinates into whatever the
coordinate space of the backing bitmap is.
2022-01-09 20:22:32 +01:00
Stephan Unverwerth
d45931b423 LibSoftGPU: Take sample from pixel center
This adds a half pixel offset to the edge value calculation in order to
sample the triangle at pixel centers. This is in line with actual OpenGL
rasterization rules and generates correctly interpolated vertex
attributes including texture coordinates.
2022-01-09 16:21:13 +03:30
Stephan Unverwerth
5028b53b49 LibSoftGPU: Make divide-by-zero guard more explicit in stats overlay
This previously assigned 1 to any divisor that was 0 which was a bit
confusing
2022-01-09 16:21:13 +03:30
Stephan Unverwerth
57215d0e1f LibSoftGPU: Allow arbitrary render target sizes
With the RASTERIZER_BLOCK_SIZE gone we can now render to any size, even
odd ones. We have to be careful to not generate out of bounds accesses
when calculating the render target and depth buffer pointers. Thus we
check the coverage mask and generate nullptrs for pixels that will not
be updated. This also masks out pixels that would touch the triangle but
are outside the render target/scissor rect bounds.
2022-01-09 16:21:13 +03:30
Stephan Unverwerth
941e9d9922 LibSoftGPU: Move alpha test into separate function 2022-01-09 16:21:13 +03:30
Stephan Unverwerth
68a1727547 LibSoftGPU: Move alpha blend factor setup out of triangle rasterization
Since the alpha blend configuration should not change between most calls
of draw_primitives it makes no sense to reinitialize the blend factors
for every rasterized triangle.
The alpha blend factors are now set up whenever the device config
changes. The blend factors are stored in struct AlphaBlendFactors.
2022-01-09 16:21:13 +03:30
Stephan Unverwerth
b4a18eaaf0 LibSoftGPU: Make rasterization and shading member functions of Device
This adds member functions Device::rasterize_triangle() and
Device::shade_fragments(). They were free standing functions/lambdas
previously which led to a lot of parameters being passed around.
2022-01-09 16:21:13 +03:30
Stephan Unverwerth
d89c515609 LibSoftGPU: Vectorize color conversion from/to framebuffer
Functions to_rgba32 and to_vec4 now process 4 color values at the same
time.

Co-authored-by: Jesse Buhagiar <jooster669@gmail.com>
2022-01-09 16:21:13 +03:30
Stephan Unverwerth
66cf2ea240 LibSoftGPU: Only interpolate fog values if fog is enabled 2022-01-09 16:21:13 +03:30
Stephan Unverwerth
f510a3cd8f LibSoftGPU: Add SIMD utilization counter to debug overlay
This adds a counter to the debug overlay that displays the average
percentage of SIMD lane utilization.

This number represents the number of pixels that were output for each
quad. A utilization of 100% means that all 4 SIMD lanes were used and
no pixels were masked out before being written to the color buffer.
2022-01-09 16:21:13 +03:30
Stephan Unverwerth
b8e06ca757 LibSoftGPU: Vectorize the rest of the rasterizer pipeline 2022-01-09 16:21:13 +03:30