- Untested wipe refactor
# Conflicts: # src/gl/renderer/gl_renderer.cpp # src/gl/system/gl_wipe.cpp # src/hwrenderer/scene/hw_attributebuffer.cpp
This commit is contained in:
parent
ecf6e3f620
commit
9af01c4667
11 changed files with 363 additions and 517 deletions
284
src/f_wipe.cpp
284
src/f_wipe.cpp
|
|
@ -27,6 +27,36 @@
|
|||
#include "m_random.h"
|
||||
#include "f_wipe.h"
|
||||
#include "templates.h"
|
||||
#include "textures/bitmap.h"
|
||||
#include "hwrenderer/textures/hw_material.h"
|
||||
|
||||
class FBurnTexture : public FTexture
|
||||
{
|
||||
uint32_t *WorkBuffer;
|
||||
public:
|
||||
FBurnTexture(int w, int h)
|
||||
{
|
||||
Width = w;
|
||||
Height = h;
|
||||
WorkBuffer = new uint32_t[w * h];
|
||||
}
|
||||
|
||||
~FBurnTexture()
|
||||
{
|
||||
delete [] WorkBuffer;
|
||||
}
|
||||
|
||||
int CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rotate, FCopyInfo *inf) override
|
||||
{
|
||||
bmp->CopyPixelDataRGB(x, y, (uint8_t*)WorkBuffer, Width, Height, 4, Width*4, rotate, CF_RGBA, inf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t *GetBuffer()
|
||||
{
|
||||
return WorkBuffer;
|
||||
}
|
||||
};
|
||||
|
||||
int wipe_CalcBurn (uint8_t *burnarray, int width, int height, int density)
|
||||
{
|
||||
|
|
@ -112,3 +142,257 @@ int wipe_CalcBurn (uint8_t *burnarray, int width, int height, int density)
|
|||
return -1;
|
||||
}
|
||||
|
||||
|
||||
// TYPES -------------------------------------------------------------------
|
||||
|
||||
class Wiper_Crossfade : public Wiper
|
||||
{
|
||||
public:
|
||||
bool Run(int ticks) override;
|
||||
|
||||
private:
|
||||
int Clock = 0;
|
||||
};
|
||||
|
||||
class Wiper_Melt : public Wiper
|
||||
{
|
||||
public:
|
||||
Wiper_Melt();
|
||||
bool Run(int ticks) override;
|
||||
|
||||
private:
|
||||
static const int WIDTH = 320, HEIGHT = 200;
|
||||
int y[WIDTH];
|
||||
};
|
||||
|
||||
class Wiper_Burn : public Wiper
|
||||
{
|
||||
public:
|
||||
Wiper_Burn();
|
||||
~Wiper_Burn();
|
||||
bool Run(int ticks) override;
|
||||
void SetTextures(FTexture *startscreen, FTexture *endscreen) override;
|
||||
|
||||
private:
|
||||
static const int WIDTH = 64, HEIGHT = 64;
|
||||
uint8_t BurnArray[WIDTH * (HEIGHT + 5)] = {0};
|
||||
FBurnTexture *BurnTexture = nullptr;
|
||||
int Density = 4;
|
||||
int BurnTime = 8;
|
||||
};
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// Screen wipes
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
Wiper *Wiper::Create(int type)
|
||||
{
|
||||
switch(type)
|
||||
{
|
||||
case wipe_Burn:
|
||||
return new Wiper_Burn;
|
||||
|
||||
case wipe_Fade:
|
||||
return new Wiper_Crossfade;
|
||||
|
||||
case wipe_Melt:
|
||||
return new Wiper_Melt;
|
||||
|
||||
default:
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// OpenGLFrameBuffer :: WipeCleanup
|
||||
//
|
||||
// Release any resources that were specifically created for the wipe.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
Wiper::~Wiper()
|
||||
{
|
||||
if (startScreen != nullptr) delete startScreen;
|
||||
if (endScreen != nullptr) delete endScreen;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// WIPE: CROSSFADE ---------------------------------------------------------
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// OpenGLFrameBuffer :: Wiper_Crossfade :: Run
|
||||
//
|
||||
// Fades the old screen into the new one over 32 ticks.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
bool Wiper_Crossfade::Run(int ticks)
|
||||
{
|
||||
Clock += ticks;
|
||||
screen->DrawTexture(startScreen, 0, 0, TAG_DONE);
|
||||
screen->DrawTexture(endScreen, 0, 0, DTA_Alpha, clamp(Clock / 32.f, 0.f, 1.f), TAG_DONE);
|
||||
return Clock >= 32;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// OpenGLFrameBuffer :: Wiper_Melt Constructor
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// OpenGLFrameBuffer :: Wiper_Melt :: Run
|
||||
//
|
||||
// Melts the old screen into the new one over 32 ticks.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
bool Wiper_Melt::Run(int ticks)
|
||||
{
|
||||
bool done;
|
||||
screen->DrawTexture(endScreen, 0, 0, TAG_DONE);
|
||||
|
||||
// Copy the old screen in vertical strips on top of the new one.
|
||||
while (ticks--)
|
||||
{
|
||||
done = true;
|
||||
for (int i = 0; i < WIDTH; i++)
|
||||
{
|
||||
if (y[i] < 0)
|
||||
{
|
||||
y[i]++;
|
||||
done = false;
|
||||
}
|
||||
else if (y[i] < HEIGHT)
|
||||
{
|
||||
int dy = (y[i] < 16) ? y[i] + 1 : 8;
|
||||
y[i] = MIN(y[i] + dy, HEIGHT);
|
||||
done = false;
|
||||
}
|
||||
if (ticks == 0)
|
||||
{
|
||||
struct {
|
||||
int32_t x;
|
||||
int32_t y;
|
||||
} dpt;
|
||||
struct {
|
||||
int32_t left;
|
||||
int32_t top;
|
||||
int32_t right;
|
||||
int32_t bottom;
|
||||
} rect;
|
||||
|
||||
// Only draw for the final tick.
|
||||
// No need for optimization. Wipes won't ever be drawn with anything else.
|
||||
|
||||
int w = startScreen->GetWidth();
|
||||
int h = startScreen->GetHeight();
|
||||
dpt.x = i * h / WIDTH;
|
||||
dpt.y = MAX(0, y[i] * h / HEIGHT);
|
||||
rect.left = dpt.x;
|
||||
rect.top = 0;
|
||||
rect.right = (i + 1) * w / WIDTH;
|
||||
rect.bottom = w - dpt.y;
|
||||
if (rect.bottom > rect.top)
|
||||
{
|
||||
screen->DrawTexture(startScreen, 0, rect.top, DTA_ClipLeft, rect.left, DTA_ClipRight, rect.right, TAG_DONE);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return done;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// OpenGLFrameBuffer :: Wiper_Burn Constructor
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void Wiper_Burn::SetTextures(FTexture *startscreen, FTexture *endscreen)
|
||||
{
|
||||
startScreen = startscreen;
|
||||
endScreen = endscreen;
|
||||
BurnTexture = new FBurnTexture(WIDTH, HEIGHT);
|
||||
auto mat = FMaterial::ValidateTexture(startscreen, false);
|
||||
mat->AddTextureLayer(BurnTexture);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// OpenGLFrameBuffer :: Wiper_Burn Destructor
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
Wiper_Burn::~Wiper_Burn()
|
||||
{
|
||||
if (BurnTexture != nullptr) delete BurnTexture;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// OpenGLFrameBuffer :: Wiper_Burn :: Run
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
bool Wiper_Burn::Run(int ticks)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
auto mat = FMaterial::ValidateTexture(BurnTexture, false);
|
||||
mat->Clean(true);
|
||||
const uint8_t *src = BurnArray;
|
||||
uint32_t *dest = (uint32_t *)BurnTexture->GetBuffer();
|
||||
for (int y = HEIGHT; y != 0; --y)
|
||||
{
|
||||
for (int x = WIDTH; x != 0; --x)
|
||||
{
|
||||
uint8_t s = clamp<int>((*src++)*2, 0, 255);
|
||||
*dest++ = MAKEARGB(s,255,255,255);
|
||||
}
|
||||
}
|
||||
|
||||
screen->DrawTexture(startScreen, 0, 0, TAG_DONE);
|
||||
screen->DrawTexture(endScreen, 0, 0, DTA_Burn, true, TAG_DONE);
|
||||
|
||||
// The fire may not always stabilize, so the wipe is forced to end
|
||||
// after an arbitrary maximum time.
|
||||
return done || (BurnTime > 40);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue