This introduces a new device independent base class for Images in LibGPU
that also keeps track of the device from which it was created in order
to prevent assigning images across devices.
This introduces a new abstraction layer, LibGPU, that serves as the
usermode interface to GPU devices. To get started we just move the
DeviceConfig there and make sure everything still works :^)
We now support generating top-left submatrices from a `Gfx::Matrix`
and we move the normal transformation calculation into
`SoftGPU::Device`. No functional changes.
We were transforming the vertices' normals twice (bug 1) and
normalizing them after lighting (bug 2). In the lighting code, we were
then diverting from the spec to deal with the normal situation, which
is now no longer needed.
This fixes the lighting of Tux in Tux Racer.
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.
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.
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.
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.
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. :^)
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.
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.
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.
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.
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.
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`
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.
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.