Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Shader resources #101

Open
wants to merge 42 commits into
base: master
Choose a base branch
from
Open

Shader resources #101

wants to merge 42 commits into from

Conversation

mardy
Copy link
Collaborator

@mardy mardy commented Feb 3, 2025

To be merged after #100

Enable operation of clipping and stencil tests when using shaders, too. In order to do this, expose the OgxGpuResources structure to the client, to let them allocate stages dynamically. The clip and stencil stages need to be run after the other stages, and for this reason it's important for opengx to know how many stages are being used by the shader program.

The last commit fixes an unrelated old regression, discovered when testing these changes.

mardy added 30 commits January 16, 2025 17:51
The logic for putting return or break in the getter code is the
following: if the current getter can lookup the value, it should return
immediately after storing it into the output variable; otherwise, we
should "break" from the switch, and then there should be a fallback code
to delegate the operation to a different getter.

This fixes gluBuild2DMipmaps(), which calls

    glGetIntegerv(GL_UNPACK_LSB_FIRST, &psm->unpack_lsb_first);

and was broken by commit 94b3aab.
As a matter of fact, we already had a couple of structs for holding
drawing parameters, but with this commit we unify them into a single one
and use it more consistently.

The DrawMode struct was also renamed with the "Ogx" prefix.
And anyway that check looks wrong, in that it affected only the vertex
array, and not the other attributes as well.
The pointer is already implemented in the `for` loop. This bug went
unnoticed because in most cases the SameTypeVertexReader is used
instead.
Do not prepare the vertex attribute readers in advance. Instead, just
store the client data in the state and build the readers just at the
time when they are needed (like in glDrawArrays() and glDrawElements).
Keep a "dirty" flag to avoid rebuilding them if the input data has not
changed.

This refactoring is a small step toward supporting arbitrary vertex
attributes (needed for OpenGL 2.0+) and also allows implementing the
getter methods more easily (see next commit).

We also fix glInterleavedArrays(), which got broken at some point.
Add a symbol to host the list of OpenGL 2.0 functions; in functions.c we
weakly define it as an empty array, but this symbol will be shadowed by
the strong symbol we'll define in the new shader implementation, if
OpenGL 2.0 is used.
This will depend on whether the client actually uses any OpenGL 2.0
functionality.
Rework the existing internal function so that it can be used with
matrices passed by the client. This function will be declared in a
public header used by clients who need to write their own shaders
(OpenGL >= 2.0).
Part of this API will be made public in some later commit to allow
it to be used by developers writing shader replacements. For this goal,
a more flexible API is introduced, where vertex attribute arrays can be
added from a OgxVertexAttribArray structure provided by the client.
As the comment was saying, these objects are just for optimization
purposes and do not really belong to the global state variable. Add a
function to array.h so that other parts of the code can retrieve them if
needed, and move the actual variables as static variables in array.c.
Instead of keeping named variables, store all readers into one array.
This helps in simplifying a bit the code.
These are in the public domain.
This is not yet complete and is likely to be buggy in many aspects, but
it allows running a non totally trivial example (the famous glgears),
which will be added in a later commit.

Among the known limitations:
- The API exposed to the client developer for implementing the shaders
  is not finalized.
- Texturing is not yet implemented.
In this way the examples (and any other binary we should add to the
project) will automatically gain an include path to the src/directoy
when building against opengx. This will allow them to find the
"opengx.h" file.
So we can rotate the gears on the console, too.
The association of a VBO to an array is to be saved in the client state:
we should look up the VBO only when we draw some geometry. The error was
discovered running the cube_tex example (it will be added to the repo in
a later commit), which uses two different VBOs for the position and
texture coordinate attributes.
This example uses SDL2 and glm. At the moment this example does not work
on the Wii/GameCube, as the textured rendering using OpenGL 2.0 will
come in a later commit.

The "common" directory contains textures that get embedded into the
executable, so that examples can be written without access to external
files (which makes testing on the console -- or on the emulator --
very straightforward).
Colors are often specifies as a 3 or 4 long vector of floats, but GX
does not support specifying colors using floating point components.
Therefore, convert such values to GXColor.
The data here is just an integer number representing the texture unit
bound to the uniform.
This is all what is needed to let the client developer write a GX shader
capable of supporting textured geometries.
This is a bit primitive, because we are hardcoding the texture stage and
other TEV variables (we'll improve this later), but it does the job.
To make clear that these functions are to be called only when
implementing shaders in the client code, rename them to have a
"ogx_shader" prefix. Also use the "_gx" or "_gl" suffix to indicate
whether they expect the matrix to be in the GX or OpenGL format.
Shader programs will be able to know which resources are available and
will not conflict with other core opengx functionality (like clipping
and stencil).
mardy added 12 commits February 3, 2025 22:00
These enums are supported both by glGetBoolean() and glIsEnabled().
It is not very clear how this should work, but we replicate the
behaviour of desktop OpenGL.
Clipping and stenciling is not working properly currently (due to the
model-view matrix not being up-to-date when drawing with shaders), but
the stages do get applied.
Add a couple of pointers in the opengx state, to the currently active
model-view and projection matrices: these are not always those set via
the immediate-mode API, because with OpenGL 2.0+ these matrices can be
implicitly set by the shader programs.
This now works when using shaders, too.
The client can update the matrices in the setup_draw() callback as well,
but having a specialized callback makes it possible for opengx to
request the client to update the matrices without setting up the whole
TEV state.
This is required for supporting stencil drawing when using shaders:
since the drawing happens in two stages (first we draw to the stencil
buffer, and then to the scene) and only the latter stage uses the TEV as
setup by the client, it would be a waste to call setup_draw() twice, if
all what we need from the first invocation is just the updated
transformation matrices.
This is as simple as ensuring that the matrices being considered for the
stencil texture projection are those used by the shader pipeline
(glUseProgram() takes care of updating the matrix pointers).
This allows to reduce branching, since the function pointer only changes
when glUseProgram() is called. We should consider using the same
mechanism for the setup_draw() function.

We also clean up the dirty bit usage for the normal matrix, partially
reverting commit 836fd7e, because the
current condition for rebuilding the normal matrix is anyway satisfied
when the dirty_matrices flag is set, so we can just set it anytime a
matrix is changed. We still keep setting the dirty_tev flag to true when
the normal matrix gets changed, in order not to break the idea behind
commit 836fd7e.
Fixes a regression introduced by commit 836fd7e, because indeed
the _ogx_stencil_draw() function (and draw_op() in particular) alters
the TEV setup, which then needs to be restored when drawing to the
scene.

This fixes an issue in the dinoshade program, where some parts of the
reflected dinosaur could be seen outside of the floor.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant