diff --git a/bin/segment2.c b/bin/segment2.c index 6b66d0e1..56ac4adf 100644 --- a/bin/segment2.c +++ b/bin/segment2.c @@ -2673,6 +2673,25 @@ UNUSED ALIGNED8 static const Texture texture_radial_light[] = { #include "textures/segment2/light_quarter_circle.ia16.inc.c" }; +#ifdef SHARP_TRANSITION_TEXTURES +const Texture texture_transition_star_half[] = { +#include "textures/segment2/transition_star_half.i8.inc.c" +}; + +const Texture texture_transition_circle_half[] = { +#include "textures/segment2/transition_circle_half.i8.inc.c" +}; + +const Texture texture_transition_mario[] = { +#include "textures/segment2/transition_mario.i8.inc.c" +}; + +const Texture texture_transition_bowser_half[] = { +#include "textures/segment2/transition_bowser_half.i8.inc.c" +}; + +#else + const Texture texture_transition_star_half[] = { #include "textures/segment2/segment2.0F458.ia8.inc.c" }; @@ -2688,6 +2707,7 @@ const Texture texture_transition_mario[] = { const Texture texture_transition_bowser_half[] = { #include "textures/segment2/segment2.11458.ia8.inc.c" }; +#endif const Texture texture_waterbox_water[] = { #include "textures/segment2/segment2.11C58.rgba16.inc.c" diff --git a/include/config/config_graphics.h b/include/config/config_graphics.h index 7817e943..c252e991 100644 --- a/include/config/config_graphics.h +++ b/include/config/config_graphics.h @@ -138,7 +138,7 @@ /** * Limits the horizontal fov on emulator like on console. May break viewport widescreen hacks. */ -//#define HORIZONTAL_CULLING_ON_EMULATOR +// #define HORIZONTAL_CULLING_ON_EMULATOR /** * Makes objects bellow the screen be culled. @@ -150,3 +150,13 @@ * will be used instead. */ #define DEFAULT_CULLING_RADIUS 300 + +/** + * Eases the textured screen transitions to make them look smoother. + */ +#define EASE_IN_OUT_TRANSITIONS + +/** + * Makes use of the tex edge render mode to deliver smooth transition textures + */ +// #define SHARP_TRANSITION_TEXTURES diff --git a/src/engine/math_util.h b/src/engine/math_util.h index a9ca7229..7a80952b 100644 --- a/src/engine/math_util.h +++ b/src/engine/math_util.h @@ -598,4 +598,30 @@ ALWAYS_INLINE f32 remap(f32 x, f32 fromA, f32 toA, f32 fromB, f32 toB) { return (x - fromA) / (toA - fromA) * (toB - fromB) + fromB; } +ALWAYS_INLINE f32 lerpf(f32 from, f32 to, f32 amount) { + return (from + (to - from) * amount); +} + +ALWAYS_INLINE f32 to_smoothstop(f32 x) { + f32 sq = sqr(1.0f - x); + return 1.0f - sq; +} + +// Commonly known as ease-in +ALWAYS_INLINE f32 smoothstart(f32 from, f32 to, f32 amount) { + return lerpf(from, to, sqr(amount)); +} + +// Commonly known as ease-out +ALWAYS_INLINE f32 smoothstop(f32 from, f32 to, f32 amount) { + return lerpf(from, to, to_smoothstop(amount)); +} + +// Commonly known as ease-in-out +ALWAYS_INLINE f32 smoothstep(f32 from, f32 to, f32 amount) { + amount = sqr(amount) * (3.0f - 2.0f * amount); + + return lerpf(from, to, amount); +} + #endif // MATH_UTIL_H diff --git a/src/game/area.c b/src/game/area.c index 53b0ea2d..b917c14e 100644 --- a/src/game/area.c +++ b/src/game/area.c @@ -349,22 +349,34 @@ void play_transition(s16 transType, s16 time, Color red, Color green, Color blue gWarpTransition.data.endTexX = SCREEN_CENTER_X; gWarpTransition.data.endTexY = SCREEN_CENTER_Y; - gWarpTransition.data.texTimer = 0; + gWarpTransition.data.angleSpeed = DEGREES(0); + + s16 fullRadius = GFX_DIMENSIONS_FULL_RADIUS; + + // HackerSM64: this fixes the pop-in with texture transition, comment out this switch + // statement if you want to restore the original full radius. + switch (transType){ + case WARP_TRANSITION_TYPE_BOWSER: + case WARP_TRANSITION_FADE_INTO_BOWSER: + fullRadius *= 4; + break; + + case WARP_TRANSITION_FADE_FROM_MARIO: + case WARP_TRANSITION_FADE_INTO_MARIO: + + case WARP_TRANSITION_FADE_FROM_STAR: + case WARP_TRANSITION_FADE_INTO_STAR: + fullRadius *= 1.5f; + break; + } if (transType & WARP_TRANSITION_FADE_INTO) { // Is the image fading in? - gWarpTransition.data.startTexRadius = GFX_DIMENSIONS_FULL_RADIUS; - if (transType >= WARP_TRANSITION_FADES_INTO_LARGE) { - gWarpTransition.data.endTexRadius = 16; - } else { - gWarpTransition.data.endTexRadius = 0; - } + gWarpTransition.data.startTexRadius = fullRadius; + gWarpTransition.data.endTexRadius = 0; + } else { // The image is fading out. (Reverses start & end circles) - if (transType >= WARP_TRANSITION_FADES_FROM_LARGE) { - gWarpTransition.data.startTexRadius = 16; - } else { - gWarpTransition.data.startTexRadius = 0; - } - gWarpTransition.data.endTexRadius = GFX_DIMENSIONS_FULL_RADIUS; + gWarpTransition.data.startTexRadius = 0; + gWarpTransition.data.endTexRadius = fullRadius; } } #endif @@ -419,7 +431,7 @@ void render_game(void) { if (gWarpTransition.isActive) { if (gWarpTransDelay == 0) { - gWarpTransition.isActive = !render_screen_transition(0, gWarpTransition.type, gWarpTransition.time, + gWarpTransition.isActive = !render_screen_transition(gWarpTransition.type, gWarpTransition.time, &gWarpTransition.data); if (!gWarpTransition.isActive) { if (gWarpTransition.type & WARP_TRANSITION_FADE_INTO) { diff --git a/src/game/area.h b/src/game/area.h index 36cfdc3f..f6dd3610 100644 --- a/src/game/area.h +++ b/src/game/area.h @@ -93,7 +93,7 @@ struct WarpTransitionData { /*0x0C*/ s16 endTexX; /*0x0E*/ s16 endTexY; - /*0x10*/ s16 texTimer; // always 0, does seems to affect transition when disabled + /*0x10*/ s16 angleSpeed; }; enum WarpTransitionFadeDirections { diff --git a/src/game/geo_misc.c b/src/game/geo_misc.c index 4f793271..d78b0248 100644 --- a/src/game/geo_misc.c +++ b/src/game/geo_misc.c @@ -36,31 +36,6 @@ static s16 sFlyingCarpetRippleTimer = 0; s8 gFlyingCarpetState; -/** - * Create a vertex with the given parameters and insert it into `vtx` at - * position `n`. - * - * Texture coordinates are s10.5 fixed-point, which means you should left-shift the actual coordinates by 5. - */ -#ifndef GBI_FLOATS -void make_vertex(Vtx *vtx, s32 n, s16 x, s16 y, s16 z, s16 tx, s16 ty, u8 r, u8 g, u8 b, u8 a) { -#else -void make_vertex(Vtx *vtx, s32 n, f32 x, f32 y, f32 z, s16 tx, s16 ty, u8 r, u8 g, u8 b, u8 a) { -#endif - vtx[n].v.ob[0] = x; - vtx[n].v.ob[1] = y; - vtx[n].v.ob[2] = z; - - vtx[n].v.flag = 0; - - vtx[n].v.tc[0] = tx; - vtx[n].v.tc[1] = ty; - - vtx[n].v.cn[0] = r; - vtx[n].v.cn[1] = g; - vtx[n].v.cn[2] = b; - vtx[n].v.cn[3] = a; -} #define NUM_STARS_REQUIRED_FOR_WING_CAP_LIGHT 10 /** diff --git a/src/game/geo_misc.h b/src/game/geo_misc.h index 5e7c297e..8fcfde5e 100644 --- a/src/game/geo_misc.h +++ b/src/game/geo_misc.h @@ -12,15 +12,50 @@ enum FlyingCarpetState { extern s8 gFlyingCarpetState; -#ifndef GBI_FLOATS -extern void make_vertex( - Vtx *vtx, s32 n, s16 x, s16 y, s16 z, s16 tx, s16 ty, u8 r, u8 g, u8 b, u8 a -); -#else -extern void make_vertex( - Vtx *vtx, s32 n, f32 x, f32 y, f32 z, s16 tx, s16 ty, u8 r, u8 g, u8 b, u8 a -); -#endif +/** + * Create a vertex with the given parameters and insert it into `vtx` at + * position `n`. + * + * Texture coordinates are s10.5 fixed-point, which means you should left-shift the actual coordinates by 5. + */ +ALWAYS_INLINE void make_vertex(Vtx *vtx, s32 n, s16 x, s16 y, s16 z, s16 tx, s16 ty, u8 r, u8 g, u8 b, u8 a) { + vtx[n].v.ob[0] = x; + vtx[n].v.ob[1] = y; + vtx[n].v.ob[2] = z; + + vtx[n].v.flag = 0; + + vtx[n].v.tc[0] = tx; + vtx[n].v.tc[1] = ty; + + vtx[n].v.cn[0] = r; + vtx[n].v.cn[1] = g; + vtx[n].v.cn[2] = b; + vtx[n].v.cn[3] = a; +} + +/** + * Create a colourless vertex with the given parameters and insert it into `vtx` at + * position `n`. + * + * Texture coordinates are s10.5 fixed-point, which means you should left-shift the actual coordinates by 5. + */ +ALWAYS_INLINE void make_simple_vertex(Vtx *vtx, s32 n, s16 x, s16 y, s16 z, s16 tx, s16 ty) { + vtx[n].v.ob[0] = x; + vtx[n].v.ob[1] = y; + vtx[n].v.ob[2] = z; + + vtx[n].v.flag = 0; + + vtx[n].v.tc[0] = tx; + vtx[n].v.tc[1] = ty; + + vtx[n].v.cn[0] = 255; + vtx[n].v.cn[1] = 255; + vtx[n].v.cn[2] = 255; + vtx[n].v.cn[3] = 255; +} + extern Gfx *geo_exec_inside_castle_light(s32 callContext, struct GraphNode *node, UNUSED Mat4 mtx); extern Gfx *geo_exec_flying_carpet_timer_update(s32 callContext, struct GraphNode *node, UNUSED Mat4 mtx); extern Gfx *geo_exec_flying_carpet_create(s32 callContext, struct GraphNode *node, UNUSED Mat4 mtx); diff --git a/src/game/screen_transition.c b/src/game/screen_transition.c index 5a1b3c3a..0db3ae11 100644 --- a/src/game/screen_transition.c +++ b/src/game/screen_transition.c @@ -13,150 +13,8 @@ #include "segment2.h" #include "sm64.h" -u8 sTransitionColorFadeCount[4] = { 0 }; -u16 sTransitionTextureFadeCount[2] = { 0 }; - -s32 set_and_reset_transition_fade_timer(s8 fadeTimer, u8 transTime) { - s32 reset = FALSE; - - sTransitionColorFadeCount[fadeTimer]++; - - if (sTransitionColorFadeCount[fadeTimer] >= transTime) { - sTransitionColorFadeCount[fadeTimer] = 0; - sTransitionTextureFadeCount[fadeTimer] = 0; - reset = TRUE; - } - return reset; -} - -u8 set_transition_color_fade_alpha(s8 fadeType, s8 fadeTimer, u8 transTime) { - u8 time = 0; - - switch (fadeType) { - case COLOR_TRANS_FADE_INTO_COLOR: - time = (f32) sTransitionColorFadeCount[fadeTimer] * 255.0 / (f32)(transTime - 1) + 0.5; // fade in - break; - case COLOR_TRANS_FADE_FROM_COLOR: - time = (1.0 - sTransitionColorFadeCount[fadeTimer] / (f32)(transTime - 1)) * 255.0 + 0.5; // fade out - break; - } - return time; -} - -Vtx *vertex_transition_color(struct WarpTransitionData *transData, u8 alpha) { - Vtx *verts = alloc_display_list(4 * sizeof(*verts)); - u8 r = transData->red; - u8 g = transData->green; - u8 b = transData->blue; - - if (verts != NULL) { - make_vertex(verts, 0, GFX_DIMENSIONS_FROM_LEFT_EDGE(0), 0, -1, 0, 0, r, g, b, alpha); - make_vertex(verts, 1, GFX_DIMENSIONS_FROM_RIGHT_EDGE(0), 0, -1, 0, 0, r, g, b, alpha); - make_vertex(verts, 2, GFX_DIMENSIONS_FROM_RIGHT_EDGE(0), SCREEN_HEIGHT, -1, 0, 0, r, g, b, alpha); - make_vertex(verts, 3, GFX_DIMENSIONS_FROM_LEFT_EDGE(0), SCREEN_HEIGHT, -1, 0, 0, r, g, b, alpha); - } - return verts; -} - -s32 dl_transition_color(s8 fadeTimer, u8 transTime, struct WarpTransitionData *transData, u8 alpha) { - Vtx *verts = vertex_transition_color(transData, alpha); - - if (verts != NULL) { - gSPDisplayList(gDisplayListHead++, dl_proj_mtx_fullscreen); - gDPSetCombineMode(gDisplayListHead++, G_CC_SHADE, G_CC_SHADE); - gDPSetRenderMode(gDisplayListHead++, G_RM_AA_XLU_SURF, G_RM_AA_XLU_SURF2); - gSPVertex(gDisplayListHead++, VIRTUAL_TO_PHYSICAL(verts), 4, 0); - gSPDisplayList(gDisplayListHead++, dl_draw_quad_verts_0123); - gSPDisplayList(gDisplayListHead++, dl_screen_transition_end); - } - return set_and_reset_transition_fade_timer(fadeTimer, transTime); -} - -s32 render_fade_transition_from_color(s8 fadeTimer, u8 transTime, struct WarpTransitionData *transData) { - u8 alpha = set_transition_color_fade_alpha(COLOR_TRANS_FADE_FROM_COLOR, fadeTimer, transTime); - - return dl_transition_color(fadeTimer, transTime, transData, alpha); -} - -s32 render_fade_transition_into_color(s8 fadeTimer, u8 transTime, struct WarpTransitionData *transData) { - u8 alpha = set_transition_color_fade_alpha(COLOR_TRANS_FADE_INTO_COLOR, fadeTimer, transTime); - - return dl_transition_color(fadeTimer, transTime, transData, alpha); -} - -s16 calc_tex_transition_radius(s8 fadeTimer, s8 transTime, struct WarpTransitionData *transData) { - f32 texRadius = transData->endTexRadius - transData->startTexRadius; - f32 radiusTime = sTransitionColorFadeCount[fadeTimer] * texRadius / (f32)(transTime - 1); - f32 result = transData->startTexRadius + radiusTime; - - return (s16)(result + 0.5f); -} - -f32 calc_tex_transition_time(s8 fadeTimer, s8 transTime, struct WarpTransitionData *transData) { - f32 startX = transData->startTexX; - f32 startY = transData->startTexY; - f32 endX = transData->endTexX; - f32 endY = transData->endTexY; - f32 sqrtfXY = sqrtf((startX - endX) * (startX - endX) + (startY - endY) * (startY - endY)); - f32 result = (f32) sTransitionColorFadeCount[fadeTimer] * sqrtfXY / (f32)(transTime - 1); - - return result; -} - -u16 convert_tex_transition_angle_to_pos(struct WarpTransitionData *transData) { - f32 x = transData->endTexX - transData->startTexX; - f32 y = transData->endTexY - transData->startTexY; - - return atan2s(x, y); -} - -s16 center_tex_transition_x(struct WarpTransitionData *transData, f32 texTransTime, u16 texTransPos) { - f32 x = transData->startTexX + coss(texTransPos) * texTransTime; - - return (s16)(x + 0.5); -} - -s16 center_tex_transition_y(struct WarpTransitionData *transData, f32 texTransTime, u16 texTransPos) { - f32 y = transData->startTexY + sins(texTransPos) * texTransTime; - - return (s16)(y + 0.5); -} - -void make_tex_transition_vertex(Vtx *verts, s32 n, s8 fadeTimer, struct WarpTransitionData *transData, s16 centerTransX, s16 centerTransY, - s16 texRadius1, s16 texRadius2, s16 tx, s16 ty) { - u8 r = transData->red; - u8 g = transData->green; - u8 b = transData->blue; - u16 zeroTimer = sTransitionTextureFadeCount[fadeTimer]; - f32 centerX = texRadius1 * coss(zeroTimer) - texRadius2 * sins(zeroTimer) + centerTransX; - f32 centerY = texRadius1 * sins(zeroTimer) + texRadius2 * coss(zeroTimer) + centerTransY; - s16 x = roundf(centerX); - s16 y = roundf(centerY); - - make_vertex(verts, n, x, y, -1, tx * 32, ty * 32, r, g, b, 255); -} - -void load_tex_transition_vertex(Vtx *verts, s8 fadeTimer, struct WarpTransitionData *transData, s16 centerTransX, s16 centerTransY, - s16 texTransRadius, s8 transTexType) { - switch (transTexType) { - case TRANS_TYPE_MIRROR: - make_tex_transition_vertex(verts, 0, fadeTimer, transData, centerTransX, centerTransY, -texTransRadius, -texTransRadius, -31, 63); - make_tex_transition_vertex(verts, 1, fadeTimer, transData, centerTransX, centerTransY, texTransRadius, -texTransRadius, 31, 63); - make_tex_transition_vertex(verts, 2, fadeTimer, transData, centerTransX, centerTransY, texTransRadius, texTransRadius, 31, 0); - make_tex_transition_vertex(verts, 3, fadeTimer, transData, centerTransX, centerTransY, -texTransRadius, texTransRadius, -31, 0); - break; - case TRANS_TYPE_CLAMP: - make_tex_transition_vertex(verts, 0, fadeTimer, transData, centerTransX, centerTransY, -texTransRadius, -texTransRadius, 0, 63); - make_tex_transition_vertex(verts, 1, fadeTimer, transData, centerTransX, centerTransY, texTransRadius, -texTransRadius, 63, 63); - make_tex_transition_vertex(verts, 2, fadeTimer, transData, centerTransX, centerTransY, texTransRadius, texTransRadius, 63, 0); - make_tex_transition_vertex(verts, 3, fadeTimer, transData, centerTransX, centerTransY, -texTransRadius, texTransRadius, 0, 0); - break; - } - make_tex_transition_vertex(verts, 4, fadeTimer, transData, centerTransX, centerTransY, -2000, -2000, 0, 0); - make_tex_transition_vertex(verts, 5, fadeTimer, transData, centerTransX, centerTransY, 2000, -2000, 0, 0); - make_tex_transition_vertex(verts, 6, fadeTimer, transData, centerTransX, centerTransY, 2000, 2000, 0, 0); - make_tex_transition_vertex(verts, 7, fadeTimer, transData, centerTransX, centerTransY, -2000, 2000, 0, 0); -} +u8 sTransitionFadeTimer = 0; +u16 sTransitionTextureAngle = 0; void *sTextureTransitionID[] = { texture_transition_star_half, @@ -165,108 +23,302 @@ void *sTextureTransitionID[] = { texture_transition_bowser_half, }; -s32 render_textured_transition(s8 fadeTimer, s8 transTime, struct WarpTransitionData *transData, s8 texID, s8 transTexType) { - f32 texTransTime = calc_tex_transition_time(fadeTimer, transTime, transData); - u16 texTransPos = convert_tex_transition_angle_to_pos(transData); - s16 centerTransX = center_tex_transition_x(transData, texTransTime, texTransPos); - s16 centerTransY = center_tex_transition_y(transData, texTransTime, texTransPos); - s16 texTransRadius = calc_tex_transition_radius(fadeTimer, transTime, transData); - Vtx *verts = alloc_display_list(8 * sizeof(*verts)); +s32 set_and_reset_transition_fade_timer(u8 transTime) { + sTransitionFadeTimer++; + + if (sTransitionFadeTimer >= transTime) { + sTransitionFadeTimer = 0; + sTransitionTextureAngle = 0; + return TRUE; + } + + return FALSE; +} + +void make_tex_transition_vertex(Vtx *verts, s32 n, f32 centerTransX, f32 centerTransY, + f32 vertX, f32 vertY, s16 tx, s16 ty) { + // Rotate around the center + s16 angle = sTransitionTextureAngle; + f32 x = vertX * coss(angle) - vertY * sins(angle) + centerTransX; + f32 y = vertX * sins(angle) + vertY * coss(angle) + centerTransY; + + s16 roundedX = roundf(x); + s16 roundedY = roundf(y); + + make_simple_vertex(verts, n, roundedX, roundedY, -1, tx * 32, ty * 32); +} + +#define SOLID_COL_RADIUS 2000 +void make_tex_transition_vertices(Vtx *verts, f32 centerTransX, f32 centerTransY, f32 texTransRadius, + s8 transTexType) { + + s16 leftUV, rightUV, downUV, upUV; + + if (transTexType == TRANS_TYPE_MIRROR) { + leftUV = -31; + rightUV = 31; + downUV = 0; + upUV = 63; + } + else { + leftUV = 0; + rightUV = 63; + downUV = 0; + upUV = 63; + } + + // Shape texture + make_tex_transition_vertex(verts, 0, centerTransX, centerTransY, -texTransRadius, -texTransRadius, leftUV, upUV); + make_tex_transition_vertex(verts, 1, centerTransX, centerTransY, texTransRadius, -texTransRadius, rightUV, upUV); + make_tex_transition_vertex(verts, 2, centerTransX, centerTransY, texTransRadius, texTransRadius, rightUV, downUV); + make_tex_transition_vertex(verts, 3, centerTransX, centerTransY, -texTransRadius, texTransRadius, leftUV, downUV); + + // Solid color + make_tex_transition_vertex(verts, 4, centerTransX, centerTransY, -SOLID_COL_RADIUS, -SOLID_COL_RADIUS, 0, 0); + make_tex_transition_vertex(verts, 5, centerTransX, centerTransY, SOLID_COL_RADIUS, -SOLID_COL_RADIUS, 0, 0); + make_tex_transition_vertex(verts, 6, centerTransX, centerTransY, SOLID_COL_RADIUS, SOLID_COL_RADIUS, 0, 0); + make_tex_transition_vertex(verts, 7, centerTransX, centerTransY, -SOLID_COL_RADIUS, SOLID_COL_RADIUS, 0, 0); +} + +f32 calc_tex_transition_radius(s8 transTime, struct WarpTransitionData *transData) { + f32 amount = (f32) sTransitionFadeTimer / (f32) (transTime - 1); + +#ifdef EASE_IN_OUT_TRANSITIONS + return smoothstep(transData->startTexRadius, transData->endTexRadius, amount); +#else + return lerpf(transData->startTexRadius, transData->endTexRadius, amount); +#endif + +} + +f32 center_tex_transition_x(struct WarpTransitionData *transData, f32 posDistance, u16 texTransDir) { + f32 x = transData->startTexX + coss(texTransDir) * posDistance; + + return x; +} + +f32 center_tex_transition_y(struct WarpTransitionData *transData, f32 posDistance, u16 texTransDir) { + f32 y = transData->startTexY + sins(texTransDir) * posDistance; + + return y; +} + +f32 calc_tex_transition_pos_distance(s8 transTime, struct WarpTransitionData *transData) { + f32 startX = transData->startTexX; + f32 startY = transData->startTexY; + f32 endX = transData->endTexX; + f32 endY = transData->endTexY; + + f32 distance = sqrtf(sqr(startX - endX) + sqr(startY - endY)); + + f32 amount = (f32) sTransitionFadeTimer / (f32)(transTime - 1); + + return distance * amount; +} + +u16 calc_tex_transition_direction(struct WarpTransitionData *transData) { + f32 x = transData->endTexX - transData->startTexX; + f32 y = transData->endTexY - transData->startTexY; + + return atan2s(x, y); +} + +/* + * Called during render_screen_transition. + * Handles shape transitions (such as the star, circle and Mario and bowser´s heads). + */ +s32 render_textured_transition(s8 transTime, struct WarpTransitionData *transData, s8 texID, s8 transTexType) { + u16 texTransDir = calc_tex_transition_direction(transData); + + f32 posDistance = calc_tex_transition_pos_distance(transTime, transData); + f32 centerTransX = center_tex_transition_x(transData, posDistance, texTransDir); + f32 centerTransY = center_tex_transition_y(transData, posDistance, texTransDir); + + f32 texTransRadius = calc_tex_transition_radius(transTime, transData); + Vtx *verts = alloc_display_list(8 * sizeof(Vtx)); + if (verts != NULL) { - load_tex_transition_vertex(verts, fadeTimer, transData, centerTransX, centerTransY, texTransRadius, transTexType); + make_tex_transition_vertices(verts, centerTransX, centerTransY, texTransRadius, transTexType); gSPDisplayList(gDisplayListHead++, dl_proj_mtx_fullscreen); - gDPSetCombineMode(gDisplayListHead++, G_CC_SHADE, G_CC_SHADE); + + u8 r = transData->red; + u8 g = transData->green; + u8 b = transData->blue; + gDPSetPrimColor(gDisplayListHead++, 0, 0, r, g, b, 255); + + gDPSetCombineMode(gDisplayListHead++, G_CC_PRIMITIVE, G_CC_PRIMITIVE); gDPSetRenderMode(gDisplayListHead++, G_RM_AA_OPA_SURF, G_RM_AA_OPA_SURF2); + gSPVertex(gDisplayListHead++, VIRTUAL_TO_PHYSICAL(verts), 8, 0); gSPDisplayList(gDisplayListHead++, dl_transition_draw_filled_region); gDPPipeSync(gDisplayListHead++); - gDPSetCombineMode(gDisplayListHead++, G_CC_MODULATEIDECALA, G_CC_MODULATEIDECALA); + + gDPSetCombineLERP(gDisplayListHead++, 0, 0, 0, PRIMITIVE, 0, 0, 0, TEXEL0, + 0, 0, 0, PRIMITIVE, 0, 0, 0, TEXEL0); + +#ifdef SHARP_TRANSITION_TEXTURES + gDPSetRenderMode(gDisplayListHead++, G_RM_AA_TEX_EDGE, G_RM_AA_TEX_EDGE2); + s32 textureType = G_IM_FMT_I; +#else gDPSetRenderMode(gDisplayListHead++, G_RM_AA_XLU_SURF, G_RM_AA_XLU_SURF2); + s32 textureType = G_IM_FMT_IA; +#endif + gDPSetTextureFilter(gDisplayListHead++, G_TF_BILERP); + switch (transTexType) { - case TRANS_TYPE_MIRROR: - gDPLoadTextureBlock(gDisplayListHead++, sTextureTransitionID[texID], G_IM_FMT_IA, G_IM_SIZ_8b, 32, 64, 0, - G_TX_WRAP | G_TX_MIRROR, G_TX_WRAP | G_TX_MIRROR, 5, 6, G_TX_NOLOD, G_TX_NOLOD); - break; - case TRANS_TYPE_CLAMP: - gDPLoadTextureBlock(gDisplayListHead++, sTextureTransitionID[texID], G_IM_FMT_IA, G_IM_SIZ_8b, 64, 64, 0, - G_TX_CLAMP, G_TX_CLAMP, 6, 6, G_TX_NOLOD, G_TX_NOLOD); - break; + case TRANS_TYPE_MIRROR: + gDPLoadTextureBlock(gDisplayListHead++, sTextureTransitionID[texID], textureType, G_IM_SIZ_8b, 32, 64, 0, + G_TX_WRAP | G_TX_MIRROR, G_TX_WRAP | G_TX_MIRROR, 5, 6, G_TX_NOLOD, G_TX_NOLOD); + break; + case TRANS_TYPE_CLAMP: + gDPLoadTextureBlock(gDisplayListHead++, sTextureTransitionID[texID], textureType, G_IM_SIZ_8b, 64, 64, 0, + G_TX_CLAMP, G_TX_CLAMP, 6, 6, G_TX_NOLOD, G_TX_NOLOD); + break; } gSPTexture(gDisplayListHead++, 0xFFFF, 0xFFFF, 0, G_TX_RENDERTILE, G_ON); gSPVertex(gDisplayListHead++, VIRTUAL_TO_PHYSICAL(verts), 4, 0); gSPDisplayList(gDisplayListHead++, dl_draw_quad_verts_0123); gSPTexture(gDisplayListHead++, 0xFFFF, 0xFFFF, 0, G_TX_RENDERTILE, G_OFF); gSPDisplayList(gDisplayListHead++, dl_screen_transition_end); - sTransitionTextureFadeCount[fadeTimer] += transData->texTimer; + sTransitionTextureAngle += transData->angleSpeed; } - return set_and_reset_transition_fade_timer(fadeTimer, transTime); + return set_and_reset_transition_fade_timer(transTime); } -s32 render_screen_transition(s8 fadeTimer, s8 transType, u8 transTime, struct WarpTransitionData *transData) { +Vtx *vertex_transition_color() { + Vtx *verts = alloc_display_list(4 * sizeof(Vtx)); + + if (verts != NULL) { + make_simple_vertex(verts, 0, GFX_DIMENSIONS_FROM_LEFT_EDGE(0), 0, -1, 0, 0); + make_simple_vertex(verts, 1, GFX_DIMENSIONS_FROM_RIGHT_EDGE(0), 0, -1, 0, 0); + make_simple_vertex(verts, 2, GFX_DIMENSIONS_FROM_RIGHT_EDGE(0), SCREEN_HEIGHT, -1, 0, 0); + make_simple_vertex(verts, 3, GFX_DIMENSIONS_FROM_LEFT_EDGE(0), SCREEN_HEIGHT, -1, 0, 0); + } + return verts; +} + +s32 dl_transition_color(u8 transTime, struct WarpTransitionData *transData, u8 alpha) { + Vtx *verts = vertex_transition_color(); + + if (verts != NULL) { + u8 r = transData->red; + u8 g = transData->green; + u8 b = transData->blue; + gDPSetPrimColor(gDisplayListHead++, 0, 0, r, g, b, alpha); + + gSPDisplayList(gDisplayListHead++, dl_proj_mtx_fullscreen); + gDPSetCombineMode(gDisplayListHead++, G_CC_PRIMITIVE, G_CC_PRIMITIVE); + gDPSetRenderMode(gDisplayListHead++, G_RM_AA_XLU_SURF, G_RM_AA_XLU_SURF2); + gSPVertex(gDisplayListHead++, VIRTUAL_TO_PHYSICAL(verts), 4, 0); + gSPDisplayList(gDisplayListHead++, dl_draw_quad_verts_0123); + gSPDisplayList(gDisplayListHead++, dl_screen_transition_end); + } + return set_and_reset_transition_fade_timer(transTime); +} + +u8 set_transition_color_fade_alpha(s8 fadeType, u8 transTime) { + u8 time = 0; + f32 amount = (f32) sTransitionFadeTimer / (f32) (transTime - 1); + switch (fadeType) { + case COLOR_TRANS_FADE_INTO_COLOR: + time = lerpf(0.f, 255.0f, amount); + break; + case COLOR_TRANS_FADE_FROM_COLOR: + time = lerpf(255.0f, 0.f, amount); + break; + } + return roundf(time); +} + +s32 render_fade_transition_from_color(u8 transTime, struct WarpTransitionData *transData) { + u8 alpha = set_transition_color_fade_alpha(COLOR_TRANS_FADE_FROM_COLOR, transTime); + + return dl_transition_color(transTime, transData, alpha); +} + +s32 render_fade_transition_into_color(u8 transTime, struct WarpTransitionData *transData) { + u8 alpha = set_transition_color_fade_alpha(COLOR_TRANS_FADE_INTO_COLOR, transTime); + + return dl_transition_color(transTime, transData, alpha); +} + +/* + * Called during rendering if gWarpTransition.isActive is on. + * Handles solid colour transitions and shape transitions + * (such as the star, circle and Mario and bowser´s heads). + */ +s32 render_screen_transition(s8 transType, u8 transTime, struct WarpTransitionData *transData) { switch (transType) { case WARP_TRANSITION_FADE_FROM_COLOR: - return render_fade_transition_from_color(fadeTimer, transTime, transData); + return render_fade_transition_from_color(transTime, transData); break; case WARP_TRANSITION_FADE_INTO_COLOR: - return render_fade_transition_into_color(fadeTimer, transTime, transData); + return render_fade_transition_into_color(transTime, transData); break; + case WARP_TRANSITION_FADE_FROM_STAR: - return render_textured_transition(fadeTimer, transTime, transData, TEX_TRANS_STAR, TRANS_TYPE_MIRROR); + return render_textured_transition(transTime, transData, TEX_TRANS_STAR, TRANS_TYPE_MIRROR); break; case WARP_TRANSITION_FADE_INTO_STAR: - return render_textured_transition(fadeTimer, transTime, transData, TEX_TRANS_STAR, TRANS_TYPE_MIRROR); + return render_textured_transition(transTime, transData, TEX_TRANS_STAR, TRANS_TYPE_MIRROR); break; + case WARP_TRANSITION_FADE_FROM_CIRCLE: - return render_textured_transition(fadeTimer, transTime, transData, TEX_TRANS_CIRCLE, TRANS_TYPE_MIRROR); + return render_textured_transition(transTime, transData, TEX_TRANS_CIRCLE, TRANS_TYPE_MIRROR); break; case WARP_TRANSITION_FADE_INTO_CIRCLE: - return render_textured_transition(fadeTimer, transTime, transData, TEX_TRANS_CIRCLE, TRANS_TYPE_MIRROR); + return render_textured_transition(transTime, transData, TEX_TRANS_CIRCLE, TRANS_TYPE_MIRROR); break; + case WARP_TRANSITION_FADE_FROM_MARIO: - return render_textured_transition(fadeTimer, transTime, transData, TEX_TRANS_MARIO, TRANS_TYPE_CLAMP); + return render_textured_transition(transTime, transData, TEX_TRANS_MARIO, TRANS_TYPE_CLAMP); break; case WARP_TRANSITION_FADE_INTO_MARIO: - return render_textured_transition(fadeTimer, transTime, transData, TEX_TRANS_MARIO, TRANS_TYPE_CLAMP); + return render_textured_transition(transTime, transData, TEX_TRANS_MARIO, TRANS_TYPE_CLAMP); break; + case WARP_TRANSITION_FADE_FROM_BOWSER: - return render_textured_transition(fadeTimer, transTime, transData, TEX_TRANS_BOWSER, TRANS_TYPE_MIRROR); + return render_textured_transition(transTime, transData, TEX_TRANS_BOWSER, TRANS_TYPE_MIRROR); break; case WARP_TRANSITION_FADE_INTO_BOWSER: - return render_textured_transition(fadeTimer, transTime, transData, TEX_TRANS_BOWSER, TRANS_TYPE_MIRROR); + return render_textured_transition(transTime, transData, TEX_TRANS_BOWSER, TRANS_TYPE_MIRROR); break; } return FALSE; } + Gfx *render_cannon_circle_base(void) { #ifdef WIDESCREEN - Vtx *verts = alloc_display_list(8 * sizeof(*verts)); - Gfx *dlist = alloc_display_list(20 * sizeof(*dlist)); + Vtx *verts = alloc_display_list(8 * sizeof(Vtx)); + Gfx *dlist = alloc_display_list(20 * sizeof(Gfx)); #else - Vtx *verts = alloc_display_list(4 * sizeof(*verts)); - Gfx *dlist = alloc_display_list(16 * sizeof(*dlist)); + Vtx *verts = alloc_display_list(4 * sizeof(Vtx)); + Gfx *dlist = alloc_display_list(16 * sizeof(Gfx)); #endif Gfx *g = dlist; if (verts != NULL && dlist != NULL) { - make_vertex(verts, 0, 0, 0, -1, -1152, 1824, 0, 0, 0, 255); - make_vertex(verts, 1, SCREEN_WIDTH, 0, -1, 1152, 1824, 0, 0, 0, 255); - make_vertex(verts, 2, SCREEN_WIDTH, SCREEN_HEIGHT, -1, 1152, 192, 0, 0, 0, 255); - make_vertex(verts, 3, 0, SCREEN_HEIGHT, -1, -1152, 192, 0, 0, 0, 255); + gDPSetPrimColor(gDisplayListHead++, 0, 0, 0, 0, 0, 255); + + make_simple_vertex(verts, 0, 0, 0, -1, -1152, 1824); + make_simple_vertex(verts, 1, SCREEN_WIDTH, 0, -1, 1152, 1824); + make_simple_vertex(verts, 2, SCREEN_WIDTH, SCREEN_HEIGHT, -1, 1152, 192); + make_simple_vertex(verts, 3, 0, SCREEN_HEIGHT, -1, -1152, 192); #ifdef WIDESCREEN // Render black rectangles outside the 4:3 area. - make_vertex(verts, 4, GFX_DIMENSIONS_FROM_LEFT_EDGE(0), 0, -1, 0, 0, 0, 0, 0, 255); - make_vertex(verts, 5, GFX_DIMENSIONS_FROM_RIGHT_EDGE(0), 0, -1, 0, 0, 0, 0, 0, 255); - make_vertex(verts, 6, GFX_DIMENSIONS_FROM_RIGHT_EDGE(0), SCREEN_HEIGHT, -1, 0, 0, 0, 0, 0, 255); - make_vertex(verts, 7, GFX_DIMENSIONS_FROM_LEFT_EDGE(0), SCREEN_HEIGHT, -1, 0, 0, 0, 0, 0, 255); + make_simple_vertex(verts, 4, GFX_DIMENSIONS_FROM_LEFT_EDGE(0), 0, -1, 0, 0, 0); + make_simple_vertex(verts, 5, GFX_DIMENSIONS_FROM_RIGHT_EDGE(0), 0, -1, 0, 0, 0); + make_simple_vertex(verts, 6, GFX_DIMENSIONS_FROM_RIGHT_EDGE(0), SCREEN_HEIGHT, -1, 0, 0); + make_simple_vertex(verts, 7, GFX_DIMENSIONS_FROM_LEFT_EDGE(0), SCREEN_HEIGHT, -1, 0, 0); #endif gSPDisplayList(g++, dl_proj_mtx_fullscreen); - gDPSetCombineMode(g++, G_CC_MODULATEIDECALA, G_CC_MODULATEIDECALA); + gDPSetCombineMode(g++, G_CC_MODULATEIA_PRIM, G_CC_MODULATEIA_PRIM); gDPSetTextureFilter(g++, G_TF_BILERP); gDPLoadTextureBlock(g++, sTextureTransitionID[TEX_TRANS_CIRCLE], G_IM_FMT_IA, G_IM_SIZ_8b, 32, 64, 0, G_TX_WRAP | G_TX_MIRROR, G_TX_WRAP | G_TX_MIRROR, 5, 6, G_TX_NOLOD, G_TX_NOLOD); diff --git a/src/game/screen_transition.h b/src/game/screen_transition.h index f78517f5..0bfb092a 100644 --- a/src/game/screen_transition.h +++ b/src/game/screen_transition.h @@ -24,7 +24,7 @@ enum ColorTransitionFade { COLOR_TRANS_FADE_FROM_COLOR, }; -s32 render_screen_transition(s8 fadeTimer, s8 transType, u8 transTime, struct WarpTransitionData *transData); +s32 render_screen_transition(s8 transType, u8 transTime, struct WarpTransitionData *transData); Gfx *geo_cannon_circle_base(s32 callContext, struct GraphNode *node, UNUSED Mat4 mtx); #endif // SCREEN_TRANSITION_H diff --git a/textures/segment2/transition_bowser_half.i8.png b/textures/segment2/transition_bowser_half.i8.png new file mode 100644 index 00000000..7f321dc5 Binary files /dev/null and b/textures/segment2/transition_bowser_half.i8.png differ diff --git a/textures/segment2/transition_circle_half.i8.png b/textures/segment2/transition_circle_half.i8.png new file mode 100644 index 00000000..fcdf54ed Binary files /dev/null and b/textures/segment2/transition_circle_half.i8.png differ diff --git a/textures/segment2/transition_mario.i8.png b/textures/segment2/transition_mario.i8.png new file mode 100644 index 00000000..6aaeb88e Binary files /dev/null and b/textures/segment2/transition_mario.i8.png differ diff --git a/textures/segment2/transition_star_half.i8.png b/textures/segment2/transition_star_half.i8.png new file mode 100644 index 00000000..f5843af0 Binary files /dev/null and b/textures/segment2/transition_star_half.i8.png differ