Fix TROR & skyboxes to work with mirrors in Software & Polymost

git-svn-id: https://svn.eduke32.com/eduke32@7733 1a8010ca-5511-0410-912e-c29ae57300e0
This commit is contained in:
pogokeen 2019-06-25 18:35:05 +00:00 committed by Christoph Oelckers
parent 2c85a0a53c
commit cdd83905ca
6 changed files with 80 additions and 49 deletions

View file

@ -1368,6 +1368,8 @@ static int32_t *swplc, *lplc, *swall, *lwall;
static float *swallf;
#endif
uint8_t* mirrorBuffer;
static int32_t smostcnt;
static int32_t smoststart[MAXWALLSB];
static char smostwalltype[MAXWALLSB];
@ -1467,7 +1469,7 @@ int16_t searchsector, searchwall, searchstat; //search output
// When aiming at a 2-sided wall, 1 if aiming at the bottom part, 0 else
int16_t searchbottomwall, searchisbottom;
char inpreparemirror = 0, mirrorrender = 0;
char inpreparemirror = 0;
static int32_t mirrorsx1, mirrorsy1, mirrorsx2, mirrorsy2;
#define MAXSETVIEW 4
@ -8025,8 +8027,6 @@ int32_t renderDrawRoomsQ16(int32_t daposx, int32_t daposy, int32_t daposz,
int32_t i, j, /*cz, fz,*/ closest;
int16_t *shortptr1, *shortptr2;
int32_t didmirror = 0;
beforedrawrooms = 0;
set_globalpos(daposx, daposy, daposz);
@ -8183,7 +8183,7 @@ int32_t renderDrawRoomsQ16(int32_t daposx, int32_t daposy, int32_t daposz,
polymost_drawrooms();
if (videoGetRenderMode() != REND_CLASSIC)
return 0;
return inpreparemirror;
//============================================================================= //POLYMOST ENDS
#endif
@ -8236,16 +8236,14 @@ int32_t renderDrawRoomsQ16(int32_t daposx, int32_t daposy, int32_t daposz,
// INPREPAREMIRROR_NO_BUNCHES
// numbunches==0 can happen if the mirror is far away... the game code decides
// to draw it, but scansector gets zero bunches. Result: big screwup!
// Leave inpreparemirror as is, it's restored by completemirror.
// Set inpreparemirror to 0 to indicate that we were unable to render the mirror
if (numbunches==0)
{
inpreparemirror = 0;
videoEndDrawing(); //!!!
return 0;
}
inpreparemirror = 0;
didmirror = 1;
mirrorsx1 = xdimen-1; mirrorsx2 = 0;
for (i=numscans-1; i>=0; i--)
{
@ -8301,7 +8299,7 @@ int32_t renderDrawRoomsQ16(int32_t daposx, int32_t daposy, int32_t daposz,
videoEndDrawing(); //}}}
return didmirror;
return inpreparemirror;
}
// UTILITY TYPES AND FUNCTIONS FOR DRAWMASKS OCCLUSION TREE
@ -9962,6 +9960,7 @@ static void videoAllocateBuffers(void)
{ (void **)&dotp1, clamped_ydim * sizeof(intptr_t) },
{ (void **)&dotp2, clamped_ydim * sizeof(intptr_t) },
{ (void **)&lastx, clamped_ydim * sizeof(int32_t) },
{ (void **)&mirrorBuffer, (size_t) (xdim * ydim)},
};
for (i = 0; i < (signed)ARRAY_SIZE(dynarray); i++)
@ -11701,7 +11700,6 @@ void squarerotatetile(int16_t tilenume)
void renderPrepareMirror(int32_t dax, int32_t day, fix16_t daang, int16_t dawall,
int32_t *tposx, int32_t *tposy, fix16_t *tang)
{
mirrorrender = 1;
const int32_t x = wall[dawall].x, dx = wall[wall[dawall].point2].x-x;
const int32_t y = wall[dawall].y, dy = wall[wall[dawall].point2].y-y;
@ -11764,15 +11762,15 @@ void renderPrepareMirrorOld(int32_t dax, int32_t day, int32_t daz, fix16_t daang
//
void renderCompleteMirror(void)
{
mirrorrender = 0;
// Don't try to complete a mirror if we haven't drawn the reflection for one
if (!inpreparemirror) { return; }
inpreparemirror = 0;
#ifdef USE_OPENGL
if (videoGetRenderMode() != REND_CLASSIC)
return;
#endif
// Can't reverse when the world has not yet been drawn from the other side.
if (inpreparemirror) { inpreparemirror = 0; return; }
// The mirroring code maps the rightmost pixel to the right neighbor of the
// leftmost one (see copybufreverse() call below). Thus, the leftmost would
// be mapped to the right neighbor of the rightmost one, which would be out
@ -11795,22 +11793,21 @@ void renderCompleteMirror(void)
int const height = mirrorsy2-mirrorsy1;
// Address of the mirror wall's top left corner in the source scene:
intptr_t p = frameplace + ylookup[windowxy1.y+mirrorsy1] + windowxy1.x+mirrorsx1;
intptr_t s = (intptr_t) mirrorBuffer + ylookup[windowxy1.y+mirrorsy1] + windowxy1.x+mirrorsx1;
// Offset (wrt p) of a mirror line's left corner in the destination:
// p+destof == frameplace + ylookup[...] + windowxy2.x-mirrorsx2
int const destofs = windowxy2.x-mirrorsx2-windowxy1.x-mirrorsx1;
// Pointer to the mirror line's left corner in the destination:
intptr_t d = (intptr_t) frameplace + ylookup[windowxy1.y+mirrorsy1] + windowxy2.x-mirrorsx2;
for (bssize_t y=0; y<height; y++)
{
#if 0
if ((p-frameplace) + width-1 >= bytesperline*ydim)
if ((p-mirrorBuffer) + width-1 >= bytesperline*ydim)
printf("oob read: mirrorsx1=%d, mirrorsx2=%d\n", mirrorsx1, mirrorsx2);
#endif
copybufbyte((void *)p, tempbuf, width);
copybufreverse(&tempbuf[width-1], (void *)(p+destofs+1), width);
copybufreverse((void *)(s+width-1), (void *)(d+1), width);
p += ylookup[1];
s += ylookup[1];
d += ylookup[1];
faketimerhandler();
}

View file

@ -209,6 +209,7 @@ extern int16_t thesector[MAXWALLSB], thewall[MAXWALLSB];
extern int16_t bunchfirst[MAXWALLSB], bunchlast[MAXWALLSB];
extern int16_t maskwall[MAXWALLSB], maskwallcnt;
extern tspriteptr_t tspriteptr[MAXSPRITESONSCREEN + 1];
extern uint8_t* mirrorBuffer;
extern int32_t xdimen, xdimenrecip, halfxdimen, xdimenscale, xdimscale, ydimen;
extern float fxdimen;
extern intptr_t frameoffset;
@ -236,7 +237,7 @@ extern int32_t searchx, searchy;
extern int16_t searchsector, searchwall, searchstat;
extern int16_t searchbottomwall, searchisbottom;
extern char inpreparemirror, mirrorrender;
extern char inpreparemirror;
extern char picsiz[MAXTILES];
extern int16_t sectorborder[256];

View file

@ -5505,7 +5505,7 @@ void polymost_drawrooms()
gctang = (gctang > 0.f) ? 1.f : -1.f;
}
if (mirrorrender)
if (inpreparemirror)
gstang = -gstang;
//Generate viewport trapezoid (for handling screen up/down)
@ -5525,7 +5525,7 @@ void polymost_drawrooms()
}
#if !SOFTROTMAT
if (mirrorrender)
if (inpreparemirror)
gstang = -gstang;
#endif
@ -5603,20 +5603,19 @@ void polymost_drawrooms()
grhalfxdown10x = grhalfxdown10;
if (mirrorrender)
grhalfxdown10x = -grhalfxdown10;
if (inpreparemirror)
{
inpreparemirror = 0;
// see engine.c: INPREPAREMIRROR_NO_BUNCHES
if (numbunches > 0)
{
grhalfxdown10x = -grhalfxdown10;
polymost_drawalls(0);
numbunches--;
bunchfirst[0] = bunchfirst[numbunches];
bunchlast[0] = bunchlast[numbunches];
} else
{
inpreparemirror = 0;
}
}

View file

@ -1650,21 +1650,22 @@ void videoBeginDrawing(void)
if (offscreenrendering) return;
if (inpreparemirror)
{
frameplace = (intptr_t)mirrorBuffer;
}
else
#ifdef USE_OPENGL
if (!nogl)
{
frameplace = (intptr_t)glsurface_getBuffer();
if (modechange)
{
bytesperline = xdim;
calc_ylookup(bytesperline, ydim);
modechange=0;
}
return;
}
else
#endif
{
frameplace = (intptr_t)softsurface_getBuffer();
}
frameplace = (intptr_t)softsurface_getBuffer();
if (modechange)
{
bytesperline = xdim;

View file

@ -623,17 +623,44 @@ void G_HandleMirror(int32_t x, int32_t y, int32_t z, fix16_t a, fix16_t q16horiz
int32_t tposx, tposy;
fix16_t tang;
//prepare to render any scripted EVENT_DISPLAYROOMS extras as mirrored
renderPrepareMirror(x, y, a, g_mirrorWall[i], &tposx, &tposy, &tang);
int32_t j = g_visibility;
g_visibility = (j>>1) + (j>>2);
//backup original camera position
int32_t origCamX = CAMERA(pos.x);
int32_t origCamY = CAMERA(pos.y);
int32_t origCamZ = CAMERA(pos.z);
fix16_t origCamq16ang = CAMERA(q16ang);
fix16_t origCamq16horiz = CAMERA(q16horiz);
//set the camera inside the mirror facing out
CAMERA(pos.x) = tposx;
CAMERA(pos.y) = tposy;
CAMERA(pos.z) = z;
CAMERA(q16ang) = tang;
CAMERA(q16horiz) = q16horiz;
display_mirror = 1;
VM_OnEventWithReturn(EVENT_DISPLAYROOMS, g_player[0].ps->i, 0, 0);
display_mirror = 0;
//reset the camera position
CAMERA(pos.x) = origCamX;
CAMERA(pos.y) = origCamY;
CAMERA(pos.z) = origCamZ;
CAMERA(q16ang) = origCamq16ang;
CAMERA(q16horiz) = origCamq16horiz;
//prepare to render the mirror
renderPrepareMirror(x, y, a, g_mirrorWall[i], &tposx, &tposy, &tang);
if (videoGetRenderMode() != REND_POLYMER)
{
int32_t didmirror;
yax_preparedrawrooms();
didmirror = renderDrawRoomsQ16(tposx,tposy,z,tang,q16horiz,g_mirrorSector[i]+MAXSECTORS);
//POGO: if didmirror == 0, we may simply wish to abort instead of rendering with yax_drawrooms (which may require cleaning yax state)
yax_drawrooms(G_DoSpriteAnimations, g_mirrorSector[i], didmirror, smoothratio);
}
#ifdef USE_OPENGL
@ -649,19 +676,22 @@ void G_HandleMirror(int32_t x, int32_t y, int32_t z, fix16_t a, fix16_t q16horiz
renderCompleteMirror(); //Reverse screen x-wise in this function
g_visibility = j;
}
}
}
static void G_ClearGotMirror()
{
#ifdef SPLITSCREEN_MOD_HACKS
if (!g_fakeMultiMode)
if (!g_fakeMultiMode)
#endif
{
// HACK for splitscreen mod: this is so that mirrors will be drawn
// from showview commands. Ugly, because we'll attempt do draw mirrors
// each frame then. But it's better than not drawing them, I guess.
// XXX: fix the sequence of setting/clearing this bit. Right now,
// we always draw one frame without drawing the mirror, after which
// the bit gets set and drawn subsequently.
gotpic[MIRROR>>3] &= ~(1<<(MIRROR&7));
}
{
// HACK for splitscreen mod: this is so that mirrors will be drawn
// from showview commands. Ugly, because we'll attempt do draw mirrors
// each frame then. But it's better than not drawing them, I guess.
// XXX: fix the sequence of setting/clearing this bit. Right now,
// we always draw one frame without drawing the mirror, after which
// the bit gets set and drawn subsequently.
gotpic[MIRROR>>3] &= ~(1<<(MIRROR&7));
}
}
@ -1029,6 +1059,7 @@ void G_DrawRooms(int32_t playerNum, int32_t smoothRatio)
#endif
G_HandleMirror(CAMERA(pos.x), CAMERA(pos.y), CAMERA(pos.z), CAMERA(q16ang), CAMERA(q16horiz), smoothRatio);
G_ClearGotMirror();
#ifdef LEGACY_ROR
G_SE40(smoothRatio);
#endif

View file

@ -1175,6 +1175,7 @@ LUNATIC_EXTERN void G_ShowView(vec3_t vec, fix16_t a, fix16_t horiz, int sect, i
if (g_screenCapture)
return;
//POGOTODO: check if this has anything to do with cameras not rendering the skybox properly
if (offscreenrendering)
{
videoClearViewableArea(0);
@ -1215,7 +1216,8 @@ LUNATIC_EXTERN void G_ShowView(vec3_t vec, fix16_t a, fix16_t horiz, int sect, i
renderSetAspect(viewingRange, yxAspect);
int const smoothratio = calc_smoothratio(totalclock, ototalclock);
G_DoInterpolations(smoothratio);
G_HandleMirror(vec.x, vec.y, vec.z, a, horiz, smoothratio);
if (!display_mirror)
G_HandleMirror(vec.x, vec.y, vec.z, a, horiz, smoothratio);
#ifdef POLYMER
if (videoGetRenderMode() == REND_POLYMER)
polymer_setanimatesprites(G_DoSpriteAnimations, vec.x, vec.y, fix16_to_int(a), smoothratio);