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);