mirror of
https://github.com/ZDoom/qzdoom.git
synced 2024-11-10 14:51:51 +00:00
- Removed the screenshot parameter from D_Display(), since it was a relic of
a long-abandoned experiment to write directly to video memory instead of to a temporary buffer in system meroy. - Added Direct3D versions of the melt and burn screenwipes. - Fixed the strip sizes for the melt screenwipe to match what Doom would have produced on a 320x200 screen, rather than producing more, thinner strips for wider screens. SVN r659 (trunk)
This commit is contained in:
parent
db54c43175
commit
dc98279403
11 changed files with 1580 additions and 1116 deletions
|
@ -1,3 +1,12 @@
|
||||||
|
December 31, 2007
|
||||||
|
- Removed the screenshot parameter from D_Display(), since it was a relic of
|
||||||
|
a long-abandoned experiment to write directly to video memory instead of
|
||||||
|
to a temporary buffer in system meroy.
|
||||||
|
- Added Direct3D versions of the melt and burn screenwipes.
|
||||||
|
- Fixed the strip sizes for the melt screenwipe to match what Doom would have
|
||||||
|
produced on a 320x200 screen, rather than producing more, thinner strips
|
||||||
|
for wider screens.
|
||||||
|
|
||||||
December 29, 2007
|
December 29, 2007
|
||||||
- Started writing Direct3D-friendly wipe code. It's just a Q&D crossfade for
|
- Started writing Direct3D-friendly wipe code. It's just a Q&D crossfade for
|
||||||
now.
|
now.
|
||||||
|
|
|
@ -228,7 +228,8 @@ CUSTOM_CVAR (Int, msgmidcolor2, 4, CVAR_ARCHIVE)
|
||||||
|
|
||||||
static void maybedrawnow (bool tick, bool force)
|
static void maybedrawnow (bool tick, bool force)
|
||||||
{
|
{
|
||||||
if (ConsoleDrawing || !gotconback || screen->IsLocked ())
|
// FIXME: Does not work right with hw2d
|
||||||
|
if (ConsoleDrawing || !gotconback || screen->IsLocked () || 1)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -438,7 +438,7 @@ CVAR (Flag, compat_invisibility,compatflags, COMPATF_INVISIBILITY);
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
void D_Display (bool screenshot)
|
void D_Display ()
|
||||||
{
|
{
|
||||||
bool wipe;
|
bool wipe;
|
||||||
bool hw2d;
|
bool hw2d;
|
||||||
|
@ -489,7 +489,7 @@ void D_Display (bool screenshot)
|
||||||
}
|
}
|
||||||
setmodeneeded = false;
|
setmodeneeded = false;
|
||||||
|
|
||||||
if (screen->Lock (screenshot))
|
if (screen->Lock (false))
|
||||||
{
|
{
|
||||||
SB_state = screen->GetPageCount ();
|
SB_state = screen->GetPageCount ();
|
||||||
BorderNeedRefresh = screen->GetPageCount ();
|
BorderNeedRefresh = screen->GetPageCount ();
|
||||||
|
@ -506,7 +506,6 @@ void D_Display (bool screenshot)
|
||||||
else if (gamestate != wipegamestate && gamestate != GS_FULLCONSOLE && gamestate != GS_TITLELEVEL)
|
else if (gamestate != wipegamestate && gamestate != GS_FULLCONSOLE && gamestate != GS_TITLELEVEL)
|
||||||
{ // save the current screen if about to wipe
|
{ // save the current screen if about to wipe
|
||||||
BorderNeedRefresh = screen->GetPageCount ();
|
BorderNeedRefresh = screen->GetPageCount ();
|
||||||
wipe = true;
|
|
||||||
if (wipegamestate != GS_FORCEWIPEFADE)
|
if (wipegamestate != GS_FORCEWIPEFADE)
|
||||||
{
|
{
|
||||||
wipe = screen->WipeStartScreen (wipetype);
|
wipe = screen->WipeStartScreen (wipetype);
|
||||||
|
@ -536,14 +535,10 @@ void D_Display (bool screenshot)
|
||||||
{
|
{
|
||||||
case GS_FULLCONSOLE:
|
case GS_FULLCONSOLE:
|
||||||
screen->SetBlendingRect(0,0,0,0);
|
screen->SetBlendingRect(0,0,0,0);
|
||||||
if (!screenshot)
|
hw2d = screen->Begin2D();
|
||||||
{
|
|
||||||
hw2d = screen->Begin2D();
|
|
||||||
}
|
|
||||||
C_DrawConsole (false);
|
C_DrawConsole (false);
|
||||||
M_Drawer ();
|
M_Drawer ();
|
||||||
if (!screenshot)
|
screen->Update ();
|
||||||
screen->Update ();
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case GS_LEVEL:
|
case GS_LEVEL:
|
||||||
|
@ -573,13 +568,10 @@ void D_Display (bool screenshot)
|
||||||
{
|
{
|
||||||
AM_Drawer ();
|
AM_Drawer ();
|
||||||
}
|
}
|
||||||
if (!screenshot)
|
if ((hw2d = screen->Begin2D()))
|
||||||
{
|
{
|
||||||
if ((hw2d = screen->Begin2D()))
|
// Redraw the status bar every frame when using 2D accel
|
||||||
{
|
SB_state = screen->GetPageCount();
|
||||||
// Redraw the status bar every frame when using 2D accel
|
|
||||||
SB_state = screen->GetPageCount();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (realviewheight == SCREENHEIGHT && viewactive)
|
if (realviewheight == SCREENHEIGHT && viewactive)
|
||||||
{
|
{
|
||||||
|
@ -596,30 +588,21 @@ void D_Display (bool screenshot)
|
||||||
|
|
||||||
case GS_INTERMISSION:
|
case GS_INTERMISSION:
|
||||||
screen->SetBlendingRect(0,0,0,0);
|
screen->SetBlendingRect(0,0,0,0);
|
||||||
if (!screenshot)
|
hw2d = screen->Begin2D();
|
||||||
{
|
|
||||||
screen->Begin2D();
|
|
||||||
}
|
|
||||||
WI_Drawer ();
|
WI_Drawer ();
|
||||||
CT_Drawer ();
|
CT_Drawer ();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case GS_FINALE:
|
case GS_FINALE:
|
||||||
screen->SetBlendingRect(0,0,0,0);
|
screen->SetBlendingRect(0,0,0,0);
|
||||||
if (!screenshot)
|
hw2d = screen->Begin2D();
|
||||||
{
|
|
||||||
screen->Begin2D();
|
|
||||||
}
|
|
||||||
F_Drawer ();
|
F_Drawer ();
|
||||||
CT_Drawer ();
|
CT_Drawer ();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case GS_DEMOSCREEN:
|
case GS_DEMOSCREEN:
|
||||||
screen->SetBlendingRect(0,0,0,0);
|
screen->SetBlendingRect(0,0,0,0);
|
||||||
if (!screenshot)
|
hw2d = screen->Begin2D();
|
||||||
{
|
|
||||||
screen->Begin2D();
|
|
||||||
}
|
|
||||||
D_PageDrawer ();
|
D_PageDrawer ();
|
||||||
CT_Drawer ();
|
CT_Drawer ();
|
||||||
break;
|
break;
|
||||||
|
@ -655,17 +638,14 @@ void D_Display (bool screenshot)
|
||||||
NoWipe = 10;
|
NoWipe = 10;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!wipe || screenshot || NoWipe < 0)
|
if (!wipe || NoWipe < 0)
|
||||||
{
|
{
|
||||||
NetUpdate (); // send out any new accumulation
|
NetUpdate (); // send out any new accumulation
|
||||||
// normal update
|
// normal update
|
||||||
C_DrawConsole (hw2d); // draw console
|
C_DrawConsole (hw2d); // draw console
|
||||||
M_Drawer (); // menu is drawn even on top of everything
|
M_Drawer (); // menu is drawn even on top of everything
|
||||||
FStat::PrintStat ();
|
FStat::PrintStat ();
|
||||||
if (!screenshot)
|
screen->Update (); // page flip or blit buffer
|
||||||
{
|
|
||||||
screen->Update (); // page flip or blit buffer
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -792,7 +772,7 @@ void D_DoomLoop ()
|
||||||
S_UpdateSounds (players[consoleplayer].camera); // move positional sounds
|
S_UpdateSounds (players[consoleplayer].camera); // move positional sounds
|
||||||
// Update display, next frame, with current state.
|
// Update display, next frame, with current state.
|
||||||
I_StartTic ();
|
I_StartTic ();
|
||||||
D_Display (false);
|
D_Display ();
|
||||||
}
|
}
|
||||||
catch (CRecoverableError &error)
|
catch (CRecoverableError &error)
|
||||||
{
|
{
|
||||||
|
|
|
@ -38,8 +38,7 @@ void D_DoomMain (void);
|
||||||
// Called by IO functions when input is detected.
|
// Called by IO functions when input is detected.
|
||||||
void D_PostEvent (const event_t* ev);
|
void D_PostEvent (const event_t* ev);
|
||||||
|
|
||||||
// [RH] Passed true if just drawing for a screenshot
|
void D_Display ();
|
||||||
void D_Display (bool screenshot);
|
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|
329
src/f_wipe.cpp
329
src/f_wipe.cpp
|
@ -53,6 +53,10 @@ static int fade;
|
||||||
|
|
||||||
// Melt -------------------------------------------------------------
|
// Melt -------------------------------------------------------------
|
||||||
|
|
||||||
|
// Match the strip sizes that oldschool Doom used on a 320x200 screen.
|
||||||
|
#define MELT_WIDTH 160
|
||||||
|
#define MELT_HEIGHT 200
|
||||||
|
|
||||||
void wipe_shittyColMajorXform (short *array)
|
void wipe_shittyColMajorXform (short *array)
|
||||||
{
|
{
|
||||||
int x, y;
|
int x, y;
|
||||||
|
@ -84,14 +88,12 @@ bool wipe_initMelt (int ticks)
|
||||||
|
|
||||||
// setup initial column positions
|
// setup initial column positions
|
||||||
// (y<0 => not ready to scroll yet)
|
// (y<0 => not ready to scroll yet)
|
||||||
y = new int[SCREENWIDTH*sizeof(int)];
|
y = new int[MELT_WIDTH];
|
||||||
y[0] = -(M_Random()&0xf);
|
y[0] = -(M_Random() & 15);
|
||||||
for (i = 1; i < SCREENWIDTH; i++)
|
for (i = 1; i < MELT_WIDTH; i++)
|
||||||
{
|
{
|
||||||
r = (M_Random()%3) - 1;
|
r = (M_Random()%3) - 1;
|
||||||
y[i] = y[i-1] + r;
|
y[i] = clamp(y[i-1] + r, -15, 0);
|
||||||
if (y[i] > 0) y[i] = 0;
|
|
||||||
else if (y[i] == -16) y[i] = -15;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -99,51 +101,52 @@ bool wipe_initMelt (int ticks)
|
||||||
|
|
||||||
bool wipe_doMelt (int ticks)
|
bool wipe_doMelt (int ticks)
|
||||||
{
|
{
|
||||||
int i;
|
int i, j, dy, x;
|
||||||
int j;
|
const short *s;
|
||||||
int dy;
|
short *d;
|
||||||
int idx;
|
bool done;
|
||||||
|
|
||||||
short* s;
|
|
||||||
short* d;
|
|
||||||
bool done = true;
|
|
||||||
|
|
||||||
int width = SCREENWIDTH / 2;
|
|
||||||
|
|
||||||
while (ticks--)
|
while (ticks--)
|
||||||
{
|
{
|
||||||
for (i = 0; i < width; i++)
|
done = true;
|
||||||
|
for (i = 0; i < MELT_WIDTH; i++)
|
||||||
{
|
{
|
||||||
if (y[i] < 0)
|
if (y[i] < 0)
|
||||||
{
|
{
|
||||||
y[i]++; done = false;
|
y[i]++;
|
||||||
}
|
|
||||||
else if (y[i] < SCREENHEIGHT)
|
|
||||||
{
|
|
||||||
int pitch = screen->GetPitch() / 2;
|
|
||||||
dy = (y[i] < 16) ? y[i]+1 : 8;
|
|
||||||
dy = (dy * SCREENHEIGHT) / 200;
|
|
||||||
if (y[i]+dy >= SCREENHEIGHT)
|
|
||||||
dy = SCREENHEIGHT - y[i];
|
|
||||||
s = &wipe_scr_end[i*SCREENHEIGHT+y[i]];
|
|
||||||
d = &((short *)screen->GetBuffer())[y[i]*pitch+i];
|
|
||||||
idx = 0;
|
|
||||||
for (j=dy;j;j--)
|
|
||||||
{
|
|
||||||
d[idx] = *(s++);
|
|
||||||
idx += pitch;
|
|
||||||
}
|
|
||||||
y[i] += dy;
|
|
||||||
s = &wipe_scr_start[i*SCREENHEIGHT];
|
|
||||||
d = &((short *)screen->GetBuffer())[y[i]*pitch+i];
|
|
||||||
idx = 0;
|
|
||||||
for (j=SCREENHEIGHT-y[i];j;j--)
|
|
||||||
{
|
|
||||||
d[idx] = *(s++);
|
|
||||||
idx += pitch;
|
|
||||||
}
|
|
||||||
done = false;
|
done = false;
|
||||||
}
|
}
|
||||||
|
else if (y[i] < MELT_HEIGHT)
|
||||||
|
{
|
||||||
|
dy = (y[i] < 16) ? y[i]+1 : 8;
|
||||||
|
y[i] = MIN(y[i] + dy, MELT_HEIGHT);
|
||||||
|
done = false;
|
||||||
|
}
|
||||||
|
if (ticks == 0 && y[i] >= 0)
|
||||||
|
{ // Only draw for the final tick.
|
||||||
|
const int pitch = screen->GetPitch() / 2;
|
||||||
|
int sy = y[i] * SCREENHEIGHT / MELT_HEIGHT;
|
||||||
|
|
||||||
|
for (x = i * (SCREENWIDTH/2) / MELT_WIDTH; x < (i + 1) * (SCREENWIDTH/2) / MELT_WIDTH; ++x)
|
||||||
|
{
|
||||||
|
s = &wipe_scr_end[x*SCREENHEIGHT];
|
||||||
|
d = &((short *)screen->GetBuffer())[x];
|
||||||
|
|
||||||
|
for (j = sy; j != 0; --j)
|
||||||
|
{
|
||||||
|
*d = *(s++);
|
||||||
|
d += pitch;
|
||||||
|
}
|
||||||
|
|
||||||
|
s = &wipe_scr_start[x*SCREENHEIGHT];
|
||||||
|
|
||||||
|
for (j = SCREENHEIGHT - sy; j != 0; --j)
|
||||||
|
{
|
||||||
|
*d = *(s++);
|
||||||
|
d += pitch;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -167,136 +170,147 @@ bool wipe_initBurn (int ticks)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int wipe_CalcBurn (BYTE *burnarray, int width, int height, int density)
|
||||||
|
{
|
||||||
|
// This is a modified version of the fire that was once used
|
||||||
|
// on the player setup menu.
|
||||||
|
static int voop;
|
||||||
|
|
||||||
|
int a, b;
|
||||||
|
BYTE *from;
|
||||||
|
|
||||||
|
// generator
|
||||||
|
from = &burnarray[width * height];
|
||||||
|
b = voop;
|
||||||
|
voop += density / 3;
|
||||||
|
for (a = 0; a < density/8; a++)
|
||||||
|
{
|
||||||
|
unsigned int offs = (a+b) & (width - 1);
|
||||||
|
unsigned int v = M_Random();
|
||||||
|
v = MIN(from[offs] + 4 + (v & 15) + (v >> 3) + (M_Random() & 31), 255u);
|
||||||
|
from[offs] = from[width*2 + ((offs + width*3/2) & (width - 1))] = v;
|
||||||
|
}
|
||||||
|
|
||||||
|
density = MIN(density + 10, width * 7);
|
||||||
|
|
||||||
|
from = burnarray;
|
||||||
|
for (b = 0; b <= height; b += 2)
|
||||||
|
{
|
||||||
|
BYTE *pixel = from;
|
||||||
|
|
||||||
|
// special case: first pixel on line
|
||||||
|
BYTE *p = pixel + (width << 1);
|
||||||
|
unsigned int top = *p + *(p + width - 1) + *(p + 1);
|
||||||
|
unsigned int bottom = *(pixel + (width << 2));
|
||||||
|
unsigned int c1 = (top + bottom) >> 2;
|
||||||
|
if (c1 > 1) c1--;
|
||||||
|
*pixel = c1;
|
||||||
|
*(pixel + width) = (c1 + bottom) >> 1;
|
||||||
|
pixel++;
|
||||||
|
|
||||||
|
// main line loop
|
||||||
|
for (a = 1; a < width-1; a++)
|
||||||
|
{
|
||||||
|
// sum top pixels
|
||||||
|
p = pixel + (width << 1);
|
||||||
|
top = *p + *(p - 1) + *(p + 1);
|
||||||
|
|
||||||
|
// bottom pixel
|
||||||
|
bottom = *(pixel + (width << 2));
|
||||||
|
|
||||||
|
// combine pixels
|
||||||
|
c1 = (top + bottom) >> 2;
|
||||||
|
if (c1 > 1) c1--;
|
||||||
|
|
||||||
|
// store pixels
|
||||||
|
*pixel = c1;
|
||||||
|
*(pixel + width) = (c1 + bottom) >> 1; // interpolate
|
||||||
|
|
||||||
|
// next pixel
|
||||||
|
pixel++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// special case: last pixel on line
|
||||||
|
p = pixel + (width << 1);
|
||||||
|
top = *p + *(p - 1) + *(p - width + 1);
|
||||||
|
bottom = *(pixel + (width << 2));
|
||||||
|
c1 = (top + bottom) >> 2;
|
||||||
|
if (c1 > 1) c1--;
|
||||||
|
*pixel = c1;
|
||||||
|
*(pixel + width) = (c1 + bottom) >> 1;
|
||||||
|
|
||||||
|
// next line
|
||||||
|
from += width << 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for done-ness. (Every pixel with level 126 or higher counts as done.)
|
||||||
|
for (a = width * height, from = burnarray; a != 0; --a, ++from)
|
||||||
|
{
|
||||||
|
if (*from < 126)
|
||||||
|
{
|
||||||
|
return density;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
bool wipe_doBurn (int ticks)
|
bool wipe_doBurn (int ticks)
|
||||||
{
|
{
|
||||||
static int voop;
|
|
||||||
bool done;
|
bool done;
|
||||||
|
|
||||||
// This is a modified version of the fire from the player
|
|
||||||
// setup menu.
|
|
||||||
burntime += ticks;
|
burntime += ticks;
|
||||||
ticks *= 2;
|
ticks *= 2;
|
||||||
|
|
||||||
// Make the fire burn
|
// Make the fire burn
|
||||||
while (ticks--)
|
done = false;
|
||||||
|
while (!done && ticks--)
|
||||||
{
|
{
|
||||||
int a, b;
|
density = wipe_CalcBurn(burnarray, FIREWIDTH, FIREHEIGHT, density);
|
||||||
BYTE *from;
|
done = (density < 0);
|
||||||
|
|
||||||
// generator
|
|
||||||
from = burnarray + FIREHEIGHT * FIREWIDTH;
|
|
||||||
b = voop;
|
|
||||||
voop += density / 3;
|
|
||||||
for (a = 0; a < density/8; a++)
|
|
||||||
{
|
|
||||||
unsigned int offs = (a+b) % FIREWIDTH;
|
|
||||||
unsigned int v = M_Random();
|
|
||||||
v = from[offs] + 4 + (v & 15) + (v >> 3) + (M_Random() & 31);
|
|
||||||
if (v > 255)
|
|
||||||
v = 255;
|
|
||||||
from[offs] = from[FIREWIDTH*2 + (offs + FIREWIDTH*3/2)%FIREWIDTH] = v;
|
|
||||||
}
|
|
||||||
|
|
||||||
density += 10;
|
|
||||||
if (density > FIREWIDTH*7)
|
|
||||||
density = FIREWIDTH*7;
|
|
||||||
|
|
||||||
from = burnarray;
|
|
||||||
for (b = 0; b <= FIREHEIGHT; b += 2)
|
|
||||||
{
|
|
||||||
BYTE *pixel = from;
|
|
||||||
|
|
||||||
// special case: first pixel on line
|
|
||||||
BYTE *p = pixel + (FIREWIDTH << 1);
|
|
||||||
unsigned int top = *p + *(p + FIREWIDTH - 1) + *(p + 1);
|
|
||||||
unsigned int bottom = *(pixel + (FIREWIDTH << 2));
|
|
||||||
unsigned int c1 = (top + bottom) >> 2;
|
|
||||||
if (c1 > 1) c1--;
|
|
||||||
*pixel = c1;
|
|
||||||
*(pixel + FIREWIDTH) = (c1 + bottom) >> 1;
|
|
||||||
pixel++;
|
|
||||||
|
|
||||||
// main line loop
|
|
||||||
for (a = 1; a < FIREWIDTH-1; a++)
|
|
||||||
{
|
|
||||||
// sum top pixels
|
|
||||||
p = pixel + (FIREWIDTH << 1);
|
|
||||||
top = *p + *(p - 1) + *(p + 1);
|
|
||||||
|
|
||||||
// bottom pixel
|
|
||||||
bottom = *(pixel + (FIREWIDTH << 2));
|
|
||||||
|
|
||||||
// combine pixels
|
|
||||||
c1 = (top + bottom) >> 2;
|
|
||||||
if (c1 > 1) c1--;
|
|
||||||
|
|
||||||
// store pixels
|
|
||||||
*pixel = c1;
|
|
||||||
*(pixel + FIREWIDTH) = (c1 + bottom) >> 1; // interpolate
|
|
||||||
|
|
||||||
// next pixel
|
|
||||||
pixel++;
|
|
||||||
}
|
|
||||||
|
|
||||||
// special case: last pixel on line
|
|
||||||
p = pixel + (FIREWIDTH << 1);
|
|
||||||
top = *p + *(p - 1) + *(p - FIREWIDTH + 1);
|
|
||||||
bottom = *(pixel + (FIREWIDTH << 2));
|
|
||||||
c1 = (top + bottom) >> 2;
|
|
||||||
if (c1 > 1) c1--;
|
|
||||||
*pixel = c1;
|
|
||||||
*(pixel + FIREWIDTH) = (c1 + bottom) >> 1;
|
|
||||||
|
|
||||||
// next line
|
|
||||||
from += FIREWIDTH << 1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw the screen
|
// Draw the screen
|
||||||
|
fixed_t xstep, ystep, firex, firey;
|
||||||
|
int x, y;
|
||||||
|
BYTE *to, *fromold, *fromnew;
|
||||||
|
|
||||||
|
xstep = (FIREWIDTH * FRACUNIT) / SCREENWIDTH;
|
||||||
|
ystep = (FIREHEIGHT * FRACUNIT) / SCREENHEIGHT;
|
||||||
|
to = screen->GetBuffer();
|
||||||
|
fromold = (BYTE *)wipe_scr_start;
|
||||||
|
fromnew = (BYTE *)wipe_scr_end;
|
||||||
|
|
||||||
|
for (y = 0, firey = 0; y < SCREENHEIGHT; y++, firey += ystep)
|
||||||
{
|
{
|
||||||
fixed_t xstep, ystep, firex, firey;
|
for (x = 0, firex = 0; x < SCREENWIDTH; x++, firex += xstep)
|
||||||
int x, y;
|
|
||||||
BYTE *to, *fromold, *fromnew;
|
|
||||||
|
|
||||||
xstep = (FIREWIDTH * FRACUNIT) / SCREENWIDTH;
|
|
||||||
ystep = (FIREHEIGHT * FRACUNIT) / SCREENHEIGHT;
|
|
||||||
to = screen->GetBuffer();
|
|
||||||
fromold = (BYTE *)wipe_scr_start;
|
|
||||||
fromnew = (BYTE *)wipe_scr_end;
|
|
||||||
done = true;
|
|
||||||
|
|
||||||
for (y = 0, firey = 0; y < SCREENHEIGHT; y++, firey += ystep)
|
|
||||||
{
|
{
|
||||||
for (x = 0, firex = 0; x < SCREENWIDTH; x++, firex += xstep)
|
int fglevel;
|
||||||
{
|
|
||||||
int fglevel;
|
|
||||||
|
|
||||||
fglevel = burnarray[(firex>>FRACBITS)+(firey>>FRACBITS)*FIREWIDTH] / 2;
|
fglevel = burnarray[(firex>>FRACBITS)+(firey>>FRACBITS)*FIREWIDTH] / 2;
|
||||||
if (fglevel >= 63)
|
if (fglevel >= 63)
|
||||||
{
|
{
|
||||||
to[x] = fromnew[x];
|
to[x] = fromnew[x];
|
||||||
}
|
}
|
||||||
else if (fglevel == 0)
|
else if (fglevel == 0)
|
||||||
{
|
{
|
||||||
to[x] = fromold[x];
|
to[x] = fromold[x];
|
||||||
done = false;
|
done = false;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
int bglevel = 64-fglevel;
|
int bglevel = 64-fglevel;
|
||||||
DWORD *fg2rgb = Col2RGB8[fglevel];
|
DWORD *fg2rgb = Col2RGB8[fglevel];
|
||||||
DWORD *bg2rgb = Col2RGB8[bglevel];
|
DWORD *bg2rgb = Col2RGB8[bglevel];
|
||||||
DWORD fg = fg2rgb[fromnew[x]];
|
DWORD fg = fg2rgb[fromnew[x]];
|
||||||
DWORD bg = bg2rgb[fromold[x]];
|
DWORD bg = bg2rgb[fromold[x]];
|
||||||
fg = (fg+bg) | 0x1f07c1f;
|
fg = (fg+bg) | 0x1f07c1f;
|
||||||
to[x] = RGB32k[0][0][fg & (fg>>15)];
|
to[x] = RGB32k[0][0][fg & (fg>>15)];
|
||||||
done = false;
|
done = false;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
fromold += SCREENWIDTH;
|
|
||||||
fromnew += SCREENWIDTH;
|
|
||||||
to += SCREENPITCH;
|
|
||||||
}
|
}
|
||||||
|
fromold += SCREENWIDTH;
|
||||||
|
fromnew += SCREENWIDTH;
|
||||||
|
to += SCREENPITCH;
|
||||||
}
|
}
|
||||||
|
|
||||||
return done || (burntime > 40);
|
return done || (burntime > 40);
|
||||||
|
@ -318,7 +332,7 @@ bool wipe_initFade (int ticks)
|
||||||
|
|
||||||
bool wipe_doFade (int ticks)
|
bool wipe_doFade (int ticks)
|
||||||
{
|
{
|
||||||
fade += ticks;
|
fade += ticks * 2;
|
||||||
if (fade > 64)
|
if (fade > 64)
|
||||||
{
|
{
|
||||||
screen->DrawBlock (0, 0, SCREENWIDTH, SCREENHEIGHT, (BYTE *)wipe_scr_end);
|
screen->DrawBlock (0, 0, SCREENWIDTH, SCREENHEIGHT, (BYTE *)wipe_scr_end);
|
||||||
|
@ -348,7 +362,6 @@ bool wipe_doFade (int ticks)
|
||||||
to += SCREENPITCH;
|
to += SCREENPITCH;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fade++;
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -32,6 +32,10 @@ void wipe_EndScreen (void);
|
||||||
bool wipe_ScreenWipe (int ticks);
|
bool wipe_ScreenWipe (int ticks);
|
||||||
void wipe_Cleanup ();
|
void wipe_Cleanup ();
|
||||||
|
|
||||||
|
// The buffer must have an additional 5 rows not included in height
|
||||||
|
// to use for a seeding area.
|
||||||
|
int wipe_CalcBurn (BYTE *buffer, int width, int height, int density);
|
||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
wipe_None, // don't bother
|
wipe_None, // don't bother
|
||||||
|
|
|
@ -77,13 +77,6 @@
|
||||||
|
|
||||||
IMPLEMENT_CLASS(D3DFB)
|
IMPLEMENT_CLASS(D3DFB)
|
||||||
|
|
||||||
struct FBVERTEX
|
|
||||||
{
|
|
||||||
FLOAT x, y, z, rhw;
|
|
||||||
FLOAT tu, tv;
|
|
||||||
};
|
|
||||||
#define D3DFVF_FBVERTEX (D3DFVF_XYZRHW|D3DFVF_TEX1)
|
|
||||||
|
|
||||||
class D3DTex : public FNativeTexture
|
class D3DTex : public FNativeTexture
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -143,7 +136,6 @@ extern bool VidResizing;
|
||||||
|
|
||||||
EXTERN_CVAR (Bool, fullscreen)
|
EXTERN_CVAR (Bool, fullscreen)
|
||||||
EXTERN_CVAR (Float, Gamma)
|
EXTERN_CVAR (Float, Gamma)
|
||||||
EXTERN_CVAR (Int, vid_displaybits)
|
|
||||||
EXTERN_CVAR (Bool, vid_vsync)
|
EXTERN_CVAR (Bool, vid_vsync)
|
||||||
EXTERN_CVAR (Float, transsouls)
|
EXTERN_CVAR (Float, transsouls)
|
||||||
|
|
||||||
|
@ -183,6 +175,7 @@ D3DFB::D3DFB (int width, int height, bool fullscreen)
|
||||||
PlainStencilShader = NULL;
|
PlainStencilShader = NULL;
|
||||||
DimShader = NULL;
|
DimShader = NULL;
|
||||||
GammaFixerShader = NULL;
|
GammaFixerShader = NULL;
|
||||||
|
BurnShader = NULL;
|
||||||
FBFormat = D3DFMT_UNKNOWN;
|
FBFormat = D3DFMT_UNKNOWN;
|
||||||
PalFormat = D3DFMT_UNKNOWN;
|
PalFormat = D3DFMT_UNKNOWN;
|
||||||
VSync = vid_vsync;
|
VSync = vid_vsync;
|
||||||
|
@ -196,6 +189,7 @@ D3DFB::D3DFB (int width, int height, bool fullscreen)
|
||||||
Textures = NULL;
|
Textures = NULL;
|
||||||
Accel2D = true;
|
Accel2D = true;
|
||||||
GatheringWipeScreen = false;
|
GatheringWipeScreen = false;
|
||||||
|
ScreenWipe = NULL;
|
||||||
|
|
||||||
Gamma = 1.0;
|
Gamma = 1.0;
|
||||||
FlashConstants[0][3] = FlashConstants[0][2] = FlashConstants[0][1] = FlashConstants[0][0] = 0;
|
FlashConstants[0][3] = FlashConstants[0][2] = FlashConstants[0][1] = FlashConstants[0][0] = 0;
|
||||||
|
@ -263,8 +257,6 @@ D3DFB::D3DFB (int width, int height, bool fullscreen)
|
||||||
|
|
||||||
D3DFB::~D3DFB ()
|
D3DFB::~D3DFB ()
|
||||||
{
|
{
|
||||||
KillNativeTexs();
|
|
||||||
KillNativePals();
|
|
||||||
ReleaseResources ();
|
ReleaseResources ();
|
||||||
if (D3DDevice != NULL)
|
if (D3DDevice != NULL)
|
||||||
{
|
{
|
||||||
|
@ -335,6 +327,11 @@ bool D3DFB::CreateResources ()
|
||||||
Printf ("Windowed mode gamma will not work.\n");
|
Printf ("Windowed mode gamma will not work.\n");
|
||||||
GammaFixerShader = NULL;
|
GammaFixerShader = NULL;
|
||||||
}
|
}
|
||||||
|
if (FAILED(D3DDevice->CreatePixelShader (BurnShaderDef, &BurnShader)))
|
||||||
|
{
|
||||||
|
Printf ("Burn screenwipe will not work in D3D mode.\n");
|
||||||
|
BurnShader = NULL;
|
||||||
|
}
|
||||||
CurPixelShader = NULL;
|
CurPixelShader = NULL;
|
||||||
memset(Constant, 0, sizeof(Constant));
|
memset(Constant, 0, sizeof(Constant));
|
||||||
if (!CreateFBTexture() ||
|
if (!CreateFBTexture() ||
|
||||||
|
@ -356,34 +353,9 @@ bool D3DFB::CreateResources ()
|
||||||
void D3DFB::ReleaseResources ()
|
void D3DFB::ReleaseResources ()
|
||||||
{
|
{
|
||||||
I_SaveWindowedPos ();
|
I_SaveWindowedPos ();
|
||||||
if (FBTexture != NULL)
|
KillNativeTexs();
|
||||||
{
|
KillNativePals();
|
||||||
FBTexture->Release();
|
ReleaseDefaultPoolItems();
|
||||||
FBTexture = NULL;
|
|
||||||
}
|
|
||||||
if (FinalWipeScreen != NULL)
|
|
||||||
{
|
|
||||||
if (FinalWipeScreen != TempRenderTexture)
|
|
||||||
{
|
|
||||||
FinalWipeScreen->Release();
|
|
||||||
}
|
|
||||||
FinalWipeScreen = NULL;
|
|
||||||
}
|
|
||||||
if (TempRenderTexture != NULL)
|
|
||||||
{
|
|
||||||
TempRenderTexture->Release();
|
|
||||||
TempRenderTexture = NULL;
|
|
||||||
}
|
|
||||||
if (InitialWipeScreen != NULL)
|
|
||||||
{
|
|
||||||
InitialWipeScreen->Release();
|
|
||||||
InitialWipeScreen = NULL;
|
|
||||||
}
|
|
||||||
if (VertexBuffer != NULL)
|
|
||||||
{
|
|
||||||
VertexBuffer->Release();
|
|
||||||
VertexBuffer = NULL;
|
|
||||||
}
|
|
||||||
if (PaletteTexture != NULL)
|
if (PaletteTexture != NULL)
|
||||||
{
|
{
|
||||||
PaletteTexture->Release();
|
PaletteTexture->Release();
|
||||||
|
@ -424,28 +396,57 @@ void D3DFB::ReleaseResources ()
|
||||||
GammaFixerShader->Release();
|
GammaFixerShader->Release();
|
||||||
GammaFixerShader = NULL;
|
GammaFixerShader = NULL;
|
||||||
}
|
}
|
||||||
|
if (BurnShader != NULL)
|
||||||
|
{
|
||||||
|
BurnShader->Release();
|
||||||
|
BurnShader = NULL;
|
||||||
|
}
|
||||||
|
if (ScreenWipe != NULL)
|
||||||
|
{
|
||||||
|
delete ScreenWipe;
|
||||||
|
ScreenWipe = NULL;
|
||||||
|
}
|
||||||
|
GatheringWipeScreen = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool D3DFB::Reset ()
|
// Free resources created with D3DPOOL_DEFAULT.
|
||||||
|
void D3DFB::ReleaseDefaultPoolItems()
|
||||||
{
|
{
|
||||||
D3DPRESENT_PARAMETERS d3dpp;
|
|
||||||
|
|
||||||
// Free resources created with D3DPOOL_DEFAULT.
|
|
||||||
if (FBTexture != NULL)
|
if (FBTexture != NULL)
|
||||||
{
|
{
|
||||||
FBTexture->Release();
|
FBTexture->Release();
|
||||||
FBTexture = NULL;
|
FBTexture = NULL;
|
||||||
}
|
}
|
||||||
|
if (FinalWipeScreen != NULL)
|
||||||
|
{
|
||||||
|
if (FinalWipeScreen != TempRenderTexture)
|
||||||
|
{
|
||||||
|
FinalWipeScreen->Release();
|
||||||
|
}
|
||||||
|
FinalWipeScreen = NULL;
|
||||||
|
}
|
||||||
if (TempRenderTexture != NULL)
|
if (TempRenderTexture != NULL)
|
||||||
{
|
{
|
||||||
TempRenderTexture->Release();
|
TempRenderTexture->Release();
|
||||||
TempRenderTexture = NULL;
|
TempRenderTexture = NULL;
|
||||||
}
|
}
|
||||||
|
if (InitialWipeScreen != NULL)
|
||||||
|
{
|
||||||
|
InitialWipeScreen->Release();
|
||||||
|
InitialWipeScreen = NULL;
|
||||||
|
}
|
||||||
if (VertexBuffer != NULL)
|
if (VertexBuffer != NULL)
|
||||||
{
|
{
|
||||||
VertexBuffer->Release();
|
VertexBuffer->Release();
|
||||||
VertexBuffer = NULL;
|
VertexBuffer = NULL;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool D3DFB::Reset ()
|
||||||
|
{
|
||||||
|
D3DPRESENT_PARAMETERS d3dpp;
|
||||||
|
|
||||||
|
ReleaseDefaultPoolItems();
|
||||||
FillPresentParameters (&d3dpp, !Windowed, VSync);
|
FillPresentParameters (&d3dpp, !Windowed, VSync);
|
||||||
if (!SUCCEEDED(D3DDevice->Reset (&d3dpp)))
|
if (!SUCCEEDED(D3DDevice->Reset (&d3dpp)))
|
||||||
{
|
{
|
||||||
|
@ -1072,265 +1073,6 @@ void D3DFB::SetBlendingRect(int x1, int y1, int x2, int y2)
|
||||||
/* 2D Stuff */
|
/* 2D Stuff */
|
||||||
/**************************************************************************/
|
/**************************************************************************/
|
||||||
|
|
||||||
//==========================================================================
|
|
||||||
//
|
|
||||||
// D3DFB :: WipeStartScreen
|
|
||||||
//
|
|
||||||
// Called before the current screen has started rendering. This needs to
|
|
||||||
// save what was drawn the previous frame so that it can be animated into
|
|
||||||
// what gets drawn this frame.
|
|
||||||
//
|
|
||||||
// In fullscreen mode, we use GetFrontBufferData() to grab the data that
|
|
||||||
// is visible on screen right now.
|
|
||||||
//
|
|
||||||
// In windowed mode, we can't do that because we'll get the whole desktop.
|
|
||||||
// Instead, we can conveniently use the TempRenderTexture, which is normally
|
|
||||||
// used for gamma-correcting copying the image to the back buffer.
|
|
||||||
//
|
|
||||||
//==========================================================================
|
|
||||||
|
|
||||||
bool D3DFB::WipeStartScreen(int type)
|
|
||||||
{
|
|
||||||
IDirect3DSurface9 *surf, *tsurf;
|
|
||||||
D3DSURFACE_DESC desc;
|
|
||||||
|
|
||||||
if (!test2d)
|
|
||||||
{
|
|
||||||
return Super::WipeStartScreen(type);
|
|
||||||
}
|
|
||||||
if (type != wipe_Fade)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Windowed)
|
|
||||||
{
|
|
||||||
// The InitialWipeScreen must have the same pixel format as
|
|
||||||
// the TempRenderTexture.
|
|
||||||
if (FAILED(TempRenderTexture->GetSurfaceLevel(0, &tsurf)) ||
|
|
||||||
FAILED(tsurf->GetDesc(&desc)))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// GetFrontBufferData works only with this format
|
|
||||||
desc.Format = D3DFMT_A8R8G8B8;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (FAILED(D3DDevice->CreateTexture(Width, TrueHeight, 1, 0,
|
|
||||||
desc.Format, D3DPOOL_SYSTEMMEM, &InitialWipeScreen, NULL)))
|
|
||||||
{
|
|
||||||
InitialWipeScreen = NULL;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (FAILED(InitialWipeScreen->GetSurfaceLevel(0, &surf)))
|
|
||||||
{
|
|
||||||
InitialWipeScreen->Release();
|
|
||||||
InitialWipeScreen = NULL;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (!Windowed)
|
|
||||||
{
|
|
||||||
if (FAILED(D3DDevice->GetFrontBufferData(0, surf)))
|
|
||||||
{
|
|
||||||
InitialWipeScreen->Release();
|
|
||||||
InitialWipeScreen = NULL;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
FinalWipeScreen = TempRenderTexture;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (FAILED(TempRenderTexture->GetSurfaceLevel(0, &tsurf)) ||
|
|
||||||
FAILED(D3DDevice->GetRenderTargetData(tsurf, surf)))
|
|
||||||
{
|
|
||||||
InitialWipeScreen->Release();
|
|
||||||
InitialWipeScreen = NULL;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
// Create another texture to copy the final wipe screen to so
|
|
||||||
// we can still gamma correct the wipe. Since this is just for
|
|
||||||
// gamma correction, it's okay to fail (though not desirable.)
|
|
||||||
if (GammaFixerShader != NULL && Gamma != 1)
|
|
||||||
{
|
|
||||||
if (FAILED(tsurf->GetDesc(&desc)) ||
|
|
||||||
FAILED(D3DDevice->CreateTexture(desc.Width, desc.Height,
|
|
||||||
1, D3DUSAGE_RENDERTARGET, desc.Format, D3DPOOL_DEFAULT,
|
|
||||||
&FinalWipeScreen, NULL)))
|
|
||||||
{
|
|
||||||
FinalWipeScreen = TempRenderTexture;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
FinalWipeScreen = TempRenderTexture;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Even fullscreen will render to the TempRenderTexture, so we can have
|
|
||||||
// a copy of the new screen readily available.
|
|
||||||
GatheringWipeScreen = true;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
//==========================================================================
|
|
||||||
//
|
|
||||||
// D3DFB :: WipeEndScreen
|
|
||||||
//
|
|
||||||
// The screen we want to animate to has just been drawn. This function is
|
|
||||||
// called in place of Update(), so it has not been Presented yet.
|
|
||||||
//
|
|
||||||
//==========================================================================
|
|
||||||
|
|
||||||
void D3DFB::WipeEndScreen()
|
|
||||||
{
|
|
||||||
if (!test2d)
|
|
||||||
{
|
|
||||||
Super::WipeEndScreen();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
WipeTime = 0;
|
|
||||||
|
|
||||||
// Don't do anything if there is no starting point.
|
|
||||||
if (InitialWipeScreen == NULL)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the whole screen was drawn without 2D accel, get it in to
|
|
||||||
// video memory now.
|
|
||||||
if (!In2D)
|
|
||||||
{
|
|
||||||
Begin2D();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Don't do anything if there is no ending point.
|
|
||||||
if (OldRenderTarget == NULL)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If these are different, reverse their roles so we don't need to
|
|
||||||
// waste time copying from TempRenderTexture to FinalWipeScreen.
|
|
||||||
swap(FinalWipeScreen, TempRenderTexture);
|
|
||||||
|
|
||||||
// At this point, InitialWipeScreen holds the screen we are wiping from.
|
|
||||||
// FinalWipeScreen holds the screen we are wiping to, which may be the
|
|
||||||
// same texture as TempRenderTexture.
|
|
||||||
}
|
|
||||||
|
|
||||||
//==========================================================================
|
|
||||||
//
|
|
||||||
// D3DFB :: WipeDo
|
|
||||||
//
|
|
||||||
// Perform the actual wipe animation. The number of tics since the last
|
|
||||||
// time this function was called is passed in. Returns true when the wipe
|
|
||||||
// is over. The first time this function has been called, the screen is
|
|
||||||
// still locked from before and EndScene() still has not been called.
|
|
||||||
// Successive times need to call BeginScene().
|
|
||||||
//
|
|
||||||
//==========================================================================
|
|
||||||
|
|
||||||
bool D3DFB::WipeDo(int ticks)
|
|
||||||
{
|
|
||||||
if (!test2d)
|
|
||||||
{
|
|
||||||
return Super::WipeDo(ticks);
|
|
||||||
}
|
|
||||||
WipeTime += ticks;
|
|
||||||
|
|
||||||
// Sanity checks.
|
|
||||||
if (InitialWipeScreen == NULL || FinalWipeScreen == NULL)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (GatheringWipeScreen)
|
|
||||||
{ // This is the first time we've been called for this wipe.
|
|
||||||
GatheringWipeScreen = false;
|
|
||||||
|
|
||||||
if (OldRenderTarget == NULL)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
D3DDevice->SetRenderTarget(0, OldRenderTarget);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{ // This is the second or later time we've been called for this wipe.
|
|
||||||
D3DDevice->BeginScene();
|
|
||||||
}
|
|
||||||
OldRenderTarget = NULL;
|
|
||||||
if (TempRenderTexture != NULL && TempRenderTexture != FinalWipeScreen &&
|
|
||||||
((Windowed && GammaFixerShader) || GatheringWipeScreen))
|
|
||||||
{
|
|
||||||
IDirect3DSurface9 *targetsurf;
|
|
||||||
if (FAILED(TempRenderTexture->GetSurfaceLevel(0, &targetsurf)) ||
|
|
||||||
FAILED(D3DDevice->GetRenderTarget(0, &OldRenderTarget)) ||
|
|
||||||
FAILED(D3DDevice->SetRenderTarget(0, targetsurf)))
|
|
||||||
{
|
|
||||||
// Setting the render target failed.
|
|
||||||
OldRenderTarget = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
In2D = 2;
|
|
||||||
D3DDevice->SetStreamSource(0, VertexBuffer, 0, sizeof(FBVERTEX));
|
|
||||||
D3DDevice->SetFVF(D3DFVF_FBVERTEX);
|
|
||||||
|
|
||||||
/* Crossfade only for testing purposes, because it's the simplest.
|
|
||||||
* More to come later.
|
|
||||||
*/
|
|
||||||
|
|
||||||
// Put the initial screen back to the buffer, presumably with DMA.
|
|
||||||
IDirect3DSurface9 *source, *target;
|
|
||||||
|
|
||||||
if (SUCCEEDED(InitialWipeScreen->GetSurfaceLevel(0, &source)) &&
|
|
||||||
SUCCEEDED(D3DDevice->GetRenderTarget(0, &target)))
|
|
||||||
{
|
|
||||||
D3DDevice->UpdateSurface(source, NULL, target, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Draw the new screen on top of it.
|
|
||||||
SetTexture(0, FinalWipeScreen);
|
|
||||||
SetAlphaBlend(TRUE, D3DBLEND_SRCALPHA, D3DBLEND_INVSRCALPHA);
|
|
||||||
SetConstant(0, 0, 0, 0, clamp(WipeTime / 32.f, 0.f, 1.f));
|
|
||||||
SetConstant(1, 1, 1, 1, 0);
|
|
||||||
SetPixelShader(PlainShader);
|
|
||||||
// FIXME: The FinalWipeScreen gets junk at the top in letterbox modes.
|
|
||||||
D3DDevice->DrawPrimitive(D3DPT_TRIANGLEFAN, 0, 2);
|
|
||||||
|
|
||||||
DrawLetterbox();
|
|
||||||
|
|
||||||
return WipeTime >= 32;
|
|
||||||
}
|
|
||||||
|
|
||||||
//==========================================================================
|
|
||||||
//
|
|
||||||
// D3DFB :: WipeCleanup
|
|
||||||
//
|
|
||||||
// Release any resources that were specifically created for the wipe.
|
|
||||||
//
|
|
||||||
//==========================================================================
|
|
||||||
|
|
||||||
void D3DFB::WipeCleanup()
|
|
||||||
{
|
|
||||||
if (!test2d)
|
|
||||||
{
|
|
||||||
Super::WipeCleanup();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (InitialWipeScreen != NULL)
|
|
||||||
{
|
|
||||||
InitialWipeScreen->Release();
|
|
||||||
InitialWipeScreen = NULL;
|
|
||||||
}
|
|
||||||
if (FinalWipeScreen != NULL && FinalWipeScreen != TempRenderTexture)
|
|
||||||
{
|
|
||||||
FinalWipeScreen->Release();
|
|
||||||
}
|
|
||||||
FinalWipeScreen = NULL;
|
|
||||||
GatheringWipeScreen = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
// D3DTex Constructor
|
// D3DTex Constructor
|
||||||
|
|
|
@ -339,3 +339,60 @@ const DWORD GammaFixerDef[] =
|
||||||
0x80000000, 0x0200000e, 0x80020000, 0x80550000, 0x0200000e, 0x80040000,
|
0x80000000, 0x0200000e, 0x80020000, 0x80550000, 0x0200000e, 0x80040000,
|
||||||
0x80aa0000, 0x02000001, 0x800f0800, 0x80e40000, 0x0000ffff
|
0x80aa0000, 0x02000001, 0x800f0800, 0x80e40000, 0x0000ffff
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// The shader used by the burn effect screen wipe ---------------------------
|
||||||
|
|
||||||
|
#if HLSL_SOURCE_CODE
|
||||||
|
sampler2D NewScreen : register(s0);
|
||||||
|
sampler2D Burn : register(s1);
|
||||||
|
|
||||||
|
float4 main (float2 coord[2] : TEXCOORD0) : COLOR
|
||||||
|
{
|
||||||
|
float4 color = tex2D(NewScreen, coord[0]);
|
||||||
|
float4 alpha = tex2D(Burn, coord[1]);
|
||||||
|
color.a = alpha.r * 2;
|
||||||
|
return color;
|
||||||
|
}
|
||||||
|
#elif SHADER_ASSEMBLY_CODE
|
||||||
|
//
|
||||||
|
// Generated by Microsoft (R) D3DX9 Shader Compiler 9.15.779.0000
|
||||||
|
//
|
||||||
|
// fxc burn.ps /Tps_1_4 /VnBurnShaderDef /Fhburn.h /LD
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// Parameters:
|
||||||
|
//
|
||||||
|
// sampler2D Burn;
|
||||||
|
// sampler2D NewScreen;
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// Registers:
|
||||||
|
//
|
||||||
|
// Name Reg Size
|
||||||
|
// ------------ ----- ----
|
||||||
|
// NewScreen s0 1
|
||||||
|
// Burn s1 1
|
||||||
|
//
|
||||||
|
|
||||||
|
ps_1_4
|
||||||
|
texld r0, t0
|
||||||
|
texld r1, t1
|
||||||
|
add r0.w, r1.x, r1.x
|
||||||
|
+ mov r0.xyz, r0
|
||||||
|
|
||||||
|
// approximately 3 instruction slots used (2 texture, 1 arithmetic)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
const DWORD BurnShaderDef[] =
|
||||||
|
{
|
||||||
|
0xffff0104, 0x0029fffe, 0x42415443, 0x0000001c, 0x0000006d, 0xffff0104,
|
||||||
|
0x00000002, 0x0000001c, 0x00000100, 0x00000066, 0x00000044, 0x00010003,
|
||||||
|
0x00000001, 0x0000004c, 0x00000000, 0x0000005c, 0x00000003, 0x00000001,
|
||||||
|
0x0000004c, 0x00000000, 0x6e727542, 0xababab00, 0x000c0004, 0x00010001,
|
||||||
|
0x00000001, 0x00000000, 0x5377654e, 0x65657263, 0x7370006e, 0x345f315f,
|
||||||
|
0x63694d00, 0x6f736f72, 0x28207466, 0x44202952, 0x39584433, 0x61685320,
|
||||||
|
0x20726564, 0x706d6f43, 0x72656c69, 0x312e3920, 0x37372e35, 0x30302e39,
|
||||||
|
0xab003030, 0x00000042, 0x800f0000, 0xb0e40000, 0x00000042, 0x800f0001,
|
||||||
|
0xb0e40001, 0x00000002, 0x80080000, 0x80000001, 0x80000001, 0x40000001,
|
||||||
|
0x80070000, 0x80e40000, 0x0000ffff
|
||||||
|
};
|
||||||
|
|
635
src/win32/fb_d3d9_wipe.cpp
Normal file
635
src/win32/fb_d3d9_wipe.cpp
Normal file
|
@ -0,0 +1,635 @@
|
||||||
|
/*
|
||||||
|
** fb_d3d9_wipe.cpp
|
||||||
|
** Implements the different screen wipes using Direct3D calls.
|
||||||
|
**
|
||||||
|
**---------------------------------------------------------------------------
|
||||||
|
** Copyright 1998-2008 Randy Heit
|
||||||
|
** All rights reserved.
|
||||||
|
**
|
||||||
|
** Redistribution and use in source and binary forms, with or without
|
||||||
|
** modification, are permitted provided that the following conditions
|
||||||
|
** are met:
|
||||||
|
**
|
||||||
|
** 1. Redistributions of source code must retain the above copyright
|
||||||
|
** notice, this list of conditions and the following disclaimer.
|
||||||
|
** 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
** notice, this list of conditions and the following disclaimer in the
|
||||||
|
** documentation and/or other materials provided with the distribution.
|
||||||
|
** 3. The name of the author may not be used to endorse or promote products
|
||||||
|
** derived from this software without specific prior written permission.
|
||||||
|
**
|
||||||
|
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||||
|
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||||
|
** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||||
|
** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||||
|
** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||||
|
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
**---------------------------------------------------------------------------
|
||||||
|
**
|
||||||
|
*/
|
||||||
|
|
||||||
|
// HEADER FILES ------------------------------------------------------------
|
||||||
|
|
||||||
|
#ifdef _DEBUG
|
||||||
|
#define D3D_DEBUG_INFO
|
||||||
|
#endif
|
||||||
|
#define DIRECT3D_VERSION 0x0900
|
||||||
|
#define WIN32_LEAN_AND_MEAN
|
||||||
|
|
||||||
|
#include <windows.h>
|
||||||
|
#include <d3d9.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#define USE_WINDOWS_DWORD
|
||||||
|
#include "doomtype.h"
|
||||||
|
#include "f_wipe.h"
|
||||||
|
#include "win32iface.h"
|
||||||
|
#include "templates.h"
|
||||||
|
#include "m_random.h"
|
||||||
|
|
||||||
|
// MACROS ------------------------------------------------------------------
|
||||||
|
|
||||||
|
// TYPES -------------------------------------------------------------------
|
||||||
|
|
||||||
|
class D3DFB::Wiper_Crossfade : public D3DFB::Wiper
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Wiper_Crossfade();
|
||||||
|
bool Run(int ticks, D3DFB *fb);
|
||||||
|
|
||||||
|
private:
|
||||||
|
int Clock;
|
||||||
|
};
|
||||||
|
|
||||||
|
class D3DFB::Wiper_Melt : public D3DFB::Wiper
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Wiper_Melt();
|
||||||
|
bool Run(int ticks, D3DFB *fb);
|
||||||
|
|
||||||
|
private:
|
||||||
|
// Match the strip sizes that oldschool Doom used.
|
||||||
|
static const int WIDTH = 160, HEIGHT = 200;
|
||||||
|
int y[WIDTH];
|
||||||
|
};
|
||||||
|
|
||||||
|
class D3DFB::Wiper_Burn : public D3DFB::Wiper
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Wiper_Burn(D3DFB *fb);
|
||||||
|
~Wiper_Burn();
|
||||||
|
bool Run(int ticks, D3DFB *fb);
|
||||||
|
|
||||||
|
private:
|
||||||
|
static const int WIDTH = 64, HEIGHT = 64;
|
||||||
|
BYTE BurnArray[WIDTH * (HEIGHT + 5)];
|
||||||
|
IDirect3DTexture9 *BurnTexture;
|
||||||
|
int Density;
|
||||||
|
int BurnTime;
|
||||||
|
|
||||||
|
struct BURNVERTEX
|
||||||
|
{
|
||||||
|
FLOAT x, y, z, rhw;
|
||||||
|
FLOAT tu0, tv0;
|
||||||
|
FLOAT tu1, tv1;
|
||||||
|
};
|
||||||
|
#define D3DFVF_BURNVERTEX (D3DFVF_XYZRHW|D3DFVF_TEX2)
|
||||||
|
};
|
||||||
|
|
||||||
|
// EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
|
||||||
|
|
||||||
|
// PUBLIC FUNCTION PROTOTYPES ----------------------------------------------
|
||||||
|
|
||||||
|
// PRIVATE FUNCTION PROTOTYPES ---------------------------------------------
|
||||||
|
|
||||||
|
// EXTERNAL DATA DECLARATIONS ----------------------------------------------
|
||||||
|
|
||||||
|
EXTERN_CVAR(Bool, test2d)
|
||||||
|
|
||||||
|
// PRIVATE DATA DEFINITIONS ------------------------------------------------
|
||||||
|
|
||||||
|
// PUBLIC DATA DEFINITIONS -------------------------------------------------
|
||||||
|
|
||||||
|
// CODE --------------------------------------------------------------------
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// D3DFB :: WipeStartScreen
|
||||||
|
//
|
||||||
|
// Called before the current screen has started rendering. This needs to
|
||||||
|
// save what was drawn the previous frame so that it can be animated into
|
||||||
|
// what gets drawn this frame.
|
||||||
|
//
|
||||||
|
// In fullscreen mode, we use GetFrontBufferData() to grab the data that
|
||||||
|
// is visible on screen right now.
|
||||||
|
//
|
||||||
|
// In windowed mode, we can't do that because we'll get the whole desktop.
|
||||||
|
// Instead, we can conveniently use the TempRenderTexture, which is normally
|
||||||
|
// used for gamma-correcting copying the image to the back buffer.
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
bool D3DFB::WipeStartScreen(int type)
|
||||||
|
{
|
||||||
|
IDirect3DSurface9 *surf, *tsurf;
|
||||||
|
D3DSURFACE_DESC desc;
|
||||||
|
|
||||||
|
if (!test2d)
|
||||||
|
{
|
||||||
|
return Super::WipeStartScreen(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case wipe_Melt:
|
||||||
|
ScreenWipe = new Wiper_Melt;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case wipe_Burn:
|
||||||
|
ScreenWipe = new Wiper_Burn(this);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case wipe_Fade:
|
||||||
|
ScreenWipe = new Wiper_Crossfade;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Windowed)
|
||||||
|
{
|
||||||
|
// The InitialWipeScreen must have the same pixel format as
|
||||||
|
// the TempRenderTexture.
|
||||||
|
if (FAILED(TempRenderTexture->GetSurfaceLevel(0, &tsurf)) ||
|
||||||
|
FAILED(tsurf->GetDesc(&desc)))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (FAILED(D3DDevice->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &tsurf)) ||
|
||||||
|
FAILED(tsurf->GetDesc(&desc)))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// GetFrontBufferData works only with this format
|
||||||
|
desc.Format = D3DFMT_A8R8G8B8;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (FAILED(D3DDevice->CreateTexture(desc.Width, desc.Height, 1, 0,
|
||||||
|
desc.Format, D3DPOOL_SYSTEMMEM, &InitialWipeScreen, NULL)))
|
||||||
|
{
|
||||||
|
InitialWipeScreen = NULL;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (FAILED(InitialWipeScreen->GetSurfaceLevel(0, &surf)))
|
||||||
|
{
|
||||||
|
InitialWipeScreen->Release();
|
||||||
|
InitialWipeScreen = NULL;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!Windowed)
|
||||||
|
{
|
||||||
|
if (FAILED(D3DDevice->GetFrontBufferData(0, surf)))
|
||||||
|
{
|
||||||
|
InitialWipeScreen->Release();
|
||||||
|
InitialWipeScreen = NULL;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
FinalWipeScreen = TempRenderTexture;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (FAILED(TempRenderTexture->GetSurfaceLevel(0, &tsurf)) ||
|
||||||
|
FAILED(D3DDevice->GetRenderTargetData(tsurf, surf)))
|
||||||
|
{
|
||||||
|
InitialWipeScreen->Release();
|
||||||
|
InitialWipeScreen = NULL;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// Create another texture to copy the final wipe screen to so
|
||||||
|
// we can still gamma correct the wipe. Since this is just for
|
||||||
|
// gamma correction, it's okay to fail (though not desirable.)
|
||||||
|
if (GammaFixerShader != NULL && Gamma != 1)
|
||||||
|
{
|
||||||
|
if (FAILED(tsurf->GetDesc(&desc)) ||
|
||||||
|
FAILED(D3DDevice->CreateTexture(desc.Width, desc.Height,
|
||||||
|
1, D3DUSAGE_RENDERTARGET, desc.Format, D3DPOOL_DEFAULT,
|
||||||
|
&FinalWipeScreen, NULL)))
|
||||||
|
{
|
||||||
|
FinalWipeScreen = TempRenderTexture;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
FinalWipeScreen = TempRenderTexture;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Even fullscreen will render to the TempRenderTexture, so we can have
|
||||||
|
// a copy of the new screen readily available.
|
||||||
|
GatheringWipeScreen = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// D3DFB :: WipeEndScreen
|
||||||
|
//
|
||||||
|
// The screen we want to animate to has just been drawn. This function is
|
||||||
|
// called in place of Update(), so it has not been Presented yet.
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
void D3DFB::WipeEndScreen()
|
||||||
|
{
|
||||||
|
if (!test2d)
|
||||||
|
{
|
||||||
|
Super::WipeEndScreen();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Don't do anything if there is no starting point.
|
||||||
|
if (InitialWipeScreen == NULL)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the whole screen was drawn without 2D accel, get it in to
|
||||||
|
// video memory now.
|
||||||
|
if (!In2D)
|
||||||
|
{
|
||||||
|
Begin2D();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Don't do anything if there is no ending point.
|
||||||
|
if (OldRenderTarget == NULL)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If these are different, reverse their roles so we don't need to
|
||||||
|
// waste time copying from TempRenderTexture to FinalWipeScreen.
|
||||||
|
swap(FinalWipeScreen, TempRenderTexture);
|
||||||
|
|
||||||
|
// At this point, InitialWipeScreen holds the screen we are wiping from.
|
||||||
|
// FinalWipeScreen holds the screen we are wiping to, which may be the
|
||||||
|
// same texture as TempRenderTexture.
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// D3DFB :: WipeDo
|
||||||
|
//
|
||||||
|
// Perform the actual wipe animation. The number of tics since the last
|
||||||
|
// time this function was called is passed in. Returns true when the wipe
|
||||||
|
// is over. The first time this function has been called, the screen is
|
||||||
|
// still locked from before and EndScene() still has not been called.
|
||||||
|
// Successive times need to call BeginScene().
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
bool D3DFB::WipeDo(int ticks)
|
||||||
|
{
|
||||||
|
if (!test2d)
|
||||||
|
{
|
||||||
|
return Super::WipeDo(ticks);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sanity checks.
|
||||||
|
if (InitialWipeScreen == NULL || FinalWipeScreen == NULL)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (GatheringWipeScreen)
|
||||||
|
{ // This is the first time we've been called for this wipe.
|
||||||
|
GatheringWipeScreen = false;
|
||||||
|
|
||||||
|
if (OldRenderTarget == NULL)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
D3DDevice->SetRenderTarget(0, OldRenderTarget);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ // This is the second or later time we've been called for this wipe.
|
||||||
|
D3DDevice->BeginScene();
|
||||||
|
}
|
||||||
|
OldRenderTarget = NULL;
|
||||||
|
if (TempRenderTexture != NULL && TempRenderTexture != FinalWipeScreen &&
|
||||||
|
((Windowed && GammaFixerShader) || GatheringWipeScreen))
|
||||||
|
{
|
||||||
|
IDirect3DSurface9 *targetsurf;
|
||||||
|
if (FAILED(TempRenderTexture->GetSurfaceLevel(0, &targetsurf)) ||
|
||||||
|
FAILED(D3DDevice->GetRenderTarget(0, &OldRenderTarget)) ||
|
||||||
|
FAILED(D3DDevice->SetRenderTarget(0, targetsurf)))
|
||||||
|
{
|
||||||
|
// Setting the render target failed.
|
||||||
|
OldRenderTarget = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
In2D = 2;
|
||||||
|
|
||||||
|
bool done = ScreenWipe->Run(ticks, this);
|
||||||
|
DrawLetterbox();
|
||||||
|
return done;
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// D3DFB :: WipeCleanup
|
||||||
|
//
|
||||||
|
// Release any resources that were specifically created for the wipe.
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
void D3DFB::WipeCleanup()
|
||||||
|
{
|
||||||
|
if (ScreenWipe != NULL)
|
||||||
|
{
|
||||||
|
delete ScreenWipe;
|
||||||
|
ScreenWipe = NULL;
|
||||||
|
}
|
||||||
|
if (InitialWipeScreen != NULL)
|
||||||
|
{
|
||||||
|
InitialWipeScreen->Release();
|
||||||
|
InitialWipeScreen = NULL;
|
||||||
|
}
|
||||||
|
if (FinalWipeScreen != NULL && FinalWipeScreen != TempRenderTexture)
|
||||||
|
{
|
||||||
|
FinalWipeScreen->Release();
|
||||||
|
}
|
||||||
|
FinalWipeScreen = NULL;
|
||||||
|
GatheringWipeScreen = false;
|
||||||
|
if (!test2d)
|
||||||
|
{
|
||||||
|
Super::WipeCleanup();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// D3DFB :: Wiper Constructor
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
D3DFB::Wiper::~Wiper()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// WIPE: CROSSFADE ---------------------------------------------------------
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// D3DFB :: Wiper_Crossfade Constructor
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
D3DFB::Wiper_Crossfade::Wiper_Crossfade()
|
||||||
|
: Clock(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// D3DFB :: Wiper_Crossfade :: Run
|
||||||
|
//
|
||||||
|
// Fades the old screen into the new one over 32 ticks.
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
bool D3DFB::Wiper_Crossfade::Run(int ticks, D3DFB *fb)
|
||||||
|
{
|
||||||
|
Clock += ticks;
|
||||||
|
|
||||||
|
// Put the initial screen back to the buffer, presumably with DMA.
|
||||||
|
IDirect3DSurface9 *source, *target;
|
||||||
|
|
||||||
|
if (SUCCEEDED(fb->InitialWipeScreen->GetSurfaceLevel(0, &source)) &&
|
||||||
|
SUCCEEDED(fb->D3DDevice->GetRenderTarget(0, &target)))
|
||||||
|
{
|
||||||
|
fb->D3DDevice->UpdateSurface(source, NULL, target, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw the new screen on top of it.
|
||||||
|
fb->D3DDevice->SetStreamSource(0, fb->VertexBuffer, 0, sizeof(FBVERTEX));
|
||||||
|
fb->D3DDevice->SetFVF(D3DFVF_FBVERTEX);
|
||||||
|
fb->SetTexture(0, fb->FinalWipeScreen);
|
||||||
|
fb->SetAlphaBlend(TRUE, D3DBLEND_SRCALPHA, D3DBLEND_INVSRCALPHA);
|
||||||
|
fb->SetConstant(0, 0, 0, 0, clamp(Clock / 32.f, 0.f, 1.f));
|
||||||
|
fb->SetConstant(1, 1, 1, 1, 0);
|
||||||
|
fb->SetPixelShader(fb->PlainShader);
|
||||||
|
// FIXME: The FinalWipeScreen gets junk at the top in letterbox modes.
|
||||||
|
fb->D3DDevice->DrawPrimitive(D3DPT_TRIANGLEFAN, 0, 2);
|
||||||
|
|
||||||
|
return Clock >= 32;
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// D3DFB :: Wiper_Melt Constructor
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
D3DFB::Wiper_Melt::Wiper_Melt()
|
||||||
|
{
|
||||||
|
int i, r;
|
||||||
|
|
||||||
|
// setup initial column positions
|
||||||
|
// (y<0 => not ready to scroll yet)
|
||||||
|
y[0] = -(M_Random() & 15);
|
||||||
|
for (i = 1; i < WIDTH; ++i)
|
||||||
|
{
|
||||||
|
r = (M_Random()%3) - 1;
|
||||||
|
y[i] = clamp(y[i-1] + r, -15, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// D3DFB :: Wiper_Melt :: Run
|
||||||
|
//
|
||||||
|
// Fades the old screen into the new one over 32 ticks.
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
bool D3DFB::Wiper_Melt::Run(int ticks, D3DFB *fb)
|
||||||
|
{
|
||||||
|
IDirect3DSurface9 *source, *target;
|
||||||
|
|
||||||
|
if (FAILED(fb->InitialWipeScreen->GetSurfaceLevel(0, &source)) ||
|
||||||
|
FAILED(fb->D3DDevice->GetRenderTarget(0, &target)))
|
||||||
|
{
|
||||||
|
// A fat lot of good we can do if we can't get these two surfaces.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw the new screen on the bottom.
|
||||||
|
fb->D3DDevice->SetStreamSource(0, fb->VertexBuffer, 0, sizeof(FBVERTEX));
|
||||||
|
fb->D3DDevice->SetFVF(D3DFVF_FBVERTEX);
|
||||||
|
fb->SetTexture(0, fb->FinalWipeScreen);
|
||||||
|
fb->SetAlphaBlend(FALSE);
|
||||||
|
fb->SetConstant(0, 0, 0, 0, 0);
|
||||||
|
fb->SetConstant(1, 1, 1, 1, 1);
|
||||||
|
fb->SetPixelShader(fb->PlainShader);
|
||||||
|
fb->D3DDevice->DrawPrimitive(D3DPT_TRIANGLEFAN, 0, 2);
|
||||||
|
|
||||||
|
int i, dy;
|
||||||
|
bool done;
|
||||||
|
|
||||||
|
// Copy the old screen in vertical strips on top of the new one.
|
||||||
|
while (ticks--)
|
||||||
|
{
|
||||||
|
done = true;
|
||||||
|
for (i = 0; i < WIDTH; i++)
|
||||||
|
{
|
||||||
|
if (y[i] < 0)
|
||||||
|
{
|
||||||
|
y[i]++;
|
||||||
|
done = false;
|
||||||
|
}
|
||||||
|
else if (y[i] < HEIGHT)
|
||||||
|
{
|
||||||
|
dy = (y[i] < 16) ? y[i]+1 : 8;
|
||||||
|
y[i] = MIN(y[i] + dy, HEIGHT);
|
||||||
|
done = false;
|
||||||
|
}
|
||||||
|
if (ticks == 0)
|
||||||
|
{ // Only draw for the final tick.
|
||||||
|
RECT rect;
|
||||||
|
POINT dpt;
|
||||||
|
|
||||||
|
dpt.x = i * fb->Width / WIDTH;
|
||||||
|
dpt.y = MAX(0, y[i] * fb->Height / HEIGHT);
|
||||||
|
rect.left = dpt.x;
|
||||||
|
rect.top = 0;
|
||||||
|
rect.right = (i + 1) * fb->Width / WIDTH;
|
||||||
|
rect.bottom = fb->Height - dpt.y;
|
||||||
|
if (rect.bottom > rect.top)
|
||||||
|
{
|
||||||
|
fb->D3DDevice->UpdateSurface(source, &rect, target, &dpt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return done;
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// D3DFB :: Wiper_Burn Constructor
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
D3DFB::Wiper_Burn::Wiper_Burn(D3DFB *fb)
|
||||||
|
{
|
||||||
|
Density = 4;
|
||||||
|
BurnTime = 0;
|
||||||
|
memset(BurnArray, 0, sizeof(BurnArray));
|
||||||
|
if (fb->BurnShader == NULL || FAILED(fb->D3DDevice->CreateTexture(WIDTH, HEIGHT, 1,
|
||||||
|
D3DUSAGE_DYNAMIC, D3DFMT_L8, D3DPOOL_DEFAULT, &BurnTexture, NULL)))
|
||||||
|
{
|
||||||
|
BurnTexture = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// D3DFB :: Wiper_Burn Destructor
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
D3DFB::Wiper_Burn::~Wiper_Burn()
|
||||||
|
{
|
||||||
|
if (BurnTexture != NULL)
|
||||||
|
{
|
||||||
|
BurnTexture->Release();
|
||||||
|
BurnTexture = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// D3DFB :: Wiper_Burn :: Run
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
bool D3DFB::Wiper_Burn::Run(int ticks, D3DFB *fb)
|
||||||
|
{
|
||||||
|
bool done;
|
||||||
|
|
||||||
|
BurnTime += ticks;
|
||||||
|
ticks *= 2;
|
||||||
|
|
||||||
|
// Make the fire burn
|
||||||
|
done = false;
|
||||||
|
while (!done && ticks--)
|
||||||
|
{
|
||||||
|
Density = wipe_CalcBurn(BurnArray, WIDTH, HEIGHT, Density);
|
||||||
|
done = (Density < 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update the burn texture with the new burn data
|
||||||
|
D3DLOCKED_RECT lrect;
|
||||||
|
if (SUCCEEDED(BurnTexture->LockRect(0, &lrect, NULL, D3DLOCK_DISCARD)))
|
||||||
|
{
|
||||||
|
const BYTE *src = BurnArray;
|
||||||
|
BYTE *dest = (BYTE *)lrect.pBits;
|
||||||
|
for (int y = HEIGHT; y != 0; --y)
|
||||||
|
{
|
||||||
|
for (int x = WIDTH; x != 0; --x)
|
||||||
|
{
|
||||||
|
*dest++ = *src++;
|
||||||
|
}
|
||||||
|
dest += lrect.Pitch - WIDTH;
|
||||||
|
}
|
||||||
|
BurnTexture->UnlockRect(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Put the initial screen back to the buffer.
|
||||||
|
IDirect3DSurface9 *source, *target;
|
||||||
|
|
||||||
|
if (SUCCEEDED(fb->InitialWipeScreen->GetSurfaceLevel(0, &source)) &&
|
||||||
|
SUCCEEDED(fb->D3DDevice->GetRenderTarget(0, &target)))
|
||||||
|
{
|
||||||
|
fb->D3DDevice->UpdateSurface(source, NULL, target, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Burn the new screen on top of it.
|
||||||
|
float top = fb->LBOffset - 0.5f;
|
||||||
|
float right = float(fb->Width) - 0.5f;
|
||||||
|
float bot = float(fb->Height) + top;
|
||||||
|
float texright = float(fb->Width) / float(fb->FBWidth);
|
||||||
|
float texbot = float(fb->Height) / float(fb->FBHeight);
|
||||||
|
|
||||||
|
BURNVERTEX verts[4] =
|
||||||
|
{
|
||||||
|
{ -0.5f, top, 0.5f, 1.f, 0.f, 0.f, 0, 0 },
|
||||||
|
{ right, top, 0.5f, 1.f, texright, 0.f, 1, 0 },
|
||||||
|
{ right, bot, 0.5f, 1.f, texright, texbot, 1, 1 },
|
||||||
|
{ -0.5f, bot, 0.5f, 1.f, 0.f, texbot, 0, 1 }
|
||||||
|
};
|
||||||
|
|
||||||
|
fb->D3DDevice->SetFVF(D3DFVF_BURNVERTEX);
|
||||||
|
fb->SetTexture(0, fb->FinalWipeScreen);
|
||||||
|
fb->SetTexture(1, BurnTexture);
|
||||||
|
fb->SetAlphaBlend(TRUE, D3DBLEND_SRCALPHA, D3DBLEND_INVSRCALPHA);
|
||||||
|
fb->SetPixelShader(fb->BurnShader);
|
||||||
|
fb->D3DDevice->SetSamplerState(1, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
|
||||||
|
fb->D3DDevice->SetSamplerState(1, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
|
||||||
|
fb->D3DDevice->SetSamplerState(1, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
|
||||||
|
fb->D3DDevice->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, verts, sizeof(BURNVERTEX));
|
||||||
|
fb->D3DDevice->SetSamplerState(1, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
|
||||||
|
fb->D3DDevice->SetSamplerState(1, D3DSAMP_ADDRESSU, D3DTADDRESS_WRAP);
|
||||||
|
fb->D3DDevice->SetSamplerState(1, D3DSAMP_ADDRESSV, D3DTADDRESS_WRAP);
|
||||||
|
|
||||||
|
// The fire may not always stabilize, so the wipe is forced to end
|
||||||
|
// after an arbitrary maximum time.
|
||||||
|
return done || (BurnTime > 40);
|
||||||
|
}
|
|
@ -264,6 +264,7 @@ private:
|
||||||
void FillPresentParameters (D3DPRESENT_PARAMETERS *pp, bool fullscreen, bool vsync);
|
void FillPresentParameters (D3DPRESENT_PARAMETERS *pp, bool fullscreen, bool vsync);
|
||||||
bool UploadVertices();
|
bool UploadVertices();
|
||||||
bool Reset();
|
bool Reset();
|
||||||
|
void ReleaseDefaultPoolItems();
|
||||||
void KillNativePals();
|
void KillNativePals();
|
||||||
void KillNativeTexs();
|
void KillNativeTexs();
|
||||||
void DrawLetterbox();
|
void DrawLetterbox();
|
||||||
|
@ -309,8 +310,6 @@ private:
|
||||||
D3DPal *Palettes;
|
D3DPal *Palettes;
|
||||||
D3DTex *Textures;
|
D3DTex *Textures;
|
||||||
|
|
||||||
int WipeTime;
|
|
||||||
|
|
||||||
IDirect3DDevice9 *D3DDevice;
|
IDirect3DDevice9 *D3DDevice;
|
||||||
IDirect3DVertexBuffer9 *VertexBuffer;
|
IDirect3DVertexBuffer9 *VertexBuffer;
|
||||||
IDirect3DTexture9 *FBTexture;
|
IDirect3DTexture9 *FBTexture;
|
||||||
|
@ -323,12 +322,33 @@ private:
|
||||||
IDirect3DPixelShader9 *PlainStencilShader;
|
IDirect3DPixelShader9 *PlainStencilShader;
|
||||||
IDirect3DPixelShader9 *DimShader;
|
IDirect3DPixelShader9 *DimShader;
|
||||||
IDirect3DPixelShader9 *GammaFixerShader;
|
IDirect3DPixelShader9 *GammaFixerShader;
|
||||||
|
IDirect3DPixelShader9 *BurnShader;
|
||||||
IDirect3DSurface9 *OldRenderTarget;
|
IDirect3DSurface9 *OldRenderTarget;
|
||||||
IDirect3DTexture9 *InitialWipeScreen, *FinalWipeScreen;
|
IDirect3DTexture9 *InitialWipeScreen, *FinalWipeScreen;
|
||||||
|
|
||||||
D3DFB() {}
|
D3DFB() {}
|
||||||
|
|
||||||
|
class Wiper
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual ~Wiper();
|
||||||
|
virtual bool Run(int ticks, D3DFB *fb) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
class Wiper_Melt; friend class Wiper_Melt;
|
||||||
|
class Wiper_Burn; friend class Wiper_Burn;
|
||||||
|
class Wiper_Crossfade; friend class Wiper_Crossfade;
|
||||||
|
|
||||||
|
Wiper *ScreenWipe;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct FBVERTEX
|
||||||
|
{
|
||||||
|
FLOAT x, y, z, rhw;
|
||||||
|
FLOAT tu, tv;
|
||||||
|
};
|
||||||
|
#define D3DFVF_FBVERTEX (D3DFVF_XYZRHW|D3DFVF_TEX1)
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
#define STARTLOG do { if (!dbg) dbg = fopen ("k:/vid.log", "w"); } while(0)
|
#define STARTLOG do { if (!dbg) dbg = fopen ("k:/vid.log", "w"); } while(0)
|
||||||
#define STOPLOG do { if (dbg) { fclose (dbg); dbg=NULL; } } while(0)
|
#define STOPLOG do { if (dbg) { fclose (dbg); dbg=NULL; } } while(0)
|
||||||
|
|
1242
zdoom.vcproj
1242
zdoom.vcproj
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue