From 8cbdf3a0c4c5c433ac683b81bc76b66ec84c9224 Mon Sep 17 00:00:00 2001 From: pogokeen Date: Tue, 25 Jun 2019 18:35:16 +0000 Subject: [PATCH] Use stencil buffer in Polymost to restrict mirrors to only render within the region of the screen occupied by the mirror wall. Additionally, raise minimum number of stencil buffer bits to accomodate future use of the stencil buffer. git-svn-id: https://svn.eduke32.com/eduke32@7736 1a8010ca-5511-0410-912e-c29ae57300e0 # Conflicts: # source/build/include/build.h # source/build/src/polymer.cpp # source/build/src/polymost.cpp # source/kenbuild/src/game.cpp --- source/build/include/build.h | 4 +- source/build/include/polymost.h | 2 + source/build/src/engine.cpp | 12 ++++- source/build/src/polymost.cpp | 88 ++++++++++++++++++++++++++++++--- source/build/src/sdlayer.cpp | 2 +- source/build/src/sdlayer12.cpp | 2 +- source/build/src/winlayer.cpp | 4 +- source/duke3d/src/game.cpp | 4 +- source/kenbuild/src/game.cpp | 6 +-- source/sw/src/jsector.cpp | 2 +- 10 files changed, 105 insertions(+), 21 deletions(-) diff --git a/source/build/include/build.h b/source/build/include/build.h index 25a285120..18063a9ce 100644 --- a/source/build/include/build.h +++ b/source/build/include/build.h @@ -1104,8 +1104,8 @@ void plotlines2d(const int32_t *xx, const int32_t *yy, int32_t numpoints, int co void plotpixel(int32_t x, int32_t y, char col); void renderSetTarget(int16_t tilenume, int32_t xsiz, int32_t ysiz); void renderRestoreTarget(void); -void renderPrepareMirror(int32_t dax, int32_t day, fix16_t daang, int16_t dawall, - int32_t *tposx, int32_t *tposy, fix16_t *tang); +void renderPrepareMirror(int32_t dax, int32_t day, int32_t daz, fix16_t daang, fix16_t dahoriz, int16_t dawall, + int32_t *tposx, int32_t *tposy, fix16_t *tang); void renderPrepareMirrorOld(int32_t dax, int32_t day, int32_t daz, fix16_t daang, fix16_t dahoriz, int16_t dawall, int16_t dasector, int32_t *tposx, int32_t *tposy, fix16_t *tang); void renderCompleteMirror(void); diff --git a/source/build/include/polymost.h b/source/build/include/polymost.h index 54042898a..d68561b7e 100644 --- a/source/build/include/polymost.h +++ b/source/build/include/polymost.h @@ -49,6 +49,8 @@ void polymost_dorotatesprite(int32_t sx, int32_t sy, int32_t z, int16_t a, int16 void polymost_fillpolygon(int32_t npoints); void polymost_initosdfuncs(void); void polymost_drawrooms(void); +void polymost_prepareMirror(int32_t dax, int32_t day, int32_t daz, fix16_t daang, fix16_t dahoriz, int16_t mirrorWall); +void polymost_completeMirror(); int32_t polymost_maskWallHasTranslucency(uwalltype const * const wall); int32_t polymost_spriteHasTranslucency(uspritetype const * const tspr); diff --git a/source/build/src/engine.cpp b/source/build/src/engine.cpp index 157076653..fdc038cac 100644 --- a/source/build/src/engine.cpp +++ b/source/build/src/engine.cpp @@ -11697,7 +11697,7 @@ void squarerotatetile(int16_t tilenume) // // preparemirror // -void renderPrepareMirror(int32_t dax, int32_t day, fix16_t daang, int16_t dawall, +void renderPrepareMirror(int32_t dax, int32_t day, int32_t daz, fix16_t daang, fix16_t dahoriz, int16_t dawall, int32_t *tposx, int32_t *tposy, fix16_t *tang) { const int32_t x = wall[dawall].x, dx = wall[wall[dawall].point2].x-x; @@ -11714,6 +11714,11 @@ void renderPrepareMirror(int32_t dax, int32_t day, fix16_t daang, int16_t dawall *tang = (fix16_from_int(getangle(dx, dy) << 1) - daang) & 0x7FFFFFF; inpreparemirror = 1; + +#ifdef USE_OPENGL + if (videoGetRenderMode() != REND_CLASSIC) + polymost_prepareMirror(dax, day, daz, daang, dahoriz, dawall); +#endif } static int32_t mirthoriz, mirbakdaz; @@ -11762,6 +11767,11 @@ void renderPrepareMirrorOld(int32_t dax, int32_t day, int32_t daz, fix16_t daang // void renderCompleteMirror(void) { +#ifdef USE_OPENGL + if (videoGetRenderMode() != REND_CLASSIC) + polymost_completeMirror(); +#endif + // Don't try to complete a mirror if we haven't drawn the reflection for one if (!inpreparemirror) { return; } inpreparemirror = 0; diff --git a/source/build/src/polymost.cpp b/source/build/src/polymost.cpp index bd0762986..7f8fab6a9 100644 --- a/source/build/src/polymost.cpp +++ b/source/build/src/polymost.cpp @@ -5659,12 +5659,11 @@ void polymost_drawrooms() videoEndDrawing(); } -void polymost_drawmaskwall(int32_t damaskwallcnt) +static void polymost_drawmaskwallinternal(int32_t wallIndex) { - int const z = maskwall[damaskwallcnt]; - auto const wal = (uwalltype *)&wall[thewall[z]]; - auto const wal2 = (uwalltype *)&wall[wal->point2]; - int32_t const sectnum = thesector[z]; + auto const wal = (uwallptr_t)&wall[wallIndex]; + auto const wal2 = (uwallptr_t)&wall[wal->point2]; + int32_t const sectnum = wall[wal->nextwall].nextsector; auto const sec = (usectortype *)§or[sectnum]; // if (wal->nextsector < 0) return; @@ -5673,14 +5672,14 @@ void polymost_drawmaskwall(int32_t damaskwallcnt) auto const nsec = (usectortype *)§or[wal->nextsector]; - polymost_outputGLDebugMessage(3, "polymost_drawmaskwall(damaskwallcnt:%d)", damaskwallcnt); + polymost_outputGLDebugMessage(3, "polymost_drawmaskwallinternal(wallIndex:%d)", wallIndex); globalpicnum = wal->overpicnum; if ((uint32_t)globalpicnum >= MAXTILES) globalpicnum = 0; globalorientation = (int32_t)wal->cstat; - tileUpdatePicnum(&globalpicnum, (int16_t)thewall[z]+16384); + tileUpdatePicnum(&globalpicnum, (int16_t)wallIndex+16384); globvis = globalvisibility; globvis = (sector[sectnum].visibility != 0) ? mulscale4(globvis, (uint8_t)(sector[sectnum].visibility + 16)) : globalvisibility; @@ -5772,7 +5771,7 @@ void polymost_drawmaskwall(int32_t damaskwallcnt) #ifdef NEW_MAP_FORMAT uint8_t const blend = wal->blend; #else - uint8_t const blend = wallext[thewall[z]].blend; + uint8_t const blend = wallext[wallIndex].blend; #endif handle_blend(!!(wal->cstat & 128), blend, !!(wal->cstat & 512)); @@ -5871,6 +5870,79 @@ void polymost_drawmaskwall(int32_t damaskwallcnt) polymost_identityrotmat(); } +void polymost_drawmaskwall(int32_t damaskwallcnt) +{ + int const z = maskwall[damaskwallcnt]; + polymost_drawmaskwallinternal(thewall[z]); +} + +void polymost_prepareMirror(int32_t dax, int32_t day, int32_t daz, fix16_t daang, fix16_t dahoriz, int16_t mirrorWall) +{ + polymost_outputGLDebugMessage(3, "polymost_prepareMirror(%u)", mirrorWall); + + //POGO: prepare necessary globals for drawing, as we intend to call this outside of drawrooms + set_globalpos(dax, day, daz); + set_globalang(daang); + globalhoriz = mulscale16(fix16_to_int(dahoriz)-100,divscale16(xdimenscale,viewingrange))+(ydimen>>1); + qglobalhoriz = mulscale16(dahoriz-F16(100), divscale16(xdimenscale, viewingrange))+fix16_from_int(ydimen>>1); + gyxscale = ((float)xdimenscale)*(1.0f/131072.f); + gxyaspect = ((double)xyaspect*fviewingrange)*(5.0/(65536.0*262144.0)); + gviewxrange = fviewingrange * fxdimen * (1.f/(32768.f*1024.f)); + gcosang = fcosglobalang*(1.0f/262144.f); + gsinang = fsinglobalang*(1.0f/262144.f); + gcosang2 = gcosang * (fviewingrange * (1.0f/65536.f)); + gsinang2 = gsinang * (fviewingrange * (1.0f/65536.f)); + ghalfx = (float)(xdimen>>1); + ghalfy = (float)(ydimen>>1); + grhalfxdown10 = 1.f/(ghalfx*1024.f); + ghoriz = fix16_to_float(qglobalhoriz); + gvisibility = ((float)globalvisibility)*FOGSCALE; + resizeglcheck(); + if (r_yshearing) + { + gshang = 0.f; + gchang = 1.f; + ghoriz2 = (float)(ydimen >> 1) - ghoriz; + } + else + { + float r = (float)(ydimen >> 1) - ghoriz; + gshang = r / Bsqrtf(r * r + ghalfx * ghalfx); + gchang = Bsqrtf(1.f - gshang * gshang); + ghoriz2 = 0.f; + } + ghoriz = (float)(ydimen>>1); + gctang = cosf(gtang); + gstang = sinf(gtang); + if (Bfabsf(gstang) < .001f) + { + gstang = 0.f; + gctang = (gctang > 0.f) ? 1.f : -1.f; + } + grhalfxdown10x = grhalfxdown10; + + //POGO: write the mirror region to the stencil buffer to allow showing mirrors & skyboxes at the same time + glEnable(GL_STENCIL_TEST); + glClear(GL_STENCIL_BUFFER_BIT); + glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE); + glStencilFunc(GL_ALWAYS, 1, 0xFF); + glDisable(GL_ALPHA_TEST); + glDisable(GL_DEPTH_TEST); + polymost_drawmaskwallinternal(mirrorWall); + glEnable(GL_ALPHA_TEST); + glEnable(GL_DEPTH_TEST); + + //POGO: render only to the mirror region + glStencilFunc(GL_EQUAL, 1, 0xFF); + glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); +} + +void polymost_completeMirror() +{ + polymost_outputGLDebugMessage(3, "polymost_completeMirror()"); + glDisable(GL_STENCIL_TEST); +} + typedef struct { uint32_t wrev; diff --git a/source/build/src/sdlayer.cpp b/source/build/src/sdlayer.cpp index ea854b90a..8d50dac42 100644 --- a/source/build/src/sdlayer.cpp +++ b/source/build/src/sdlayer.cpp @@ -1545,7 +1545,7 @@ int32_t videoSetMode(int32_t x, int32_t y, int32_t c, int32_t fs) { SDL_GL_MULTISAMPLEBUFFERS, glmultisample > 0 }, { SDL_GL_MULTISAMPLESAMPLES, glmultisample }, #endif - { SDL_GL_STENCIL_SIZE, 1 }, + { SDL_GL_STENCIL_SIZE, 8 }, { SDL_GL_ACCELERATED_VISUAL, 1 }, }; diff --git a/source/build/src/sdlayer12.cpp b/source/build/src/sdlayer12.cpp index 73bed584d..e2db358da 100644 --- a/source/build/src/sdlayer12.cpp +++ b/source/build/src/sdlayer12.cpp @@ -364,7 +364,7 @@ int32_t videoSetMode(int32_t x, int32_t y, int32_t c, int32_t fs) { SDL_GL_DOUBLEBUFFER, 1 }, { SDL_GL_MULTISAMPLEBUFFERS, glmultisample > 0 }, { SDL_GL_MULTISAMPLESAMPLES, glmultisample }, - { SDL_GL_STENCIL_SIZE, 1 }, + { SDL_GL_STENCIL_SIZE, 8 }, { SDL_GL_ACCELERATED_VISUAL, 1 }, { SDL_GL_SWAP_CONTROL, vsync_renderlayer }, }; diff --git a/source/build/src/winlayer.cpp b/source/build/src/winlayer.cpp index 81b22ce26..6500d4fa6 100644 --- a/source/build/src/winlayer.cpp +++ b/source/build/src/winlayer.cpp @@ -2623,8 +2623,8 @@ static int32_t SetupOpenGL(int32_t width, int32_t height, int32_t bitspp) 0, //Shift Bit Ignored 0, //No Accumulation Buffer 0,0,0,0, //Accumulation Bits Ignored - 32, //16/24/32 Z-Buffer depth - 1, //No Stencil Buffer + 24, //16/24/32 Z-Buffer depth + 8, //8-bit Stencil Buffer 0, //No Auxiliary Buffer PFD_MAIN_PLANE, //Main Drawing Layer 0, //Reserved diff --git a/source/duke3d/src/game.cpp b/source/duke3d/src/game.cpp index 031b57867..d69745e2a 100644 --- a/source/duke3d/src/game.cpp +++ b/source/duke3d/src/game.cpp @@ -628,7 +628,7 @@ void G_HandleMirror(int32_t x, int32_t y, int32_t z, fix16_t a, fix16_t q16horiz fix16_t tang; //prepare to render any scripted EVENT_DISPLAYROOMS extras as mirrored - renderPrepareMirror(x, y, a, g_mirrorWall[i], &tposx, &tposy, &tang); + renderPrepareMirror(x, y, z, a, q16horiz, g_mirrorWall[i], &tposx, &tposy, &tang); int32_t j = g_visibility; g_visibility = (j>>1) + (j>>2); @@ -660,7 +660,7 @@ void G_HandleMirror(int32_t x, int32_t y, int32_t z, fix16_t a, fix16_t q16horiz VM_OnEvent(EVENT_RESETGOTPICS, -1, -1); //prepare to render the mirror - renderPrepareMirror(x, y, a, g_mirrorWall[i], &tposx, &tposy, &tang); + renderPrepareMirror(x, y, z, a, q16horiz, g_mirrorWall[i], &tposx, &tposy, &tang); if (videoGetRenderMode() != REND_POLYMER) { diff --git a/source/kenbuild/src/game.cpp b/source/kenbuild/src/game.cpp index e1df21666..95212d58b 100644 --- a/source/kenbuild/src/game.cpp +++ b/source/kenbuild/src/game.cpp @@ -4019,9 +4019,9 @@ void drawscreen(short snum, int dasmoothratio) //Prepare drawrooms for drawing mirror and calculate reflected //position into tposx, tposy, and tang (tpos.z == cpos.z) - //Must call preparemirror before drawrooms and - // completemirror after drawrooms - preparemirror(cpos.x,cpos.y,/*cpos.z,*/ cang, /*choriz,*/ + //Must call renderPrepareMirror before drawrooms and + // renderCompleteMirror after drawrooms + renderPrepareMirror(cpos.x,cpos.y,cpos.z,fix16_from_int(cang),choriz, mirrorwall[i],/*mirrorsector[i],*/ &tposx,&tposy,&tang); ovisibility = g_visibility; diff --git a/source/sw/src/jsector.cpp b/source/sw/src/jsector.cpp index 20bd01d73..1a337e2ef 100644 --- a/source/sw/src/jsector.cpp +++ b/source/sw/src/jsector.cpp @@ -889,7 +889,7 @@ JS_DrawMirrors(PLAYERp pp, int tx, int ty, int tz, short tpang, int tphoriz) // Must call preparemirror before drawrooms and // completemirror after drawrooms - renderPrepareMirror(tx, ty, /*tz,*/ fix16_from_int(tpang), /*tphoriz,*/ + renderPrepareMirror(tx, ty, tz, fix16_from_int(tpang), tphoriz, mirror[cnt].mirrorwall, /*mirror[cnt].mirrorsector,*/ &tposx, &tposy, &tang); drawrooms(tposx, tposy, tz, fix16_to_int(tang), tphoriz, mirror[cnt].mirrorsector + MAXSECTORS);