@@ -344,23 +344,51 @@ static bool setup_tev_full(int *stages, int *tex_coords,
344
344
345
345
/* Add a set of texture coordinates that exactly match the viewport
346
346
* 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. */
348
354
Mtx m ;
349
355
guMtxScaleApply (glparamstate .modelview_matrix , m ,
350
356
glparamstate .projection_matrix [0 ][0 ],
351
357
glparamstate .projection_matrix [1 ][1 ],
352
358
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
+ }
362
390
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 );
364
392
glparamstate .dirty .bits .dirty_texture_gen = 1 ;
365
393
366
394
GX_LoadTexObj (& s_stencil_texture , tex_map );
0 commit comments