WIP: uncapped framerate 5

This commit is contained in:
MysterD 2022-04-27 19:43:55 -07:00
parent 0eece3001f
commit 6e47f226c9
4 changed files with 149 additions and 62 deletions

View file

@ -155,6 +155,11 @@ Vtx* gBackgroundSkyboxVerts[3][3] = { 0 };
Mtx* gBackgroundSkyboxMtx = NULL; Mtx* gBackgroundSkyboxMtx = NULL;
struct GraphNodeRoot* sBackgroundNodeRoot = NULL; struct GraphNodeRoot* sBackgroundNodeRoot = NULL;
#define MAX_SHADOW_NODES 128
struct ShadowInterp sShadowInterp[MAX_SHADOW_NODES] = { 0 };
struct ShadowInterp* gShadowInterpCurrent = NULL;
static u8 sShadowInterpCount = 0;
struct { struct {
Gfx *pos; Gfx *pos;
void *mtx; void *mtx;
@ -189,6 +194,8 @@ void patch_mtx_before(void) {
sBackgroundNode = NULL; sBackgroundNode = NULL;
gBackgroundSkyboxGfx = NULL; gBackgroundSkyboxGfx = NULL;
} }
sShadowInterpCount = 0;
} }
void patch_mtx_interpolated(f32 delta) { void patch_mtx_interpolated(f32 delta) {
@ -232,6 +239,20 @@ void patch_mtx_interpolated(f32 delta) {
gCurGraphNodeRoot = rootCopy; gCurGraphNodeRoot = rootCopy;
} }
struct GraphNodeObject* savedObj = gCurGraphNodeObject;
for (s32 i = 0; i < sShadowInterpCount; i++) {
struct ShadowInterp* interp = &sShadowInterp[i];
gShadowInterpCurrent = interp;
Vec3f posInterp;
delta_interpolate_vec3f(posInterp, interp->shadowPosPrev, interp->shadowPos, delta);
if (i == 0) {
printf("XXX: %f <--> %f == %f\n", interp->shadowPosPrev[1], interp->shadowPos[1], posInterp[1]);
}
gCurGraphNodeObject = interp->obj;
create_shadow_below_xyz(posInterp[0], posInterp[1], posInterp[2], interp->shadowScale, interp->node->shadowSolidity, interp->node->shadowType);
}
gCurGraphNodeObject = savedObj;
for (s32 i = 0; i < gMtxTblSize; i++) { for (s32 i = 0; i < gMtxTblSize; i++) {
Gfx *pos = gMtxTbl[i].pos; Gfx *pos = gMtxTbl[i].pos;
delta_interpolate_mtx(&gMtxTbl[i].interp, (Mtx*) gMtxTbl[i].mtxPrev, (Mtx*) gMtxTbl[i].mtx, delta); delta_interpolate_mtx(&gMtxTbl[i].interp, (Mtx*) gMtxTbl[i].mtxPrev, (Mtx*) gMtxTbl[i].mtx, delta);
@ -241,6 +262,7 @@ void patch_mtx_interpolated(f32 delta) {
gSPDisplayList(pos++, gMtxTbl[i].displayList); gSPDisplayList(pos++, gMtxTbl[i].displayList);
} }
} }
} }
/** /**
@ -949,16 +971,30 @@ static void geo_process_shadow(struct GraphNodeShadow *node) {
gCurGraphNodeObject->prevShadowPosTimestamp = gGlobalTimer; gCurGraphNodeObject->prevShadowPosTimestamp = gGlobalTimer;
} }
if (sShadowInterpCount < MAX_SHADOW_NODES) {
struct ShadowInterp* interp = &sShadowInterp[sShadowInterpCount++];
gShadowInterpCurrent = interp;
interp->gfx = NULL;
interp->node = node;
interp->shadowScale = shadowScale;
interp->obj = gCurGraphNodeObject;
vec3f_copy(interp->shadowPos, shadowPos);
vec3f_copy(interp->shadowPosPrev, shadowPosPrev);
} else {
gShadowInterpCurrent = NULL;
}
Gfx *shadowListPrev = create_shadow_below_xyz(shadowPosPrev[0], shadowPosPrev[1], Gfx *shadowListPrev = create_shadow_below_xyz(shadowPosPrev[0], shadowPosPrev[1],
shadowPosPrev[2], shadowScale, shadowPosPrev[2], shadowScale,
node->shadowSolidity, node->shadowType); node->shadowSolidity, node->shadowType);
Gfx *shadowList = create_shadow_below_xyz(shadowPos[0], shadowPos[1], shadowPos[2], shadowScale, if (gShadowInterpCurrent != NULL) {
node->shadowSolidity, node->shadowType); gShadowInterpCurrent->gfx = shadowListPrev;
if (shadowListPrev != NULL && shadowList != NULL) { }
if (shadowListPrev != NULL) {
mtxf_translate(mtxf, shadowPos); mtxf_translate(mtxf, shadowPos);
mtxf_mul(gMatStack[gMatStackIndex + 1], mtxf, *gCurGraphNodeCamera->matrixPtr); mtxf_mul(gMatStack[gMatStackIndex + 1], mtxf, *gCurGraphNodeCamera->matrixPtr);
mtxf_translate(mtxf, shadowPosPrev); mtxf_translate(mtxf, shadowPosPrev);
mtxf_mul(gMatStackPrev[gMatStackIndex + 1], mtxf, *gCurGraphNodeCamera->matrixPtrPrev); mtxf_mul(gMatStackPrev[gMatStackIndex + 1], mtxf, *gCurGraphNodeCamera->matrixPtrPrev);
@ -966,13 +1002,13 @@ static void geo_process_shadow(struct GraphNodeShadow *node) {
if (!increment_mat_stack()) { return; } if (!increment_mat_stack()) { return; }
if (gShadowAboveWaterOrLava == TRUE) { if (gShadowAboveWaterOrLava == TRUE) {
geo_append_display_list2((void *) VIRTUAL_TO_PHYSICAL(shadowList), geo_append_display_list2((void *) VIRTUAL_TO_PHYSICAL(shadowListPrev),
(void *) VIRTUAL_TO_PHYSICAL(shadowListPrev), 4); (void *) VIRTUAL_TO_PHYSICAL(shadowListPrev), 4);
} else if (gMarioOnIceOrCarpet == TRUE) { } else if (gMarioOnIceOrCarpet == TRUE) {
geo_append_display_list2((void *) VIRTUAL_TO_PHYSICAL(shadowList), geo_append_display_list2((void *) VIRTUAL_TO_PHYSICAL(shadowListPrev),
(void *) VIRTUAL_TO_PHYSICAL(shadowListPrev), 5); (void *) VIRTUAL_TO_PHYSICAL(shadowListPrev), 5);
} else { } else {
geo_append_display_list2((void *) VIRTUAL_TO_PHYSICAL(shadowList), geo_append_display_list2((void *) VIRTUAL_TO_PHYSICAL(shadowListPrev),
(void *) VIRTUAL_TO_PHYSICAL(shadowListPrev), 6); (void *) VIRTUAL_TO_PHYSICAL(shadowListPrev), 6);
} }
gMatStackIndex--; gMatStackIndex--;

View file

@ -33,4 +33,15 @@ void geo_process_root(struct GraphNodeRoot *node, Vp *b, Vp *c, s32 clearColor);
void interpolate_vectors(Vec3f res, Vec3f a, Vec3f b); void interpolate_vectors(Vec3f res, Vec3f a, Vec3f b);
void interpolate_vectors_s16(Vec3s res, Vec3s a, Vec3s b); void interpolate_vectors_s16(Vec3s res, Vec3s a, Vec3s b);
struct ShadowInterp {
Gfx* gfx;
Vec3f shadowPos;
Vec3f shadowPosPrev;
Vtx *verts;
Gfx *displayList;
struct GraphNodeShadow *node;
f32 shadowScale;
struct GraphNodeObject *obj;
};
#endif // RENDERING_GRAPH_NODE_H #endif // RENDERING_GRAPH_NODE_H

View file

@ -16,6 +16,9 @@
// Avoid Z-fighting // Avoid Z-fighting
#define find_floor_height_and_data 0.4 + find_floor_height_and_data #define find_floor_height_and_data 0.4 + find_floor_height_and_data
extern u8 gRenderingInterpolated;
extern struct ShadowInterp* gShadowInterpCurrent;
/** /**
* @file shadow.c * @file shadow.c
* This file implements a self-contained subsystem used to draw shadows. * This file implements a self-contained subsystem used to draw shadows.
@ -114,6 +117,39 @@ s8 gMarioOnIceOrCarpet;
s8 sMarioOnFlyingCarpet; s8 sMarioOnFlyingCarpet;
s16 sSurfaceTypeBelowShadow; s16 sSurfaceTypeBelowShadow;
static Vtx* shadow_get_or_alloc_verts(u8 vertCount) {
if (gRenderingInterpolated) {
if (gShadowInterpCurrent == NULL) {
return NULL;
}
return gShadowInterpCurrent->verts;
} else {
Vtx* verts = alloc_display_list(vertCount * sizeof(Vtx));
if (gShadowInterpCurrent) {
gShadowInterpCurrent->verts = verts;
}
return verts;
}
return NULL;
}
static Gfx* shadow_get_or_alloc_display_list(u8 dlCount) {
if (gRenderingInterpolated) {
if (gShadowInterpCurrent == NULL) {
return NULL;
}
return gShadowInterpCurrent->displayList;
} else {
Gfx *displayList = alloc_display_list(dlCount * sizeof(Gfx));
if (gShadowInterpCurrent) {
gShadowInterpCurrent->displayList = displayList;
}
return displayList;
}
return NULL;
}
/** /**
* Let (oldZ, oldX) be the relative coordinates of a point on a rectangle, * Let (oldZ, oldX) be the relative coordinates of a point on a rectangle,
* assumed to be centered at the origin on the standard SM64 X-Z plane. This * assumed to be centered at the origin on the standard SM64 X-Z plane. This
@ -622,8 +658,8 @@ Gfx *create_shadow_player(f32 xPos, f32 yPos, f32 zPos, s16 shadowScale, u8 soli
return NULL; return NULL;
} }
verts = alloc_display_list(9 * sizeof(Vtx)); verts = shadow_get_or_alloc_verts(9);
displayList = alloc_display_list(5 * sizeof(Gfx)); displayList = shadow_get_or_alloc_display_list(5);
if (verts == NULL || displayList == NULL) { if (verts == NULL || displayList == NULL) {
return NULL; return NULL;
} }
@ -650,8 +686,8 @@ Gfx *create_shadow_circle_9_verts(f32 xPos, f32 yPos, f32 zPos, s16 shadowScale,
return NULL; return NULL;
} }
verts = alloc_display_list(9 * sizeof(Vtx)); verts = shadow_get_or_alloc_verts(9);
displayList = alloc_display_list(5 * sizeof(Gfx)); displayList = shadow_get_or_alloc_display_list(5);
if (verts == NULL || displayList == NULL) { if (verts == NULL || displayList == NULL) {
return 0; return 0;
@ -676,8 +712,8 @@ Gfx *create_shadow_circle_4_verts(f32 xPos, f32 yPos, f32 zPos, s16 shadowScale,
return NULL; return NULL;
} }
verts = alloc_display_list(4 * sizeof(Vtx)); verts = shadow_get_or_alloc_verts(4);
displayList = alloc_display_list(5 * sizeof(Gfx)); displayList = shadow_get_or_alloc_display_list(5);
if (verts == NULL || displayList == NULL) { if (verts == NULL || displayList == NULL) {
return 0; return 0;
@ -709,8 +745,8 @@ Gfx *create_shadow_circle_assuming_flat_ground(f32 xPos, f32 yPos, f32 zPos, s16
distBelowFloor = floorHeight - yPos; distBelowFloor = floorHeight - yPos;
} }
verts = alloc_display_list(4 * sizeof(Vtx)); verts = shadow_get_or_alloc_verts(4);
displayList = alloc_display_list(5 * sizeof(Gfx)); displayList = shadow_get_or_alloc_display_list(5);
if (verts == NULL || displayList == NULL) { if (verts == NULL || displayList == NULL) {
return 0; return 0;
@ -738,8 +774,8 @@ Gfx *create_shadow_spike_ext(f32 xPos, f32 yPos, f32 zPos, s16 shadowScale, u8 s
return NULL; return NULL;
} }
verts = alloc_display_list(4 * sizeof(Vtx)); verts = shadow_get_or_alloc_verts(4);
displayList = alloc_display_list(5 * sizeof(Gfx)); displayList = shadow_get_or_alloc_display_list(5);
if (verts == NULL || displayList == NULL) { if (verts == NULL || displayList == NULL) {
return 0; return 0;
@ -757,8 +793,9 @@ Gfx *create_shadow_spike_ext(f32 xPos, f32 yPos, f32 zPos, s16 shadowScale, u8 s
* underneath the shadow is totally flat. * underneath the shadow is totally flat.
*/ */
Gfx *create_shadow_rectangle(f32 halfWidth, f32 halfLength, f32 relY, u8 solidity) { Gfx *create_shadow_rectangle(f32 halfWidth, f32 halfLength, f32 relY, u8 solidity) {
Vtx *verts = alloc_display_list(4 * sizeof(Vtx)); Vtx *verts = shadow_get_or_alloc_verts(4);
Gfx *displayList = alloc_display_list(5 * sizeof(Gfx)); Gfx *displayList = shadow_get_or_alloc_display_list(5);
f32 frontLeftX, frontLeftZ, frontRightX, frontRightZ, backLeftX, backLeftZ, backRightX, backRightZ; f32 frontLeftX, frontLeftZ, frontRightX, frontRightZ, backLeftX, backLeftZ, backRightX, backRightZ;
if (verts == NULL || displayList == NULL) { if (verts == NULL || displayList == NULL) {

View file

@ -45,10 +45,10 @@
* first, in a display list with the Z buffer disabled * first, in a display list with the Z buffer disabled
*/ */
struct Skybox { struct Skybox {
/// The camera's yaw, from 0 to 65536, which maps to 0 to 360 degrees /// The camera's yaw, from 0 to (M_PI*2), which maps to 0 to 360 degrees
u16 yaw; f32 yaw;
/// The camera's pitch, which is bounded by +-16384, which maps to -90 to 90 degrees /// The camera's pitch, which is bounded by +-(M_PI/2), which maps to -90 to 90 degrees
s16 pitch; f32 pitch;
/// The skybox's X position in world space /// The skybox's X position in world space
f32 scaledX; f32 scaledX;
/// The skybox's Y position in world space /// The skybox's Y position in world space
@ -138,11 +138,11 @@ u8 sSkyboxColors[][3] = {
* (how far is the camera rotated from 0, scaled 0 to 1) * * (how far is the camera rotated from 0, scaled 0 to 1) *
* (the screen width) * (the screen width)
*/ */
s32 calculate_skybox_scaled_x(s8 player, f32 fov) { f32 calculate_skybox_scaled_x(s8 player, f32 fov) {
f32 yaw = sSkyBoxInfo[player].yaw; f32 yaw = sSkyBoxInfo[player].yaw;
//! double literals are used instead of floats //! double literals are used instead of floats
f32 scaledX = SCREEN_WIDTH * 360.0 * yaw / (fov * 65536.0); f32 scaledX = SCREEN_WIDTH * 180.0 * yaw / (fov * M_PI);
if (scaledX > SKYBOX_WIDTH) { if (scaledX > SKYBOX_WIDTH) {
scaledX -= (s32) scaledX / SKYBOX_WIDTH * SKYBOX_WIDTH; scaledX -= (s32) scaledX / SKYBOX_WIDTH * SKYBOX_WIDTH;
@ -156,9 +156,9 @@ s32 calculate_skybox_scaled_x(s8 player, f32 fov) {
* fov may have been used in an earlier version, but the developers changed the function to always use * fov may have been used in an earlier version, but the developers changed the function to always use
* 90 degrees. * 90 degrees.
*/ */
s32 calculate_skybox_scaled_y(s8 player, UNUSED f32 fov) { f32 calculate_skybox_scaled_y(s8 player, UNUSED f32 fov) {
// Convert pitch to degrees. Pitch is bounded between -90 (looking down) and 90 (looking up). // Convert pitch to degrees. Pitch is bounded between -90 (looking down) and 90 (looking up).
f32 pitchInDegrees = (f32) sSkyBoxInfo[player].pitch * 360.0 / 65535.0; f32 pitchInDegrees = sSkyBoxInfo[player].pitch * 180.0 / M_PI;
// Scale by 360 / fov // Scale by 360 / fov
f32 degreesToScale = 360.0f * pitchInDegrees / 90.0; f32 degreesToScale = 360.0f * pitchInDegrees / 90.0;
@ -193,7 +193,7 @@ static s32 get_top_left_tile_idx(s8 player) {
* into an x and y by modulus and division by SKYBOX_COLS. x and y are then scaled by * into an x and y by modulus and division by SKYBOX_COLS. x and y are then scaled by
* SKYBOX_TILE_WIDTH to get a point in world space. * SKYBOX_TILE_WIDTH to get a point in world space.
*/ */
Vtx *make_skybox_rect(s32 tileIndex, s8 colorIndex, s32 row, s32 col, s8 player) { Vtx *make_skybox_rect(s32 tileIndex, s8 colorIndex, s32 row, s32 col) {
extern Vtx* gBackgroundSkyboxVerts[3][3]; extern Vtx* gBackgroundSkyboxVerts[3][3];
Vtx *verts; Vtx *verts;
@ -242,7 +242,7 @@ void draw_skybox_tile_grid(Gfx **dlist, s8 background, s8 player, s8 colorIndex)
texture = (Texture*)(*(SkyboxTexture *) segmented_to_virtual(sSkyboxTextures[background]))[tileIndex]; texture = (Texture*)(*(SkyboxTexture *) segmented_to_virtual(sSkyboxTextures[background]))[tileIndex];
} }
Vtx *vertices = make_skybox_rect(tileIndex, colorIndex, row, col, player); Vtx *vertices = make_skybox_rect(tileIndex, colorIndex, row, col);
gLoadBlockTexture((*dlist)++, 32, 32, G_IM_FMT_RGBA, texture); gLoadBlockTexture((*dlist)++, 32, 32, G_IM_FMT_RGBA, texture);
gSPVertex((*dlist)++, VIRTUAL_TO_PHYSICAL(vertices), 4, 0); gSPVertex((*dlist)++, VIRTUAL_TO_PHYSICAL(vertices), 4, 0);
@ -342,8 +342,11 @@ Gfx *create_skybox_facing_camera(s8 player, s8 background, f32 fov,
//! fov is always set to 90.0f. If this line is removed, then the game crashes because fov is 0 on //! fov is always set to 90.0f. If this line is removed, then the game crashes because fov is 0 on
//! the first frame, which causes a floating point divide by 0 //! the first frame, which causes a floating point divide by 0
fov = 90.0f; fov = 90.0f;
sSkyBoxInfo[player].yaw = atan2s(cameraFaceZ, cameraFaceX);
sSkyBoxInfo[player].pitch = atan2s(sqrtf(cameraFaceX * cameraFaceX + cameraFaceZ * cameraFaceZ), cameraFaceY); sSkyBoxInfo[player].yaw = (M_PI / 2.0) - atan2(cameraFaceZ, cameraFaceX);
if (sSkyBoxInfo[player].yaw < 0) { sSkyBoxInfo[player].yaw += M_PI * 2.0; }
sSkyBoxInfo[player].pitch = (M_PI / 2.0) - atan2(sqrtf(cameraFaceX * cameraFaceX + cameraFaceZ * cameraFaceZ), cameraFaceY);
sSkyBoxInfo[player].scaledX = calculate_skybox_scaled_x(player, fov); sSkyBoxInfo[player].scaledX = calculate_skybox_scaled_x(player, fov);
sSkyBoxInfo[player].scaledY = calculate_skybox_scaled_y(player, fov); sSkyBoxInfo[player].scaledY = calculate_skybox_scaled_y(player, fov);
sSkyBoxInfo[player].upperLeftTile = get_top_left_tile_idx(player); sSkyBoxInfo[player].upperLeftTile = get_top_left_tile_idx(player);