diff --git a/bin/segment2.c b/bin/segment2.c index 55695ccf3c..0427ff2895 100644 --- a/bin/segment2.c +++ b/bin/segment2.c @@ -2761,14 +2761,24 @@ const Gfx dl_draw_quad_verts_4567[] = { gsSPEndDisplayList(), }; +#define G_CC_SHADOW TEXEL0, 0, SHADE, 0, TEXEL0, 0, PRIMITIVE, 0 + const Gfx dl_shadow_begin[] = { gsDPPipeSync(), gsSPClearGeometryMode(G_LIGHTING | G_CULL_BACK), - gsDPSetCombineMode(G_CC_MODULATEIFADEA, G_CC_MODULATEIFADEA), + gsDPSetCombineMode(G_CC_SHADOW, G_CC_SHADOW), gsSPTexture(0xFFFF, 0xFFFF, 0, G_TX_RENDERTILE, G_ON), gsSPEndDisplayList(), }; +const Gfx dl_shadow_end[] = { + gsDPPipeSync(), + gsSPTexture(0xFFFF, 0xFFFF, 0, G_TX_RENDERTILE, G_OFF), + gsSPSetGeometryMode(G_LIGHTING | G_CULL_BACK), + gsDPSetCombineMode(G_CC_SHADE, G_CC_SHADE), + gsSPEndDisplayList(), +}; + #ifdef HD_SHADOWS const Gfx dl_shadow_circle[] = { gsSPDisplayList(dl_shadow_begin), @@ -2810,13 +2820,9 @@ static const Vtx vertex_shadow[] = { }; // 0x02014638 - 0x02014660 -const Gfx dl_shadow_end[] = { +const Gfx dl_shadow_tris[] = { gsSPVertex(vertex_shadow, 4, 0), gsSP2Triangles( 0, 2, 1, 0x0, 1, 2, 3, 0x0), - gsDPPipeSync(), - gsSPTexture(0xFFFF, 0xFFFF, 0, G_TX_RENDERTILE, G_OFF), - gsSPSetGeometryMode(G_LIGHTING | G_CULL_BACK), - gsDPSetCombineMode(G_CC_SHADE, G_CC_SHADE), gsSPEndDisplayList(), }; diff --git a/include/sm64.h b/include/sm64.h index f9c44cd092..4f405cb857 100644 --- a/include/sm64.h +++ b/include/sm64.h @@ -70,12 +70,25 @@ enum RenderLayers { LAYER_OCCLUDE_SILHOUETTE_OPAQUE, LAYER_OCCLUDE_SILHOUETTE_ALPHA, #endif + LAYER_CLD, LAYER_TRANSPARENT_DECAL, LAYER_TRANSPARENT, LAYER_TRANSPARENT_INTER, LAYER_COUNT }; +enum BatchTransparentDecal { + BATCH_TRANSPARENT_DECAL_SHADOW_CIRCLE, + BATCH_TRANSPARENT_DECAL_SHADOW_SQUARE, + BATCH_TRANSPARENT_DECAL_COUNT, +}; + +enum BatchCld { + BATCH_CLD_SHADOW_CIRCLE, + BATCH_CLD_SHADOW_SQUARE, + BATCH_CLD_COUNT, +}; + #define LAYER_FIRST LAYER_FORCE #define LAYER_LAST (LAYER_COUNT - 1) diff --git a/src/engine/batch_list.c b/src/engine/batch_list.c new file mode 100644 index 0000000000..ead07540bc --- /dev/null +++ b/src/engine/batch_list.c @@ -0,0 +1,30 @@ +#include "batch_list.h" + +#include "game/segment2.h" + +static const struct BatchDisplayLists BatchesTransparentDecal[] = { + [ BATCH_TRANSPARENT_DECAL_SHADOW_CIRCLE ] = { dl_shadow_circle, dl_shadow_end }, + [ BATCH_TRANSPARENT_DECAL_SHADOW_SQUARE ] = { dl_shadow_square, dl_shadow_end }, +}; +STATIC_ASSERT(BATCH_TRANSPARENT_DECAL_COUNT == sizeof(BatchesTransparentDecal) / sizeof(*BatchesTransparentDecal), "Mismatch in transparent decal batch count"); + +static const struct BatchDisplayLists BatchesCLD[] = { + [ BATCH_CLD_SHADOW_CIRCLE ] = { dl_shadow_circle, dl_shadow_end }, + [ BATCH_CLD_SHADOW_SQUARE ] = { dl_shadow_square, dl_shadow_end }, +}; +STATIC_ASSERT(BATCH_CLD_COUNT == sizeof(BatchesCLD) / sizeof(*BatchesCLD), "Mismatch in CLD batch count"); + +static inline struct BatchArray* batch_array_alloc(struct AllocOnlyPool *pool, int count, const struct BatchDisplayLists* dls) { + struct BatchArray* batches = alloc_only_pool_alloc(pool, sizeof(struct BatchArray) + count * sizeof(struct DisplayListLinks)); + batches->count = count; + batches->batchDLs = dls; + return batches; +} + +struct BatchArray* batch_list_objects_alloc_xlu_decal(struct AllocOnlyPool *pool) { + return batch_array_alloc(pool, BATCH_TRANSPARENT_DECAL_COUNT, BatchesTransparentDecal); +} + +struct BatchArray* batch_list_objects_alloc_cld(struct AllocOnlyPool *pool) { + return batch_array_alloc(pool, BATCH_CLD_COUNT, BatchesCLD); +} diff --git a/src/engine/batch_list.h b/src/engine/batch_list.h new file mode 100644 index 0000000000..71fb18cd7c --- /dev/null +++ b/src/engine/batch_list.h @@ -0,0 +1,18 @@ +#pragma once + +#include "sm64.h" +#include "engine/graph_node.h" + +struct BatchArray* batch_list_objects_alloc_xlu_decal(struct AllocOnlyPool *pool); +struct BatchArray* batch_list_objects_alloc_cld(struct AllocOnlyPool *pool); + +static inline struct BatchArray* batch_list_objects_alloc(struct AllocOnlyPool *pool, enum RenderLayers layer) { + switch (layer) { + case LAYER_TRANSPARENT_DECAL: + return batch_list_objects_alloc_xlu_decal(pool); + case LAYER_CLD: + return batch_list_objects_alloc_cld(pool); + default: + return 0; + } +} diff --git a/src/engine/graph_node.c b/src/engine/graph_node.c index 62fccb8812..95796090fb 100644 --- a/src/engine/graph_node.c +++ b/src/engine/graph_node.c @@ -8,6 +8,7 @@ #include "game/rendering_graph_node.h" #include "game/area.h" #include "geo_layout.h" +#include "batch_list.h" /** * Initialize a geo node with a given type. Sets all links such that there @@ -122,6 +123,13 @@ struct GraphNodeMasterList *init_graph_node_master_list(struct AllocOnlyPool *po if (on) { graphNode->node.flags |= GRAPH_RENDER_Z_BUFFER; + for (int layer = 0; layer < LAYER_COUNT; layer++) { + graphNode->layers[layer].objects = batch_list_objects_alloc(pool, layer); + } + } else { + for (int layer = 0; layer < LAYER_COUNT; layer++) { + graphNode->layers[layer].objects = NULL; + } } } diff --git a/src/engine/graph_node.h b/src/engine/graph_node.h index bccb8f2b3a..5387703159 100644 --- a/src/engine/graph_node.h +++ b/src/engine/graph_node.h @@ -140,15 +140,35 @@ struct DisplayListNode { struct DisplayListNode *next; }; +struct DisplayListLinks { + struct DisplayListNode* head; + struct DisplayListNode* tail; +}; + +struct BatchDisplayLists { + const void* startDl; + const void* endDl; +}; + +struct BatchArray { + int count; + const struct BatchDisplayLists* batchDLs; + struct DisplayListLinks batches[0]; +}; + +struct MasterLayer { + struct DisplayListLinks list; + struct BatchArray* objects; +}; + /** GraphNode that manages the 8 top-level display lists that will be drawn * Each list has its own render mode, so for example water is drawn in a * different master list than opaque objects. * It also sets the z-buffer on before rendering and off after. */ struct GraphNodeMasterList { - /*0x00*/ struct GraphNode node; - /*0x14*/ struct DisplayListNode *listHeads[LAYER_COUNT]; - /*0x34*/ struct DisplayListNode *listTails[LAYER_COUNT]; + struct GraphNode node; + struct MasterLayer layers[LAYER_COUNT]; }; /** Simply used as a parent to group multiple children. diff --git a/src/game/rendering_graph_node.c b/src/game/rendering_graph_node.c index cb0d62cbbe..64bf729973 100644 --- a/src/game/rendering_graph_node.c +++ b/src/game/rendering_graph_node.c @@ -80,7 +80,7 @@ s16 *gCurrAnimData; struct AllocOnlyPool *gDisplayListHeap; /* Rendermode settings for cycle 1 for all 8 or 13 layers. */ -struct RenderModeContainer renderModeTable_1Cycle[2] = { +static const struct RenderModeContainer renderModeTable_1Cycle[2] = { [RENDER_NO_ZB] = { { [LAYER_FORCE] = G_RM_OPA_SURF, [LAYER_OPAQUE] = G_RM_AA_OPA_SURF, @@ -94,6 +94,7 @@ struct RenderModeContainer renderModeTable_1Cycle[2] = { [LAYER_OCCLUDE_SILHOUETTE_OPAQUE] = G_RM_AA_OPA_SURF, [LAYER_OCCLUDE_SILHOUETTE_ALPHA] = G_RM_AA_TEX_EDGE, #endif + [LAYER_CLD] = G_RM_CLD_SURF, [LAYER_TRANSPARENT_DECAL] = G_RM_AA_XLU_SURF, [LAYER_TRANSPARENT] = G_RM_AA_XLU_SURF, [LAYER_TRANSPARENT_INTER] = G_RM_AA_XLU_SURF, @@ -111,13 +112,14 @@ struct RenderModeContainer renderModeTable_1Cycle[2] = { [LAYER_OCCLUDE_SILHOUETTE_OPAQUE] = G_RM_AA_ZB_OPA_SURF, [LAYER_OCCLUDE_SILHOUETTE_ALPHA] = G_RM_AA_ZB_TEX_EDGE, #endif + [LAYER_CLD] = G_RM_ZB_CLD_SURF, [LAYER_TRANSPARENT_DECAL] = G_RM_AA_ZB_XLU_DECAL, [LAYER_TRANSPARENT] = G_RM_AA_ZB_XLU_SURF, [LAYER_TRANSPARENT_INTER] = G_RM_AA_ZB_XLU_INTER, } } }; /* Rendermode settings for cycle 2 for all 13 layers. */ -struct RenderModeContainer renderModeTable_2Cycle[2] = { +static const struct RenderModeContainer renderModeTable_2Cycle[2] = { [RENDER_NO_ZB] = { { [LAYER_FORCE] = G_RM_OPA_SURF2, [LAYER_OPAQUE] = G_RM_AA_OPA_SURF2, @@ -131,6 +133,7 @@ struct RenderModeContainer renderModeTable_2Cycle[2] = { [LAYER_OCCLUDE_SILHOUETTE_OPAQUE] = G_RM_AA_OPA_SURF2, [LAYER_OCCLUDE_SILHOUETTE_ALPHA] = G_RM_AA_TEX_EDGE2, #endif + [LAYER_CLD] = G_RM_CLD_SURF2, [LAYER_TRANSPARENT_DECAL] = G_RM_AA_XLU_SURF2, [LAYER_TRANSPARENT] = G_RM_AA_XLU_SURF2, [LAYER_TRANSPARENT_INTER] = G_RM_AA_XLU_SURF2, @@ -148,6 +151,7 @@ struct RenderModeContainer renderModeTable_2Cycle[2] = { [LAYER_OCCLUDE_SILHOUETTE_OPAQUE] = G_RM_AA_ZB_OPA_SURF2, [LAYER_OCCLUDE_SILHOUETTE_ALPHA] = G_RM_AA_ZB_TEX_EDGE2, #endif + [LAYER_CLD] = G_RM_ZB_CLD_SURF2, [LAYER_TRANSPARENT_DECAL] = G_RM_AA_ZB_XLU_DECAL2, [LAYER_TRANSPARENT] = G_RM_AA_ZB_XLU_SURF2, [LAYER_TRANSPARENT_INTER] = G_RM_AA_ZB_XLU_INTER2, @@ -248,6 +252,81 @@ Mtx identityMatrixWorldScale = {{ 0x00000000, LOWER_FIXED(1.0f) << 0} }}; +static void lists_render(Gfx **ptempGfxHead, struct DisplayListNode* currList) { +#define tempGfxHead (*ptempGfxHead) + do { + gSPMatrix(tempGfxHead++, VIRTUAL_TO_PHYSICAL(currList->transform), (G_MTX_MODELVIEW | G_MTX_LOAD | G_MTX_NOPUSH)); + gSPDisplayList(tempGfxHead++, currList->displayList); + currList = currList->next; + } while (currList != NULL); +#undef tempGfxHead +} + +static int batches_render(Gfx **ptempGfxHead, struct BatchArray* arr, u32 mode1, u32 mode2) { +#define tempGfxHead (*ptempGfxHead) + int amountRendered = 0; + + // Some "fun" display lists before may decide to change the render mode so we need to reset it. + // Notably this happens when env effects that change render mode and do not revert it. + gDPSetRenderMode(tempGfxHead++, mode1, mode2); + + for (int batch = 0; batch < arr->count; batch++) { + struct DisplayListLinks* batchLinks = &arr->batches[batch]; + if (!batchLinks->head) + continue; + + const struct BatchDisplayLists* batchDisplayLists = &arr->batchDLs[batch]; + gSPDisplayList(tempGfxHead++, batchDisplayLists->startDl); + amountRendered++; + lists_render(&tempGfxHead, batchLinks->head); + gSPDisplayList(tempGfxHead++, batchDisplayLists->endDl); + } +#undef tempGfxHead + + return amountRendered; +} + +static void main_render(Gfx **ptempGfxHead, struct DisplayListNode* currList, u32 mode1, u32 mode2, int phaseIndex) { +#define tempGfxHead (*ptempGfxHead) +#if defined(DISABLE_AA) || !SILHOUETTE + (void)phaseIndex; + // Set the render mode for the current layer. + gDPSetRenderMode(tempGfxHead++, mode1, mode2); +#else + if (phaseIndex == RENDER_PHASE_NON_SILHOUETTE) { + // To properly cover the silhouette, disable AA. + // The silhouette model does not have AA due to the hack used to prevent triangle overlap. + gDPSetRenderMode(tempGfxHead++, mode1 & ~IM_RD, mode2 & ~IM_RD); + } else { + // Set the render mode for the current dl. + gDPSetRenderMode(tempGfxHead++, mode1, mode2); + } +#endif + // Iterate through all the displaylists on the current layer. + while (currList != NULL) { + // Add the display list's transformation to the master list. + gSPMatrix(tempGfxHead++, VIRTUAL_TO_PHYSICAL(currList->transform), + (G_MTX_MODELVIEW | G_MTX_LOAD | G_MTX_NOPUSH)); +#if SILHOUETTE + if (phaseIndex == RENDER_PHASE_SILHOUETTE) { + // Add the current display list to the master list, with silhouette F3D. + gSPDisplayList(tempGfxHead++, dl_silhouette_begin); + gSPDisplayList(tempGfxHead++, currList->displayList); + gSPDisplayList(tempGfxHead++, dl_silhouette_end); + } else { + // Add the current display list to the master list. + gSPDisplayList(tempGfxHead++, currList->displayList); + } +#else + // Add the current display list to the master list. + gSPDisplayList(tempGfxHead++, currList->displayList); +#endif + // Move to the next DisplayListNode. + currList = currList->next; + } +#undef tempGfxHead +} + /** * Process a master list node. This has been modified, so now it runs twice, for each microcode. * It iterates through the first 5 layers of if the first index using F3DLX2.Rej, then it switches @@ -257,15 +336,14 @@ Mtx identityMatrixWorldScale = {{ */ void geo_process_master_list_sub(struct GraphNodeMasterList *node) { struct RenderPhase *renderPhase; - struct DisplayListNode *currList; s32 currLayer = LAYER_FIRST; s32 startLayer = LAYER_FIRST; s32 endLayer = LAYER_LAST; s32 phaseIndex = RENDER_PHASE_FIRST; s32 enableZBuffer = (node->node.flags & GRAPH_RENDER_Z_BUFFER) != 0; s32 finalPhase = enableZBuffer ? RENDER_PHASE_END : 1; - struct RenderModeContainer *mode1List = &renderModeTable_1Cycle[enableZBuffer]; - struct RenderModeContainer *mode2List = &renderModeTable_2Cycle[enableZBuffer]; + const struct RenderModeContainer *mode1List = &renderModeTable_1Cycle[enableZBuffer]; + const struct RenderModeContainer *mode2List = &renderModeTable_2Cycle[enableZBuffer]; Gfx *tempGfxHead = gDisplayListHead; // Loop through the render phases @@ -284,46 +362,17 @@ void geo_process_master_list_sub(struct GraphNodeMasterList *node) { } // Iterate through the layers on the current render phase. for (currLayer = startLayer; currLayer <= endLayer; currLayer++) { - // Set 'currList' to the first DisplayListNode on the current layer. - currList = node->listHeads[currLayer]; -#if defined(DISABLE_AA) || !SILHOUETTE - // Set the render mode for the current layer. - gDPSetRenderMode(tempGfxHead++, mode1List->modes[currLayer], - mode2List->modes[currLayer]); -#else - if (phaseIndex == RENDER_PHASE_NON_SILHOUETTE) { - // To properly cover the silhouette, disable AA. - // The silhouette model does not have AA due to the hack used to prevent triangle overlap. - gDPSetRenderMode(tempGfxHead++, (mode1List->modes[currLayer] & ~IM_RD), - (mode2List->modes[currLayer] & ~IM_RD)); - } else { - // Set the render mode for the current dl. - gDPSetRenderMode(tempGfxHead++, mode1List->modes[currLayer], - mode2List->modes[currLayer]); - } -#endif - // Iterate through all the displaylists on the current layer. - while (currList != NULL) { - // Add the display list's transformation to the master list. - gSPMatrix(tempGfxHead++, VIRTUAL_TO_PHYSICAL(currList->transform), - (G_MTX_MODELVIEW | G_MTX_LOAD | G_MTX_NOPUSH)); -#if SILHOUETTE - if (phaseIndex == RENDER_PHASE_SILHOUETTE) { - // Add the current display list to the master list, with silhouette F3D. - gSPDisplayList(tempGfxHead++, dl_silhouette_begin); - gSPDisplayList(tempGfxHead++, currList->displayList); - gSPDisplayList(tempGfxHead++, dl_silhouette_end); - } else { - // Add the current display list to the master list. - gSPDisplayList(tempGfxHead++, currList->displayList); - } -#else - // Add the current display list to the master list. - gSPDisplayList(tempGfxHead++, currList->displayList); -#endif - // Move to the next DisplayListNode. - currList = currList->next; - } + struct MasterLayer *masterLayer = &node->layers[currLayer]; + u32 mode1 = mode1List->modes[currLayer]; + u32 mode2 = mode2List->modes[currLayer]; + + struct DisplayListNode *currList = masterLayer->list.head; + if (currList) + main_render(&tempGfxHead, currList, mode1, mode2, phaseIndex); + + struct BatchArray *objects = masterLayer->objects; + if (objects) + batches_render(&tempGfxHead, objects, mode1, mode2); } } @@ -342,16 +391,22 @@ void geo_process_master_list_sub(struct GraphNodeMasterList *node) { gDisplayListHead = tempGfxHead; } -/** - * Appends the display list to one of the master lists based on the layer - * parameter. Look at the RenderModeContainer struct to see the corresponding - * render modes of layers. - */ -void geo_append_display_list(void *displayList, s32 layer) { -#ifdef F3DEX_GBI_2 - gSPLookAt(gDisplayListHead++, gCurLookAt); -#endif +static void append_dl(struct DisplayListLinks* list, void* dl) { + struct DisplayListNode *listNode = alloc_only_pool_alloc(gDisplayListHeap, sizeof(struct DisplayListNode)); + + listNode->transform = gMatStackFixed[gMatStackIndex]; + listNode->displayList = dl; + listNode->next = NULL; + if (list->head == NULL) { + list->head = listNode; + } else { + list->tail->next = listNode; + } + list->tail = listNode; +} + #if SILHOUETTE +static inline int mangle_silhouette_layer(int layer) { if (gCurGraphNodeObject != NULL) { if (gCurGraphNodeObject->node.flags & GRAPH_RENDER_SILHOUETTE) { switch (layer) { @@ -366,21 +421,36 @@ void geo_append_display_list(void *displayList, s32 layer) { } } } -#endif // F3DEX_GBI_2 || SILHOUETTE - if (gCurGraphNodeMasterList != NULL) { - struct DisplayListNode *listNode = - alloc_only_pool_alloc(gDisplayListHeap, sizeof(struct DisplayListNode)); - - listNode->transform = gMatStackFixed[gMatStackIndex]; - listNode->displayList = displayList; - listNode->next = NULL; - if (gCurGraphNodeMasterList->listHeads[layer] == NULL) { - gCurGraphNodeMasterList->listHeads[layer] = listNode; - } else { - gCurGraphNodeMasterList->listTails[layer]->next = listNode; - } - gCurGraphNodeMasterList->listTails[layer] = listNode; - } + + return layer; +} +#else +static inline int mangle_silhouette_layer(int layer) { + return layer; +} +#endif + +/** + * Appends the display list to one of the master lists based on the layer + * parameter. Look at the RenderModeContainer struct to see the corresponding + * render modes of layers. + */ +void geo_append_display_list(void *displayList, s32 layer) { +#ifdef F3DEX_GBI_2 + gSPLookAt(gDisplayListHead++, gCurLookAt); +#endif + layer = mangle_silhouette_layer(layer); + struct MasterLayer* masterLayer = &gCurGraphNodeMasterList->layers[layer]; + append_dl(&masterLayer->list, displayList); +} + +static void geo_append_batched_display_list(void *displayList, enum RenderLayers layer, s32 batch) { +#ifdef F3DEX_GBI_2 + gSPLookAt(gDisplayListHead++, gCurLookAt); +#endif + layer = mangle_silhouette_layer(layer); + struct MasterLayer* masterLayer = &gCurGraphNodeMasterList->layers[layer]; + append_dl(&masterLayer->objects->batches[batch], displayList); } static void inc_mat_stack() { @@ -400,6 +470,15 @@ static void append_dl_and_return(struct GraphNodeDisplayList *node) { gMatStackIndex--; } +static void batches_clean(struct BatchArray* arr) { + if (!arr) + return; + + for (int batch = 0; batch < arr->count; batch++) { + arr->batches[batch].head = NULL; + } +} + /** * Process the master list node. */ @@ -409,7 +488,9 @@ void geo_process_master_list(struct GraphNodeMasterList *node) { if (gCurGraphNodeMasterList == NULL && node->node.children != NULL) { gCurGraphNodeMasterList = node; for (layer = LAYER_FIRST; layer < LAYER_COUNT; layer++) { - node->listHeads[layer] = NULL; + struct MasterLayer* masterLayer = &node->layers[layer]; + masterLayer->list.head = NULL; + batches_clean(masterLayer->objects); } geo_process_node_and_siblings(node->node.children); geo_process_master_list_sub(gCurGraphNodeMasterList); @@ -903,10 +984,15 @@ void geo_process_shadow(struct GraphNodeShadow *node) { gCurrShadow.floorNormal, shadowPos, gCurrShadow.scale, gCurGraphNodeObject->angle[1]); inc_mat_stack(); - geo_append_display_list( - (void *) VIRTUAL_TO_PHYSICAL(shadowList), - gCurrShadow.isDecal ? LAYER_TRANSPARENT_DECAL : LAYER_TRANSPARENT - ); + + s32 layer = gCurrShadow.isDecal ? LAYER_TRANSPARENT_DECAL : LAYER_CLD; + s32 batch; + if (node->shadowType == SHADOW_CIRCLE) { + batch = gCurrShadow.isDecal ? BATCH_TRANSPARENT_DECAL_SHADOW_CIRCLE : BATCH_CLD_SHADOW_CIRCLE; + } else { + batch = gCurrShadow.isDecal ? BATCH_TRANSPARENT_DECAL_SHADOW_SQUARE : BATCH_CLD_SHADOW_SQUARE; + } + geo_append_batched_display_list((void *) VIRTUAL_TO_PHYSICAL(shadowList), layer, batch); gMatStackIndex--; } diff --git a/src/game/segment2.h b/src/game/segment2.h index 239e213958..0ab6867992 100644 --- a/src/game/segment2.h +++ b/src/game/segment2.h @@ -32,6 +32,7 @@ extern Gfx dl_shadow_circle[]; extern Gfx dl_shadow_square[]; extern Gfx dl_shadow_4_verts[]; extern Gfx dl_shadow_end[]; +extern Gfx dl_shadow_tris[]; extern Gfx dl_skybox_begin[]; extern Gfx dl_skybox_tile_tex_settings[]; extern Gfx dl_skybox_end[]; diff --git a/src/game/shadow.c b/src/game/shadow.c index 001b01914e..b405507958 100644 --- a/src/game/shadow.c +++ b/src/game/shadow.c @@ -168,14 +168,9 @@ void correct_lava_shadow_height(f32 *floorHeight) { * shadowType 0 uses a circle texture, the rest use a square texture. * Uses environment alpha for shadow solidity. */ -static void add_shadow_to_display_list(Gfx *displayListHead, s8 shadowType) { - if (shadowType == SHADOW_CIRCLE) { - gSPDisplayList(displayListHead++, dl_shadow_circle); - } else { - gSPDisplayList(displayListHead++, dl_shadow_square); - } - gDPSetEnvColor(displayListHead++, 255, 255, 255, s->solidity); - gSPDisplayList(displayListHead++, dl_shadow_end); +static void add_shadow_to_display_list(Gfx *displayListHead) { + gDPSetPrimColor(displayListHead++, 0, 0, 255, 255, 255, s->solidity); + gSPDisplayList(displayListHead++, dl_shadow_tris); gSPEndDisplayList(displayListHead); } @@ -353,14 +348,14 @@ Gfx *create_shadow_below_xyz(Vec3f pos, s16 shadowScale, u8 shadowSolidity, s8 s } } - Gfx *displayList = alloc_display_list(4 * sizeof(Gfx)); + Gfx *displayList = alloc_display_list(3 * sizeof(Gfx)); if (displayList == NULL) { return NULL; } // Generate the shadow display list with type and solidity. - add_shadow_to_display_list(displayList, shadowType); + add_shadow_to_display_list(displayList); // Move the shadow position to the floor height. pos[1] = floorHeight;