- cleanup of savegame picture code.

* re-added screen blends for images from the hardware renderer.
* moved all postprocessing of the image out of the renderers.
* cleaned out a large piece of cruft for handling the palette in the frame buffer class. This was all a remnant of the old paletted backend that no longer exists. Nowadays the screen blend is just a postprocessing effect drawn over the 3D screen, there is no need to maintain any of it as global state anymore.
* since the engine doesn't produce paletted screenshots anymore there is no need to have handling for it in the generation code. This depended on otherwise obsolete information so it got removed along with that information.
This commit is contained in:
Christoph Oelckers 2019-03-09 14:48:14 +01:00
parent 392ba7ed2e
commit b7d09c95dd
14 changed files with 62 additions and 120 deletions

View File

@ -1294,7 +1294,6 @@ void C_FullConsole ()
primaryLevel->Music = "";
S_Start ();
P_FreeLevelData ();
V_SetBlend (0,0,0,0);
}
else
{

View File

@ -1247,7 +1247,6 @@ void D_DoAdvanceDemo (void)
return;
}
V_SetBlend (0,0,0,0);
players[consoleplayer].playerstate = PST_LIVE; // not reborn
usergame = false; // no save / end game here
paused = 0;
@ -2698,8 +2697,6 @@ void D_DoomMain (void)
}
else
{
// let the renderer reinitialize some stuff if needed
screen->InitPalette();
// These calls from inside V_Init2 are still necessary
C_NewModeAdjust();
D_StartTitle (); // start up intro loop

View File

@ -2100,6 +2100,56 @@ static void PutSaveComment (FSerializer &arc)
arc.AddString("Comment", comment);
}
void DoWriteSavePic(FileWriter *file, ESSType ssformat, uint8_t *scr, int width, int height, sector_t *viewsector, bool upsidedown)
{
PalEntry palette[256];
PalEntry modulateColor;
auto blend = screen->CalcBlend(viewsector, &modulateColor);
int pixelsize = 1;
// Apply the screen blend, because the renderer does not provide this.
if (ssformat == SS_RGB)
{
int numbytes = width * height * 3;
pixelsize = 3;
if (modulateColor != 0xffffffff)
{
float r = modulateColor.r / 255.f;
float g = modulateColor.g / 255.f;
float b = modulateColor.b / 255.f;
for (int i = 0; i < numbytes; i += 3)
{
scr[i] = uint8_t(scr[i] * r);
scr[i + 1] = uint8_t(scr[i + 1] * g);
scr[i + 2] = uint8_t(scr[i + 2] * b);
}
}
float iblendfac = 1.f - blend.W;
blend.X *= blend.W;
blend.Y *= blend.W;
blend.Z *= blend.W;
for (int i = 0; i < numbytes; i += 3)
{
scr[i] = uint8_t(scr[i] * iblendfac + blend.X);
scr[i + 1] = uint8_t(scr[i + 1] * iblendfac + blend.Y);
scr[i + 2] = uint8_t(scr[i + 2] * iblendfac + blend.Z);
}
}
else
{
// Apply the screen blend to the palette. The colormap related parts get skipped here because these are already part of the image.
DoBlending(GPalette.BaseColors, palette, 256, uint8_t(blend.X), uint8_t(blend.Y), uint8_t(blend.Z), uint8_t(blend.W*255));
}
int pitch = width * pixelsize;
if (upsidedown)
{
scr += ((height - 1) * width * pixelsize);
pitch *= -1;
}
M_CreatePNG(file, scr, ssformat == SS_PAL? palette : nullptr, ssformat, width, height, pitch, Gamma);
}
static void PutSavePic (FileWriter *file, int width, int height)
{
if (width <= 0 || height <= 0 || !storesavepic)

View File

@ -173,7 +173,7 @@ TArray<uint8_t> FImageSource::GetPalettedPixels(int conversion)
int FImageSource::CopyPixels(FBitmap *bmp, int conversion)
{
if (conversion == luminance) conversion = normal; // luminance images have no use as an RGB source.
PalEntry *palette = screen->GetPalette();
PalEntry *palette = GPalette.BaseColors;
for(int i=1;i<256;i++) palette[i].a = 255; // set proper alpha values
auto ppix = CreatePalettedPixels(conversion);
bmp->CopyPixelData(0, 0, ppix.Data(), Width, Height, Height, 1, 0, palette, nullptr);

View File

@ -211,7 +211,6 @@ int DIntermissionScreenFader::Responder (event_t *ev)
{
if (ev->type == EV_KeyDown)
{
V_SetBlend(0,0,0,0);
return -1;
}
return Super::Responder(ev);
@ -852,7 +851,6 @@ void F_StartIntermission(FIntermissionDescriptor *desc, bool deleteme, uint8_t s
{
DIntermissionController::CurrentIntermission->Destroy();
}
V_SetBlend (0,0,0,0);
S_StopAllChannels ();
gameaction = ga_nothing;
gamestate = GS_FINALE;

View File

@ -612,12 +612,6 @@ void M_ScreenShot (const char *filename)
auto buffer = screen->GetScreenshotBuffer(pitch, color_type, gamma);
if (buffer.Size() > 0)
{
PalEntry palette[256];
if (color_type == SS_PAL)
{
screen->GetFlashedPalette(palette);
}
file = FileWriter::Open(autoname);
if (file == NULL)
{
@ -626,12 +620,12 @@ void M_ScreenShot (const char *filename)
}
if (writepcx)
{
WritePCXfile(file, buffer.Data(), palette, color_type,
WritePCXfile(file, buffer.Data(), nullptr, color_type,
screen->GetWidth(), screen->GetHeight(), pitch);
}
else
{
WritePNGfile(file, buffer.Data(), palette, color_type,
WritePNGfile(file, buffer.Data(), nullptr, color_type,
screen->GetWidth(), screen->GetHeight(), pitch, gamma);
}
delete file;

View File

@ -67,6 +67,8 @@ EXTERN_CVAR(Bool, cl_capfps)
extern bool NoInterpolateView;
void DoWriteSavePic(FileWriter *file, ESSType ssformat, uint8_t *scr, int width, int height, sector_t *viewsector, bool upsidedown);
namespace OpenGLRenderer
{
@ -370,9 +372,11 @@ void FGLRenderer::WriteSavePic (player_t *player, FileWriter *file, int width, i
// strictly speaking not needed as the glReadPixels should block until the scene is rendered, but this is to safeguard against shitty drivers
glFinish();
uint8_t * scr = (uint8_t *)M_Malloc(width * height * 3);
int numpixels = width * height;
uint8_t * scr = (uint8_t *)M_Malloc(numpixels * 3);
glReadPixels(0,0,width, height,GL_RGB,GL_UNSIGNED_BYTE,scr);
M_CreatePNG (file, scr + ((height-1) * width * 3), NULL, SS_RGB, width, height, -width * 3, Gamma);
DoWriteSavePic(file, SS_RGB, scr, width, height, viewsector, true);
M_Free(scr);
// Switch back the screen render buffers

View File

@ -208,10 +208,11 @@ void FSoftwareRenderer::RenderView(player_t *player, DCanvas *target, void *vide
});
}
void DoWriteSavePic(FileWriter *file, ESSType ssformat, uint8_t *scr, int width, int height, sector_t *viewsector, bool upsidedown);
void FSoftwareRenderer::WriteSavePic (player_t *player, FileWriter *file, int width, int height)
{
DCanvas pic(width, height, false);
PalEntry palette[256];
// Take a snapshot of the player's view
if (V_IsPolyRenderer())
@ -230,11 +231,7 @@ void FSoftwareRenderer::WriteSavePic (player_t *player, FileWriter *file, int wi
r_viewpoint = mScene.MainThread()->Viewport->viewpoint;
r_viewwindow = mScene.MainThread()->Viewport->viewwindow;
}
auto blend = screen->CalcBlend(r_viewpoint.sector, nullptr);
const PalEntry bcolor(255, uint8_t(blend.X), uint8_t(blend.Y), uint8_t(blend.Z));
screen->SetFlash(bcolor, int(blend.W * 256));
screen->GetFlashedPalette (palette);
M_CreatePNG (file, pic.GetPixels(), palette, SS_PAL, width, height, pic.GetPitch(), Gamma);
DoWriteSavePic(file, SS_PAL, pic.GetPixels(), width, height, r_viewpoint.sector, false);
}
void FSoftwareRenderer::DrawRemainingPlayerSprites()

View File

@ -202,11 +202,6 @@ void DFrameBuffer::DrawRateStuff ()
//
//==========================================================================
void DFrameBuffer::GetFlashedPalette(PalEntry pal[256])
{
DoBlending(SourcePalette, pal, 256, Flash.r, Flash.g, Flash.b, Flash.a);
}
void DFrameBuffer::Update()
{
CheckBench();
@ -225,24 +220,6 @@ void DFrameBuffer::Update()
}
}
PalEntry *DFrameBuffer::GetPalette()
{
return SourcePalette;
}
bool DFrameBuffer::SetFlash(PalEntry rgb, int amount)
{
Flash = PalEntry(amount, rgb.r, rgb.g, rgb.b);
return true;
}
void DFrameBuffer::GetFlash(PalEntry &rgb, int &amount)
{
rgb = Flash;
rgb.a = 0;
amount = Flash.a;
}
void DFrameBuffer::SetClearColor(int color)
{
PalEntry pe = GPalette.BaseColors[color];
@ -293,18 +270,6 @@ FTexture *DFrameBuffer::WipeEndScreen()
return nullptr;
}
//==========================================================================
//
// DFrameBuffer :: InitPalette
//
//==========================================================================
void DFrameBuffer::InitPalette()
{
memcpy(SourcePalette, GPalette.BaseColors, sizeof(PalEntry) * 256);
UpdatePalette();
}
//==========================================================================
//
// DFrameBuffer :: GetCaps

View File

@ -443,29 +443,6 @@ void DoBlending (const PalEntry *from, PalEntry *to, int count, int r, int g, in
}
}
void V_SetBlend (int blendr, int blendg, int blendb, int blenda)
{
// Don't do anything if the new blend is the same as the old
if (((blenda|BlendA) == 0) ||
(blendr == BlendR &&
blendg == BlendG &&
blendb == BlendB &&
blenda == BlendA))
return;
V_ForceBlend (blendr, blendg, blendb, blenda);
}
void V_ForceBlend (int blendr, int blendg, int blendb, int blenda)
{
BlendR = blendr;
BlendG = blendg;
BlendB = blendb;
BlendA = blenda;
screen->SetFlash (PalEntry (BlendR, BlendG, BlendB), BlendA);
}
CCMD (testblend)
{
FString colorstring;

View File

@ -77,23 +77,6 @@ void DoBlending (const PalEntry *from, PalEntry *to, int count, int r, int g, in
void ReadPalette(int lumpnum, uint8_t *buffer);
void InitPalette ();
// V_SetBlend()
// input: blendr: red component of blend
// blendg: green component of blend
// blendb: blue component of blend
// blenda: alpha component of blend
//
// Applies the blend to all palettes with PALETTEF_BLEND flag
void V_SetBlend (int blendr, int blendg, int blendb, int blenda);
// V_ForceBlend()
//
// Normally, V_SetBlend() does nothing if the new blend is the
// same as the old. This function will perform the blending
// even if the blend hasn't changed.
void V_ForceBlend (int blendr, int blendg, int blendb, int blenda);
EXTERN_CVAR (Int, paletteflash)
enum PaletteFlashFlags
{

View File

@ -696,9 +696,6 @@ void V_Init (bool restart)
// Update screen palette when restarting
else
{
PalEntry *palette = screen->GetPalette ();
for (int i = 0; i < 256; ++i)
*palette++ = GPalette.BaseColors[i];
screen->UpdatePalette();
}

View File

@ -352,9 +352,6 @@ private:
protected:
int clipleft = 0, cliptop = 0, clipwidth = -1, clipheight = -1;
PalEntry Flash = 0; // Only needed to support some cruft in the interface that only makes sense for the software renderer
PalEntry SourcePalette[256]; // This is where unpaletted textures get their palette from
public:
// Hardware render state that needs to be exposed to the API independent part of the renderer. For ease of access this is stored in the base class.
int hwcaps = 0; // Capability flags
@ -404,26 +401,12 @@ public:
// Make the surface visible.
virtual void Update ();
// Return a pointer to 256 palette entries that can be written to.
PalEntry *GetPalette ();
// Stores the palette with flash blended in into 256 dwords
void GetFlashedPalette (PalEntry palette[256]);
// Mark the palette as changed. It will be updated on the next Update().
virtual void UpdatePalette() {}
virtual void SetGamma() {}
// Sets a color flash. RGB is the color, and amount is 0-256, with 256
// being all flash and 0 being no flash. Returns false if the hardware
// does not support this. (Always true for now, since palettes can always
// be flashed.)
bool SetFlash (PalEntry rgb, int amount);
// Converse of SetFlash
void GetFlash (PalEntry &rgb, int &amount);
// Returns true if running fullscreen.
virtual bool IsFullscreen () = 0;
virtual void ToggleFullscreen(bool yes) {}
@ -475,7 +458,6 @@ public:
}
// Report a game restart
void InitPalette();
void SetClearColor(int color);
virtual uint32_t GetCaps();
virtual void WriteSavePic(player_t *player, FileWriter *file, int width, int height);

View File

@ -761,7 +761,6 @@ void WI_Start(wbstartstruct_t *wbstartstruct)
}
}
V_SetBlend(0, 0, 0, 0);
S_StopAllChannels();
for (auto Level : AllLevels())
{