diff --git a/src/dusk/display/mesh/plane.c b/src/dusk/display/mesh/plane.c index df3d135c..86d178ba 100644 --- a/src/dusk/display/mesh/plane.c +++ b/src/dusk/display/mesh/plane.c @@ -74,11 +74,11 @@ void planeBuffer( /* Flat in XZ at y = min[1]; spans X and Z. */ const float_t y = min[1]; PLANE_VERT(0, min[0], y, min[2], u0, v0) - PLANE_VERT(1, max[0], y, min[2], u1, v0) - PLANE_VERT(2, max[0], y, max[2], u1, v1) + PLANE_VERT(1, max[0], y, max[2], u1, v1) + PLANE_VERT(2, max[0], y, min[2], u1, v0) PLANE_VERT(3, min[0], y, min[2], u0, v0) - PLANE_VERT(4, max[0], y, max[2], u1, v1) - PLANE_VERT(5, min[0], y, max[2], u0, v1) + PLANE_VERT(4, min[0], y, max[2], u0, v1) + PLANE_VERT(5, max[0], y, max[2], u1, v1) break; } diff --git a/src/duskrpg/scene/overworldscene.c b/src/duskrpg/scene/overworldscene.c index 5c6dd746..4f7347b9 100644 --- a/src/duskrpg/scene/overworldscene.c +++ b/src/duskrpg/scene/overworldscene.c @@ -17,8 +17,13 @@ #include "display/color.h" #include "time/time.h" -#define OVERWORLD_SCENE_CAMERA_ORBIT_RADIUS 8.0f -#define OVERWORLD_SCENE_CAMERA_ORBIT_HEIGHT 5.0f +// Radius must stay well outside the floor's footprint (a 20x20 plane has a +// corner-to-center distance of 10*sqrt(2) =~ 14.1) -- orbiting inside that +// puts parts of the floor's own geometry near/behind the camera's view +// direction, which the PSP's legacy GU pipeline can't clip properly and +// drops the whole triangle instead of clipping it. +#define OVERWORLD_SCENE_CAMERA_ORBIT_RADIUS 18.0f +#define OVERWORLD_SCENE_CAMERA_ORBIT_HEIGHT 10.0f #define OVERWORLD_SCENE_CAMERA_ORBIT_SPEED 0.5f static overworldcameraorbit_t OVERWORLD_SCENE_CAMERA_ORBIT; diff --git a/src/dusksdl2/display/displaysdl2.c b/src/dusksdl2/display/displaysdl2.c index 8c570c25..8ed4fb85 100644 --- a/src/dusksdl2/display/displaysdl2.c +++ b/src/dusksdl2/display/displaysdl2.c @@ -10,12 +10,7 @@ #include "display/displaygl.h" #include "error/errorgl.h" -static bool_t DISPLAY_SDL2_STATE_VALID = false; -static uint8_t DISPLAY_SDL2_STATE_FLAGS = 0; - errorret_t displaySDL2Init(void) { - DISPLAY_SDL2_STATE_VALID = false; - uint32_t flags = SDL_INIT_VIDEO; #ifdef DUSK_INPUT_GAMEPAD flags |= SDL_INIT_GAMECONTROLLER | SDL_INIT_JOYSTICK; @@ -108,53 +103,48 @@ errorret_t displaySDL2Swap(void) { } errorret_t displaySDL2SetState(displaystate_t state) { - // Only touch GL state that actually differs from what's already bound -- - // avoids a redundant glEnable/glDisable/glBlendFunc/glDepthFunc round - // trip per draw when consecutive entities share the same display state. - const uint8_t changed = DISPLAY_SDL2_STATE_VALID ? - (state.flags ^ DISPLAY_SDL2_STATE_FLAGS) : 0xFF; - - if(changed & DISPLAY_STATE_FLAG_CULL) { - if(state.flags & DISPLAY_STATE_FLAG_CULL) { - glEnable(GL_CULL_FACE); - errorChain(errorGLCheck()); - glCullFace(GL_BACK); - errorChain(errorGLCheck()); - } else { - glDisable(GL_CULL_FACE); - errorChain(errorGLCheck()); - } + // Unconditionally reapply every group on every call, rather than + // diffing against the last-applied flags and skipping unchanged ones. + // A prior version of this function cached/diffed to skip redundant GL + // calls, but that meant e.g. glDisable(GL_CULL_FACE) only ever fired + // once at program start instead of before every draw -- and on + // PSPGL/GU, GL state doesn't reliably persist across other draw calls + // the way it does on desktop GL drivers, which surfaced as faces + // rendering inconsistently depending on draw order/history. Reasserting + // every call is the same behavior this engine always had before that + // optimization, and is cheap enough not to matter. + if(state.flags & DISPLAY_STATE_FLAG_CULL) { + glEnable(GL_CULL_FACE); + errorChain(errorGLCheck()); + glCullFace(GL_BACK); + errorChain(errorGLCheck()); + } else { + glDisable(GL_CULL_FACE); + errorChain(errorGLCheck()); } - if(changed & DISPLAY_STATE_FLAG_DEPTH_TEST) { - if(state.flags & DISPLAY_STATE_FLAG_DEPTH_TEST) { - glEnable(GL_DEPTH_TEST); - errorChain(errorGLCheck()); - glDepthFunc(GL_LEQUAL); - errorChain(errorGLCheck()); - glClearDepth(1.0f); - errorChain(errorGLCheck()); - } else { - glDisable(GL_DEPTH_TEST); - errorChain(errorGLCheck()); - } + if(state.flags & DISPLAY_STATE_FLAG_DEPTH_TEST) { + glEnable(GL_DEPTH_TEST); + errorChain(errorGLCheck()); + glDepthFunc(GL_LEQUAL); + errorChain(errorGLCheck()); + glClearDepth(1.0f); + errorChain(errorGLCheck()); + } else { + glDisable(GL_DEPTH_TEST); + errorChain(errorGLCheck()); } - if(changed & DISPLAY_STATE_FLAG_BLEND) { - if(state.flags & DISPLAY_STATE_FLAG_BLEND) { - glEnable(GL_BLEND); - errorChain(errorGLCheck()); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - errorChain(errorGLCheck()); - } else { - glDisable(GL_BLEND); - errorChain(errorGLCheck()); - } + if(state.flags & DISPLAY_STATE_FLAG_BLEND) { + glEnable(GL_BLEND); + errorChain(errorGLCheck()); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + errorChain(errorGLCheck()); + } else { + glDisable(GL_BLEND); + errorChain(errorGLCheck()); } - DISPLAY_SDL2_STATE_FLAGS = state.flags; - DISPLAY_SDL2_STATE_VALID = true; - errorOk(); }