Skip to content

Commit 13c9078

Browse files
mardyWinterMute
authored andcommitted
stencil: support orthographic projections
Orthographic projections can be handled with a 2x4 matrix, to avoid problems with the division by the q coordinate.
1 parent f1bd77b commit 13c9078

File tree

1 file changed

+39
-11
lines changed

1 file changed

+39
-11
lines changed

src/stencil.c

+39-11
Original file line numberDiff line numberDiff line change
@@ -344,23 +344,51 @@ static bool setup_tev_full(int *stages, int *tex_coords,
344344

345345
/* Add a set of texture coordinates that exactly match the viewport
346346
* coordinates of each vertex. This is done by multiplying the vertex
347-
* positions by the model view matrix and by the projection matrix. */
347+
* positions by the model view matrix and by the projection matrix.
348+
* Note that since the texture coordinate generator only works with
349+
* matrices up to 3x4, it's unable to multiply the full 4x4 matrix needed
350+
* for the projection, so we have to resort to some hacks (described
351+
* below).
352+
* Here we just take the movel view matrix and apply the scale on the X and
353+
* Y coordinates from the projection matrix. */
348354
Mtx m;
349355
guMtxScaleApply(glparamstate.modelview_matrix, m,
350356
glparamstate.projection_matrix[0][0],
351357
glparamstate.projection_matrix[1][1],
352358
1.0);
353-
/* This matrix scales the [-1,1]x[-1,1] viewport to [0,1]x[0,1]. I have no
354-
* idea how and why it works, but it does! */
355-
const static Mtx trans = {
356-
{-0.5, 0, 0.5, 0},
357-
{0, 0.5, 0.5, 0},
358-
{0, 0, 1, 0},
359-
};
360-
guMtxConcat(trans, m, m);
361-
GX_LoadTexMtxImm(m, tex_mtx, GX_MTX3x4);
359+
u8 matrix_type;
360+
if (glparamstate.projection_matrix[3][3] != 0) {
361+
/* Othographic projection: this can be handled by a 2x4 matrix. We
362+
* apply a scale & translation matrix to transform the [-1,1]x[-1,1]
363+
* clip space coordinates to the [0,1]x[0,1] range which we need for
364+
* the s and t texture coordinates. This is can be done by scaling by
365+
* 0.5 and translating along the positive X and Y axes by 0.5. */
366+
matrix_type = GX_TG_MTX2x4;
367+
const static Mtx trans = {
368+
{0.5, 0, 0, 0.5},
369+
{0, -0.5, 0, 0.5},
370+
{0, 0, 0, 1}, /* this row is ignored */
371+
};
372+
guMtxConcat(trans, m, m);
373+
GX_LoadTexMtxImm(m, tex_mtx, GX_MTX2x4);
374+
} else {
375+
/* Perspective projection: this is conceptually harder, because the
376+
* operation that we need to perform (and that we do usually perform
377+
* when drawing to the screen) involves dividing the x, y, z
378+
* coordinates by the w coordinate, whose value in turn depends on the
379+
* z coordinate. See the PDF document for an explanation of why this
380+
* works. */
381+
matrix_type = GX_TG_MTX3x4;
382+
const static Mtx trans = {
383+
{-0.5, 0, 0.5, 0},
384+
{0, 0.5, 0.5, 0},
385+
{0, 0, 1, 0},
386+
};
387+
guMtxConcat(trans, m, m);
388+
GX_LoadTexMtxImm(m, tex_mtx, GX_MTX3x4);
389+
}
362390

363-
GX_SetTexCoordGen(tex_coord, GX_TG_MTX3x4, GX_TG_POS, tex_mtx);
391+
GX_SetTexCoordGen(tex_coord, matrix_type, GX_TG_POS, tex_mtx);
364392
glparamstate.dirty.bits.dirty_texture_gen = 1;
365393

366394
GX_LoadTexObj(&s_stencil_texture, tex_map);

0 commit comments

Comments
 (0)