Merge remote-tracking branch 'gzdoom/master' into asmjit

This commit is contained in:
Magnus Norddahl 2018-09-14 02:09:17 +02:00
commit 4e85134d8e
42 changed files with 875 additions and 974 deletions

View file

@ -1044,6 +1044,7 @@ set (PCH_SOURCES
g_statusbar/shared_sbar.cpp
gl/data/gl_vertexbuffer.cpp
gl/data/gl_uniformbuffer.cpp
gl/data/gl_viewpointbuffer.cpp
gl/dynlights/gl_lightbuffer.cpp
gl/dynlights/gl_shadowmap.cpp
gl/models/gl_models.cpp
@ -1061,7 +1062,6 @@ set (PCH_SOURCES
gl_load/gl_interface.cpp
gl/system/gl_framebuffer.cpp
gl/system/gl_debug.cpp
gl/system/gl_wipe.cpp
gl/textures/gl_hwtexture.cpp
gl/textures/gl_samplers.cpp
hwrenderer/data/flatvertices.cpp

View file

@ -638,7 +638,8 @@ CVAR(Bool, vid_activeinbackground, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
void D_Display ()
{
bool wipe;
FTexture *wipe = nullptr;
int wipe_type;
sector_t *viewsec;
if (nodrawers || screen == NULL)
@ -703,142 +704,130 @@ void D_Display ()
if (NoWipe)
{
NoWipe--;
wipe = false;
wipe = nullptr;
wipegamestate = gamestate;
}
// No wipes when in a stereo3D VR mode
else if (gamestate != wipegamestate && gamestate != GS_FULLCONSOLE && gamestate != GS_TITLELEVEL && (vr_mode == 0 || vid_rendermode != 4))
{ // save the current screen if about to wipe
wipe = screen->WipeStartScreen ();
switch (wipegamestate)
{
default:
wipe = screen->WipeStartScreen (wipetype);
wipe_type = wipetype;
break;
case GS_FORCEWIPEFADE:
wipe = screen->WipeStartScreen (wipe_Fade);
wipe_type = wipe_Fade;
break;
case GS_FORCEWIPEBURN:
wipe = screen->WipeStartScreen (wipe_Burn);
wipe_type =wipe_Burn;
break;
case GS_FORCEWIPEMELT:
wipe = screen->WipeStartScreen (wipe_Melt);
wipe_type = wipe_Melt;
break;
}
wipegamestate = gamestate;
}
else
{
wipe = false;
wipe = nullptr;
}
screen->FrameTime = I_msTimeFS();
TexMan.UpdateAnimations(screen->FrameTime);
R_UpdateSky(screen->FrameTime);
screen->BeginFrame();
screen->ClearClipRect();
if ((gamestate == GS_LEVEL || gamestate == GS_TITLELEVEL) && gametic != 0)
{
screen->FrameTime = I_msTimeFS();
TexMan.UpdateAnimations(screen->FrameTime);
R_UpdateSky(screen->FrameTime);
screen->BeginFrame();
screen->ClearClipRect();
// [ZZ] execute event hook that we just started the frame
//E_RenderFrame();
//
// Check for the presence of dynamic lights at the start of the frame once.
if ((gl_lights && vid_rendermode == 4) || (r_dynlights && vid_rendermode != 4))
{
TThinkerIterator<ADynamicLight> it(STAT_DLIGHT);
level.HasDynamicLights = !!it.Next();
}
else level.HasDynamicLights = false; // lights are off so effectively we have none.
viewsec = screen->RenderView(&players[consoleplayer]);
screen->Begin2D();
screen->DrawBlend(viewsec);
if (automapactive)
{
AM_Drawer (hud_althud? viewheight : StatusBar->GetTopOfStatusbar());
}
if (!automapactive || viewactive)
{
screen->RefreshViewBorder ();
}
// for timing the statusbar code.
//cycle_t stb;
//stb.Reset();
//stb.Clock();
if (hud_althud && viewheight == SCREENHEIGHT && screenblocks > 10)
{
StatusBar->DrawBottomStuff (HUD_AltHud);
if (DrawFSHUD || automapactive) DrawHUD();
if (players[consoleplayer].camera && players[consoleplayer].camera->player && !automapactive)
{
StatusBar->DrawCrosshair();
}
StatusBar->CallDraw (HUD_AltHud, vp.TicFrac);
StatusBar->DrawTopStuff (HUD_AltHud);
}
else if (viewheight == SCREENHEIGHT && viewactive && screenblocks > 10)
{
EHudState state = DrawFSHUD ? HUD_Fullscreen : HUD_None;
StatusBar->DrawBottomStuff (state);
StatusBar->CallDraw (state, vp.TicFrac);
StatusBar->DrawTopStuff (state);
}
else
{
StatusBar->DrawBottomStuff (HUD_StatusBar);
StatusBar->CallDraw (HUD_StatusBar, vp.TicFrac);
StatusBar->DrawTopStuff (HUD_StatusBar);
}
//stb.Unclock();
//Printf("Stbar = %f\n", stb.TimeMS());
}
else
{
screen->Begin2D();
switch (gamestate)
{
case GS_FULLCONSOLE:
screen->Begin2D(false);
C_DrawConsole ();
M_Drawer ();
screen->End2D();
screen->Update ();
return;
case GS_LEVEL:
case GS_TITLELEVEL:
if (!gametic)
{
screen->Begin2D(false);
case GS_FULLCONSOLE:
screen->Begin2D();
C_DrawConsole ();
M_Drawer ();
screen->End2DAndUpdate ();
return;
case GS_INTERMISSION:
WI_Drawer ();
break;
case GS_FINALE:
F_Drawer ();
break;
case GS_DEMOSCREEN:
D_PageDrawer ();
break;
default:
break;
}
// [ZZ] execute event hook that we just started the frame
//E_RenderFrame();
//
// Check for the presence of dynamic lights at the start of the frame once.
if ((gl_lights && vid_rendermode == 4) || (r_dynlights && vid_rendermode != 4))
{
TThinkerIterator<ADynamicLight> it(STAT_DLIGHT);
level.HasDynamicLights = !!it.Next();
}
else level.HasDynamicLights = false; // lights are off so effectively we have none.
viewsec = screen->RenderView(&players[consoleplayer]);
screen->Begin2D(false);
screen->DrawBlend(viewsec);
// returns with 2S mode set.
if (automapactive)
{
AM_Drawer (hud_althud? viewheight : StatusBar->GetTopOfStatusbar());
}
if (!automapactive || viewactive)
{
screen->RefreshViewBorder ();
}
// for timing the statusbar code.
//cycle_t stb;
//stb.Reset();
//stb.Clock();
if (hud_althud && viewheight == SCREENHEIGHT && screenblocks > 10)
{
StatusBar->DrawBottomStuff (HUD_AltHud);
if (DrawFSHUD || automapactive) DrawHUD();
if (players[consoleplayer].camera && players[consoleplayer].camera->player && !automapactive)
{
StatusBar->DrawCrosshair();
}
StatusBar->CallDraw (HUD_AltHud, vp.TicFrac);
StatusBar->DrawTopStuff (HUD_AltHud);
}
else
if (viewheight == SCREENHEIGHT && viewactive && screenblocks > 10)
{
EHudState state = DrawFSHUD ? HUD_Fullscreen : HUD_None;
StatusBar->DrawBottomStuff (state);
StatusBar->CallDraw (state, vp.TicFrac);
StatusBar->DrawTopStuff (state);
}
else
{
StatusBar->DrawBottomStuff (HUD_StatusBar);
StatusBar->CallDraw (HUD_StatusBar, vp.TicFrac);
StatusBar->DrawTopStuff (HUD_StatusBar);
}
//stb.Unclock();
//Printf("Stbar = %f\n", stb.TimeMS());
CT_Drawer ();
break;
case GS_INTERMISSION:
screen->Begin2D(false);
WI_Drawer ();
CT_Drawer ();
break;
case GS_FINALE:
screen->Begin2D(false);
F_Drawer ();
CT_Drawer ();
break;
case GS_DEMOSCREEN:
screen->Begin2D(false);
D_PageDrawer ();
CT_Drawer ();
break;
default:
break;
}
}
CT_Drawer ();
// draw pause pic
if ((paused || pauseext) && menuactive == MENU_Off)
{
@ -879,15 +868,17 @@ void D_Display ()
GSnd->DrawWaveDebug(snd_drawoutput);
}
if (!wipe || NoWipe < 0)
if (!wipe || NoWipe < 0 || wipe_type == wipe_None)
{
if (wipe != nullptr) delete wipe;
wipe = nullptr;
NetUpdate (); // send out any new accumulation
// normal update
// draw ZScript UI stuff
C_DrawConsole (); // draw console
M_Drawer (); // menu is drawn even on top of everything
FStat::PrintStat ();
screen->Update (); // page flip or blit buffer
screen->End2DAndUpdate ();
}
else
{
@ -897,7 +888,10 @@ void D_Display ()
GSnd->SetSfxPaused(true, 1);
I_FreezeTime(true);
screen->WipeEndScreen ();
screen->End2D();
auto wipend = screen->WipeEndScreen ();
auto wiper = Wiper::Create(wipe_type);
wiper->SetTextures(wipe, wipend);
wipestart = I_msTime();
NetUpdate(); // send out any new accumulation
@ -911,17 +905,17 @@ void D_Display ()
diff = (nowtime - wipestart) * 40 / 1000; // Using 35 here feels too slow.
} while (diff < 1);
wipestart = nowtime;
done = screen->WipeDo (1);
screen->Begin2D();
done = wiper->Run(1);
C_DrawConsole (); // console and
M_Drawer (); // menu are drawn even on top of wipes
screen->Update (); // page flip or blit buffer
screen->End2DAndUpdate ();
NetUpdate (); // [RH] not sure this is needed anymore
} while (!done);
screen->WipeCleanup();
delete wiper;
I_FreezeTime(false);
GSnd->SetSfxPaused(false, 1);
}
screen->End2D();
cycles.Unclock();
FrameCycles = cycles;
}

View file

@ -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,256 @@ 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();
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, DTA_FlipY, screen->RenderTextureIsFlipped(), DTA_Masked, false, TAG_DONE);
screen->DrawTexture(endScreen, 0, 0, DTA_FlipY, screen->RenderTextureIsFlipped(), DTA_Masked, false, 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, DTA_FlipY, screen->RenderTextureIsFlipped(), DTA_Masked, false, 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 * w / WIDTH;
dpt.y = MAX(0, y[i] * h / HEIGHT);
rect.left = dpt.x;
rect.top = 0;
rect.right = (i + 1) * w / WIDTH;
rect.bottom = h - dpt.y;
if (rect.bottom > rect.top)
{
screen->DrawTexture(startScreen, 0, dpt.y, DTA_FlipY, screen->RenderTextureIsFlipped(), DTA_ClipLeft, rect.left, DTA_ClipRight, rect.right, DTA_Masked, false, 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, DTA_FlipY, screen->RenderTextureIsFlipped(), DTA_Masked, false, TAG_DONE);
screen->DrawTexture(endScreen, 0, 0, DTA_FlipY, screen->RenderTextureIsFlipped(), DTA_Burn, true, DTA_Masked, false, TAG_DONE);
// The fire may not always stabilize, so the wipe is forced to end
// after an arbitrary maximum time.
return done || (BurnTime > 40);
}

View file

@ -26,19 +26,9 @@
#ifndef __F_WIPE_H__
#define __F_WIPE_H__
//
// SCREEN WIPE PACKAGE
//
#include "stdint.h"
#if 0
bool wipe_StartScreen (int type);
void wipe_EndScreen (void);
bool wipe_ScreenWipe (int ticks);
void wipe_Cleanup ();
// The buffer must have an additional 5 rows not included in height
// to use for a seeding area.
#endif
class FTexture;
int wipe_CalcBurn(uint8_t *buffer, int width, int height, int density);
enum
@ -50,4 +40,21 @@ enum
wipe_NUMWIPES
};
class Wiper
{
protected:
FTexture *startScreen = nullptr, *endScreen = nullptr;
public:
virtual ~Wiper();
virtual bool Run(int ticks) = 0;
virtual void SetTextures(FTexture *startscreen, FTexture *endscreen)
{
startScreen = startscreen;
endScreen = endscreen;
}
static Wiper *Create(int type);
};
#endif

View file

@ -0,0 +1,176 @@
//
//---------------------------------------------------------------------------
//
// Copyright(C) 2018 Christoph Oelckers
// All rights reserved.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with this program. If not, see http://www.gnu.org/licenses/
//
//--------------------------------------------------------------------------
//
/*
** gl_viewpointbuffer.cpp
** Buffer data maintenance for per viewpoint uniform data
**
**/
#include "gl_load/gl_system.h"
#include "gl_load/gl_interface.h"
#include "hwrenderer/data/shaderuniforms.h"
#include "hwrenderer/scene/hw_viewpointuniforms.h"
#include "gl_viewpointbuffer.h"
static const int INITIAL_BUFFER_SIZE = 100; // 100 viewpoints per frame should nearly always be enough
GLViewpointBuffer::GLViewpointBuffer()
{
mBufferSize = INITIAL_BUFFER_SIZE;
mBlockAlign = ((sizeof(HWViewpointUniforms) / gl.uniformblockalignment) + 1) * gl.uniformblockalignment;
mByteSize = mBufferSize * mBlockAlign;
Allocate();
Clear();
mLastMappedIndex = UINT_MAX;
mClipPlaneInfo.Push(0);
}
GLViewpointBuffer::~GLViewpointBuffer()
{
glBindBuffer(GL_UNIFORM_BUFFER, 0);
glDeleteBuffers(1, &mBufferId);
}
void GLViewpointBuffer::Allocate()
{
glGenBuffers(1, &mBufferId);
glBindBufferBase(GL_UNIFORM_BUFFER, VIEWPOINT_BINDINGPOINT, mBufferId);
glBindBuffer(GL_UNIFORM_BUFFER, mBufferId); // Note: Some older AMD drivers don't do that in glBindBufferBase, as they should.
if (gl.flags & RFL_BUFFER_STORAGE)
{
glBufferStorage(GL_UNIFORM_BUFFER, mByteSize, NULL, GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT);
mBufferPointer = glMapBufferRange(GL_UNIFORM_BUFFER, 0, mByteSize, GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT);
}
else
{
glBufferData(GL_UNIFORM_BUFFER, mByteSize, NULL, GL_STATIC_DRAW);
mBufferPointer = NULL;
}
}
void GLViewpointBuffer::CheckSize()
{
if (mUploadIndex >= mBufferSize)
{
// reallocate the buffer with twice the size
unsigned int oldbuffer = mBufferId;
mBufferSize *= 2;
mByteSize *= 2;
// first unmap the old buffer
glBindBuffer(GL_UNIFORM_BUFFER, mBufferId);
glUnmapBuffer(GL_UNIFORM_BUFFER);
Allocate();
glBindBuffer(GL_COPY_READ_BUFFER, oldbuffer);
// copy contents and delete the old buffer.
glCopyBufferSubData(GL_COPY_READ_BUFFER, GL_UNIFORM_BUFFER, 0, 0, mByteSize / 2); // old size is half of the current one.
glBindBuffer(GL_COPY_READ_BUFFER, 0);
glDeleteBuffers(1, &oldbuffer);
}
}
void GLViewpointBuffer::Map()
{
if (!(gl.flags & RFL_BUFFER_STORAGE))
{
glBindBuffer(GL_UNIFORM_BUFFER, mBufferId);
mBufferPointer = (float*)glMapBufferRange(GL_UNIFORM_BUFFER, 0, mByteSize, GL_MAP_WRITE_BIT);
}
}
void GLViewpointBuffer::Unmap()
{
if (!(gl.flags & RFL_BUFFER_STORAGE))
{
glBindBuffer(GL_UNIFORM_BUFFER, mBufferId);
glUnmapBuffer(GL_UNIFORM_BUFFER);
mBufferPointer = nullptr;
}
else
{
glMemoryBarrier(GL_CLIENT_MAPPED_BUFFER_BARRIER_BIT);
}
}
int GLViewpointBuffer::Bind(unsigned int index)
{
if (index != mLastMappedIndex)
{
mLastMappedIndex = index;
glBindBufferRange(GL_UNIFORM_BUFFER, VIEWPOINT_BINDINGPOINT, mBufferId, index * mBlockAlign, mBlockAlign);
// Update the viewpoint-related clip plane setting.
if (!(gl.flags & RFL_NO_CLIP_PLANES))
{
if (mClipPlaneInfo[index])
{
glEnable(GL_CLIP_DISTANCE0);
}
else
{
glDisable(GL_CLIP_DISTANCE0);
}
}
}
return index;
}
void GLViewpointBuffer::Set2D(int width, int height)
{
if (width != m2DWidth || height != m2DHeight)
{
HWViewpointUniforms matrices;
matrices.SetDefaults();
matrices.mProjectionMatrix.ortho(0, width, height, 0, -1.0f, 1.0f);
matrices.mFogEnabled = 3;
matrices.CalcDependencies();
Map();
memcpy(mBufferPointer, &matrices, sizeof(matrices));
Unmap();
m2DWidth = width;
m2DHeight = height;
mLastMappedIndex = -1;
}
Bind(0);
}
int GLViewpointBuffer::SetViewpoint(HWViewpointUniforms *vp)
{
CheckSize();
Map();
memcpy(((char*)mBufferPointer) + mUploadIndex * mBlockAlign, vp, sizeof(*vp));
Unmap();
mClipPlaneInfo.Push(vp->mClipHeightDirection != 0.f || vp->mClipLine.X > -10000000.0f);
return Bind(mUploadIndex++);
}
void GLViewpointBuffer::Clear()
{
// Index 0 is reserved for the 2D projection.
mUploadIndex = 1;
mClipPlaneInfo.Resize(1);
}

View file

@ -0,0 +1,36 @@
#include "tarray.h"
struct HWViewpointUniforms;
class GLViewpointBuffer
{
unsigned int mBufferId;
unsigned int mBufferSize;
unsigned int mBlockAlign;
unsigned int mUploadIndex;
unsigned int mLastMappedIndex;
unsigned int mByteSize;
void * mBufferPointer;
TArray<bool> mClipPlaneInfo;
unsigned int m2DWidth = ~0u, m2DHeight = ~0u;
unsigned int mBlockSize;
void CheckSize();
void Allocate();
public:
GLViewpointBuffer();
~GLViewpointBuffer();
void Clear();
void Map();
void Unmap();
int Bind(unsigned int index);
void Set2D(int width, int height);
int SetViewpoint(HWViewpointUniforms *vp);
unsigned int GetBlockSize() const { return mBlockSize; }
};

View file

@ -103,10 +103,10 @@ void gl_SetColor(int sectorlightlevel, int rellight, bool fullbright, const FCol
}
else
{
int hwlightlevel = hw_CalcLightLevel(sectorlightlevel, rellight, weapon);
int hwlightlevel = hw_CalcLightLevel(sectorlightlevel, rellight, weapon, cm.BlendFactor);
PalEntry pe = hw_CalcLightColor(hwlightlevel, cm.LightColor, cm.BlendFactor);
gl_RenderState.SetColorAlpha(pe, alpha, cm.Desaturation);
gl_RenderState.SetSoftLightLevel(hw_ClampLight(sectorlightlevel + rellight));
gl_RenderState.SetSoftLightLevel(hw_ClampLight(sectorlightlevel + rellight), cm.BlendFactor);
}
}
@ -163,7 +163,7 @@ void gl_SetFog(int lightlevel, int rellight, bool fullbright, const FColormap *c
else if (cmap != NULL && !fullbright)
{
fogcolor = cmap->FadeColor;
fogdensity = hw_GetFogDensity(lightlevel, fogcolor, cmap->FogDensity);
fogdensity = hw_GetFogDensity(lightlevel, fogcolor, cmap->FogDensity, cmap->BlendFactor);
fogcolor.a=0;
}
else
@ -184,9 +184,9 @@ void gl_SetFog(int lightlevel, int rellight, bool fullbright, const FColormap *c
}
else
{
if (level.lightmode == 2 && fogcolor == 0)
if ((level.lightmode == 2 || (level.lightmode == 8 && cmap->BlendFactor > 0)) && fogcolor == 0)
{
float light = hw_CalcLightLevel(lightlevel, rellight, false);
float light = hw_CalcLightLevel(lightlevel, rellight, false, cmap->BlendFactor);
gl_SetShaderLight(light, lightlevel);
}
else
@ -205,7 +205,7 @@ void gl_SetFog(int lightlevel, int rellight, bool fullbright, const FColormap *c
gl_RenderState.SetFog(fogcolor, fogdensity);
// Korshun: fullbright fog like in software renderer.
if (level.lightmode == 8 && level.brightfog && fogdensity != 0 && fogcolor != 0)
if (level.lightmode == 8 && cmap->BlendFactor == 0 && level.brightfog && fogdensity != 0 && fogcolor != 0)
{
gl_RenderState.SetSoftLightLevel(255);
}

View file

@ -57,6 +57,7 @@
#include "gl/shaders/gl_postprocessshaderinstance.h"
#include "gl/textures/gl_samplers.h"
#include "gl/dynlights/gl_lightbuffer.h"
#include "gl/data/gl_viewpointbuffer.h"
#include "r_videoscale.h"
EXTERN_CVAR(Int, screenblocks)
@ -79,21 +80,6 @@ extern bool NoInterpolateView;
FGLRenderer::FGLRenderer(OpenGLFrameBuffer *fb)
{
framebuffer = fb;
mMirrorCount = 0;
mPlaneMirrorCount = 0;
mVBO = nullptr;
mSkyVBO = nullptr;
mShaderManager = nullptr;
mLights = nullptr;
mBuffers = nullptr;
mScreenBuffers = nullptr;
mSaveBuffers = nullptr;
mPresentShader = nullptr;
mPresent3dCheckerShader = nullptr;
mPresent3dColumnShader = nullptr;
mPresent3dRowShader = nullptr;
mShadowMapShader = nullptr;
mCustomPostProcessShaders = nullptr;
}
void FGLRenderer::Initialize(int width, int height)
@ -118,6 +104,7 @@ void FGLRenderer::Initialize(int width, int height)
mVBO = new FFlatVertexBuffer(width, height);
mSkyVBO = new FSkyVertexBuffer;
mLights = new FLightBuffer();
mViewpoints = new GLViewpointBuffer;
gl_RenderState.SetVertexBuffer(mVBO);
mFBID = 0;
mOldFBID = 0;
@ -132,11 +119,12 @@ FGLRenderer::~FGLRenderer()
FlushModels();
AActor::DeleteAllAttachedLights();
FMaterial::FlushAll();
if (mShaderManager != NULL) delete mShaderManager;
if (mSamplerManager != NULL) delete mSamplerManager;
if (mVBO != NULL) delete mVBO;
if (mSkyVBO != NULL) delete mSkyVBO;
if (mLights != NULL) delete mLights;
if (mShaderManager != nullptr) delete mShaderManager;
if (mSamplerManager != nullptr) delete mSamplerManager;
if (mVBO != nullptr) delete mVBO;
if (mSkyVBO != nullptr) delete mSkyVBO;
if (mLights != nullptr) delete mLights;
if (mViewpoints != nullptr) delete mViewpoints;
if (mFBID != 0) glDeleteFramebuffers(1, &mFBID);
if (mVAOID != 0)
{
@ -147,6 +135,7 @@ FGLRenderer::~FGLRenderer()
if (swdrawer) delete swdrawer;
if (mBuffers) delete mBuffers;
if (mSaveBuffers) delete mSaveBuffers;
if (mPresentShader) delete mPresentShader;
if (mPresent3dCheckerShader) delete mPresent3dCheckerShader;
if (mPresent3dColumnShader) delete mPresent3dColumnShader;
@ -233,6 +222,7 @@ sector_t *FGLRenderer::RenderView(player_t* player)
P_FindParticleSubsectors();
mLights->Clear();
mViewpoints->Clear();
// NoInterpolateView should have no bearing on camera textures, but needs to be preserved for the main view below.
bool saved_niv = NoInterpolateView;
@ -334,7 +324,8 @@ void FGLRenderer::WriteSavePic (player_t *player, FileWriter *file, int width, i
gl_RenderState.SetVertexBuffer(mVBO);
mVBO->Reset();
mLights->Clear();
mViewpoints->Clear();
// This shouldn't overwrite the global viewpoint even for a short time.
FRenderViewpoint savevp;
sector_t *viewsector = RenderViewpoint(savevp, players[consoleplayer].camera, &bounds, r_viewpoint.FieldOfView.Degrees, 1.6f, 1.6f, true, false);
@ -427,12 +418,7 @@ void FGLRenderer::Draw2D(F2DDrawer *drawer)
mBuffers->BindCurrentFB();
const auto &mScreenViewport = screen->mScreenViewport;
glViewport(mScreenViewport.left, mScreenViewport.top, mScreenViewport.width, mScreenViewport.height);
HWViewpointUniforms matrices;
matrices.SetDefaults();
matrices.mProjectionMatrix.ortho(0, screen->GetWidth(), screen->GetHeight(), 0, -1.0f, 1.0f);
matrices.CalcDependencies();
GLRenderer->mShaderManager->ApplyMatrices(&matrices, NORMAL_PASS);
GLRenderer->mViewpoints->Set2D(screen->GetWidth(), screen->GetHeight());
glDisable(GL_DEPTH_TEST);
@ -530,6 +516,10 @@ void FGLRenderer::Draw2D(F2DDrawer *drawer)
gl_RenderState.mTextureMatrix.translate(0.f, 1.f, 0.0f);
gl_RenderState.EnableTextureMatrix(true);
}
if (cmd.mFlags & F2DDrawer::DTF_Burn)
{
gl_RenderState.SetEffect(EFF_BURN);
}
}
else
{
@ -555,6 +545,8 @@ void FGLRenderer::Draw2D(F2DDrawer *drawer)
gl_RenderState.SetObjectColor(0xffffffff);
gl_RenderState.SetObjectColor2(0);
gl_RenderState.EnableTextureMatrix(false);
gl_RenderState.SetEffect(EFF_NONE);
}
glDisable(GL_SCISSOR_TEST);

View file

@ -35,6 +35,7 @@ class FHardwareTexture;
class FShadowMapShader;
class FCustomPostProcessShaders;
class SWSceneDrawer;
class GLViewpointBuffer;
struct FRenderViewpoint;
#define NOQUEUE nullptr // just some token to be used as a placeholder
@ -51,33 +52,34 @@ class FGLRenderer
public:
OpenGLFrameBuffer *framebuffer;
int mMirrorCount;
int mPlaneMirrorCount;
FShaderManager *mShaderManager;
FSamplerManager *mSamplerManager;
int mMirrorCount = 0;
int mPlaneMirrorCount = 0;
FShaderManager *mShaderManager = nullptr;
FSamplerManager *mSamplerManager = nullptr;
unsigned int mFBID;
unsigned int mVAOID;
unsigned int PortalQueryObject;
int mOldFBID;
FGLRenderBuffers *mBuffers;
FGLRenderBuffers *mScreenBuffers;
FGLRenderBuffers *mSaveBuffers;
FPresentShader *mPresentShader;
FPresent3DCheckerShader *mPresent3dCheckerShader;
FPresent3DColumnShader *mPresent3dColumnShader;
FPresent3DRowShader *mPresent3dRowShader;
FShadowMapShader *mShadowMapShader;
FCustomPostProcessShaders *mCustomPostProcessShaders;
FGLRenderBuffers *mBuffers = nullptr;
FGLRenderBuffers *mScreenBuffers = nullptr;
FGLRenderBuffers *mSaveBuffers = nullptr;
FPresentShader *mPresentShader = nullptr;
FPresent3DCheckerShader *mPresent3dCheckerShader = nullptr;
FPresent3DColumnShader *mPresent3dColumnShader = nullptr;
FPresent3DRowShader *mPresent3dRowShader = nullptr;
FShadowMapShader *mShadowMapShader = nullptr;
FCustomPostProcessShaders *mCustomPostProcessShaders = nullptr;
FShadowMap mShadowMap;
//FRotator mAngles;
FFlatVertexBuffer *mVBO;
FSkyVertexBuffer *mSkyVBO;
FLightBuffer *mLights;
FFlatVertexBuffer *mVBO = nullptr;
FSkyVertexBuffer *mSkyVBO = nullptr;
FLightBuffer *mLights = nullptr;
GLViewpointBuffer *mViewpoints = nullptr;
SWSceneDrawer *swdrawer = nullptr;
FPortalSceneState mPortalState;

View file

@ -119,7 +119,7 @@ bool FRenderState::ApplyShader()
static uint64_t firstFrame = 0;
// if firstFrame is not yet initialized, initialize it to current time
// if we're going to overflow a float (after ~4.6 hours, or 24 bits), re-init to regain precision
if ((firstFrame == 0) || (screen->FrameTime - firstFrame >= 1<<24) || level.ShaderStartTime >= firstFrame)
if ((firstFrame == 0) || (screen->FrameTime - firstFrame >= 1 << 24) || level.ShaderStartTime >= firstFrame)
firstFrame = screen->FrameTime;
static const float nulvec[] = { 0.f, 0.f, 0.f, 0.f };
@ -133,31 +133,15 @@ bool FRenderState::ApplyShader()
activeShader->Bind();
}
int fogset = 0;
if (mFogEnabled)
{
if (mFogEnabled == 2)
{
fogset = -3; // 2D rendering with 'foggy' overlay.
}
else if ((mFogColor & 0xffffff) == 0)
{
fogset = gl_fogmode;
}
else
{
fogset = -gl_fogmode;
}
}
glVertexAttrib4fv(VATTR_COLOR, mColor.vec);
glVertexAttrib4fv(VATTR_NORMAL, mNormal.vec);
activeShader->muDesaturation.Set(mDesaturation / 255.f);
activeShader->muFogEnabled.Set(fogset);
activeShader->muTextureMode.Set(mTextureMode == TM_MODULATE && mTempTM == TM_OPAQUE ? TM_OPAQUE : mTextureMode);
float fds = mLightParms[2];
if (!mFogEnabled) mLightParms[2] = 0;
activeShader->muLightParms.Set(mLightParms);
mLightParms[2] = fds;
activeShader->muFogColor.Set(mFogColor);
activeShader->muObjectColor.Set(mObjectColor);
activeShader->muObjectColor2.Set(mObjectColor2);

View file

@ -290,9 +290,9 @@ public:
mGlowBottom.Set(b[0], b[1], b[2], b[3]);
}
void SetSoftLightLevel(int llevel)
void SetSoftLightLevel(int llevel, int blendfactor = 0)
{
if (level.lightmode == 8) mLightParms[3] = llevel / 255.f;
if (level.lightmode == 8 && blendfactor == 0) mLightParms[3] = llevel / 255.f;
else mLightParms[3] = -1.f;
}

View file

@ -213,6 +213,7 @@ void FDrawInfo::StartScene()
decals[0].Clear();
decals[1].Clear();
hudsprites.Clear();
vpIndex = 0;
// Fullbright information needs to be propagated from the main view.
if (outer != nullptr) FullbrightFlags = outer->FullbrightFlags;

View file

@ -38,6 +38,7 @@ struct FDrawInfo : public HWDrawInfo
HWDrawList drawlists[GLDL_TYPES];
TArray<HUDSprite> hudsprites; // These may just be stored by value.
TArray<GLDecal *> decals[2]; // the second slot is for mirrors which get rendered in a separate pass.
int vpIndex;
void ApplyVPUniforms() override;

View file

@ -42,6 +42,7 @@
#include "gl/data/gl_vertexbuffer.h"
#include "hwrenderer/scene/hw_clipper.h"
#include "gl/scene/gl_portal.h"
#include "gl/data/gl_viewpointbuffer.h"
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
@ -66,9 +67,7 @@ void GLPortal::ClearScreen(HWDrawInfo *di)
{
bool multi = !!glIsEnabled(GL_MULTISAMPLE);
di->VPUniforms.mViewMatrix.loadIdentity();
di->VPUniforms.mProjectionMatrix.ortho(0, SCREENWIDTH, SCREENHEIGHT, 0, -1.0f, 1.0f);
di->ApplyVPUniforms();
GLRenderer->mViewpoints->Set2D(SCREENWIDTH, SCREENHEIGHT);
gl_RenderState.SetColor(0, 0, 0);
gl_RenderState.Apply();
@ -236,7 +235,7 @@ void GLPortal::End(HWDrawInfo *di, bool usestencil)
Clocker c(PortalAll);
di = static_cast<FDrawInfo*>(di)->EndDrawInfo();
di->ApplyVPUniforms();
GLRenderer->mViewpoints->Bind(static_cast<FDrawInfo*>(di)->vpIndex);
if (usestencil)
{
auto &vp = di->Viewpoint;
@ -295,7 +294,6 @@ void GLPortal::End(HWDrawInfo *di, bool usestencil)
// Restore the old view
if (vp.camera != nullptr) vp.camera->renderflags = (vp.camera->renderflags & ~RF_MAYBEINVISIBLE) | savedvisibility;
di->SetupView(vp.Pos.X, vp.Pos.Y, vp.Pos.Z, !!(mState->MirrorFlag & 1), !!(mState->PlaneMirrorFlag & 1));
// This draws a valid z-buffer into the stencil's contents to ensure it
// doesn't get overwritten by the level's geometry.
@ -345,10 +343,12 @@ GLHorizonPortal::GLHorizonPortal(FPortalSceneState *s, GLHorizonInfo * pt, FRend
// Draw to some far away boundary
// This is not drawn as larger strips because it causes visual glitches.
FFlatVertex *ptr = GLRenderer->mVBO->GetBuffer();
for (float x = -32768 + vx; x<32768 + vx; x += 4096)
for (int xx = -32768; xx < 32768; xx += 4096)
{
for (float y = -32768 + vy; y<32768 + vy; y += 4096)
float x = xx + vx;
for (int yy = -32768; yy < 32768; yy += 4096)
{
float y = yy + vy;
ptr->Set(x, z, y, x / 64, -y / 64);
ptr++;
ptr->Set(x + 4096, z, y, x / 64 + 64, -y / 64);

View file

@ -50,6 +50,7 @@
#include "gl/renderer/gl_renderstate.h"
#include "gl/renderer/gl_renderbuffers.h"
#include "gl/data/gl_vertexbuffer.h"
#include "gl/data/gl_viewpointbuffer.h"
#include "hwrenderer/scene/hw_clipper.h"
#include "hwrenderer/scene/hw_portal.h"
#include "gl/scene/gl_drawinfo.h"
@ -76,19 +77,7 @@ EXTERN_CVAR (Bool, r_drawvoxels)
void FDrawInfo::ApplyVPUniforms()
{
VPUniforms.CalcDependencies();
GLRenderer->mShaderManager->ApplyMatrices(&VPUniforms, gl_RenderState.GetPassType());
if (!(gl.flags & RFL_NO_CLIP_PLANES))
{
if (VPUniforms.mClipHeightDirection != 0.f || VPUniforms.mClipLine.X > -10000000.0f)
{
glEnable(GL_CLIP_DISTANCE0);
}
else
{
glDisable(GL_CLIP_DISTANCE0);
}
}
vpIndex = GLRenderer->mViewpoints->SetViewpoint(&VPUniforms);
}
@ -337,7 +326,7 @@ void FDrawInfo::DrawScene(int drawmode)
GLRenderer->mBuffers->BindSceneFB(true);
gl_RenderState.EnableDrawBuffers(gl_RenderState.GetPassDrawBufferCount());
gl_RenderState.Apply();
ApplyVPUniforms();
GLRenderer->mViewpoints->Bind(vpIndex);
}
// Handle all portals after rendering the opaque objects but before
@ -383,9 +372,11 @@ void FDrawInfo::DrawEndScene2D(sector_t * viewsector)
const bool renderHUDModel = IsHUDModelForPlayerAvailable(players[consoleplayer].camera->player);
auto vrmode = VRMode::GetVRMode(true);
VPUniforms.mViewMatrix.loadIdentity();
VPUniforms.mProjectionMatrix = vrmode->GetHUDSpriteProjection();
ApplyVPUniforms();
HWViewpointUniforms vp = VPUniforms;
vp.mViewMatrix.loadIdentity();
vp.mProjectionMatrix = vrmode->GetHUDSpriteProjection();
vp.mFogEnabled = 0;
GLRenderer->mViewpoints->SetViewpoint(&vp);
glDisable(GL_DEPTH_TEST);
glDisable(GL_MULTISAMPLE);
@ -493,6 +484,7 @@ sector_t * FGLRenderer::RenderViewpoint (FRenderViewpoint &mainvp, AActor * came
if (mainview)
{
PostProcess.Clock();
if (toscreen) di->EndDrawScene(mainvp.sector); // do not call this for camera textures.
if (gl_RenderState.GetPassType() == GBUFFER_PASS) // Turn off ssao draw buffers
@ -506,6 +498,7 @@ sector_t * FGLRenderer::RenderViewpoint (FRenderViewpoint &mainvp, AActor * came
FGLDebug::PopGroup(); // MainView
PostProcessScene(cm, [&]() { di->DrawEndScene2D(mainvp.sector); });
PostProcess.Unclock();
}
di->EndDrawInfo();
if (vrmode->mEyeCount > 1)

View file

@ -269,7 +269,6 @@ void GLSkyPortal::DrawContents(HWDrawInfo *di)
}
}
gl_RenderState.SetVertexBuffer(GLRenderer->mVBO);
di->ApplyVPUniforms();
::level.lightmode = oldlightmode;
gl_RenderState.SetDepthClamp(oldClamp);
}

View file

@ -113,7 +113,7 @@ void FDrawInfo::DrawSprite(GLSprite *sprite, int pass)
if (!sprite->Colormap.FadeColor.isBlack())
{
float dist=Dist2(vp.Pos.X, vp.Pos.Y, sprite->x, sprite->y);
int fogd = hw_GetFogDensity(sprite->lightlevel, sprite->Colormap.FadeColor, sprite->Colormap.FogDensity);
int fogd = hw_GetFogDensity(sprite->lightlevel, sprite->Colormap.FadeColor, sprite->Colormap.FogDensity, sprite->Colormap.BlendFactor);
// this value was determined by trial and error and is scale dependent!
float factor = 0.05f + exp(-fogd*dist / 62500.f);

View file

@ -49,18 +49,32 @@ bool FShader::Load(const char * name, const char * vert_prog_lump, const char *
static char buffer[10000];
FString error;
FString i_data;
// these settings are actually pointless but there seem to be some old ATI drivers that fail to compile the shader without setting the precision here.
i_data += "precision highp int;\n";
i_data += "precision highp float;\n";
FString i_data = R"(
// these settings are actually pointless but there seem to be some old ATI drivers that fail to compile the shader without setting the precision here.
precision highp int;
precision highp float;
i_data += "uniform vec4 uCameraPos;\n";
// This must match the HWViewpointUniforms struct
layout(std140) uniform ViewpointUBO {
mat4 ProjectionMatrix;
mat4 ViewMatrix;
mat4 NormalViewMatrix;
vec4 uCameraPos;
vec4 uClipLine;
float uGlobVis; // uGlobVis = R_GetGlobVis(r_visibility) / 32.0
int uPalLightLevels;
int uViewHeight; // Software fuzz scaling
float uClipHeight;
float uClipHeightDirection;
int uFogEnabled;
};
)";
i_data += "uniform int uTextureMode;\n";
i_data += "uniform float uClipHeight;\n";
i_data += "uniform float uClipHeightDirection;\n";
i_data += "uniform vec2 uClipSplit;\n";
i_data += "uniform vec4 uClipLine;\n";
i_data += "uniform float uAlphaThreshold;\n";
// colors
@ -86,16 +100,10 @@ bool FShader::Load(const char * name, const char * vert_prog_lump, const char *
i_data += "#define uFogDensity uLightAttr.b\n";
i_data += "#define uLightFactor uLightAttr.g\n";
i_data += "#define uLightDist uLightAttr.r\n";
i_data += "uniform int uFogEnabled;\n";
i_data += "uniform int uPalLightLevels;\n";
i_data += "uniform float uGlobVis;\n"; // uGlobVis = R_GetGlobVis(r_visibility) / 32.0
// dynamic lights
i_data += "uniform int uLightIndex;\n";
// Software fuzz scaling
i_data += "uniform int uViewHeight;\n";
// Blinn glossiness and specular level
i_data += "uniform vec2 uSpecularMaterial;\n";
@ -107,10 +115,7 @@ bool FShader::Load(const char * name, const char * vert_prog_lump, const char *
i_data += "#endif\n";
// matrices
i_data += "uniform mat4 ProjectionMatrix;\n";
i_data += "uniform mat4 ViewMatrix;\n";
i_data += "uniform mat4 ModelMatrix;\n";
i_data += "uniform mat4 NormalViewMatrix;\n";
i_data += "uniform mat4 NormalModelMatrix;\n";
i_data += "uniform mat4 TextureMatrix;\n";
@ -326,7 +331,6 @@ bool FShader::Load(const char * name, const char * vert_prog_lump, const char *
muDesaturation.Init(hShader, "uDesaturationFactor");
muFogEnabled.Init(hShader, "uFogEnabled");
muTextureMode.Init(hShader, "uTextureMode");
muLightParms.Init(hShader, "uLightAttr");
muClipSplit.Init(hShader, "uClipSplit");
@ -348,28 +352,20 @@ bool FShader::Load(const char * name, const char * vert_prog_lump, const char *
lights_index = glGetUniformLocation(hShader, "lights");
fakevb_index = glGetUniformLocation(hShader, "fakeVB");
projectionmatrix_index = glGetUniformLocation(hShader, "ProjectionMatrix");
viewmatrix_index = glGetUniformLocation(hShader, "ViewMatrix");
modelmatrix_index = glGetUniformLocation(hShader, "ModelMatrix");
texturematrix_index = glGetUniformLocation(hShader, "TextureMatrix");
vertexmatrix_index = glGetUniformLocation(hShader, "uQuadVertices");
texcoordmatrix_index = glGetUniformLocation(hShader, "uQuadTexCoords");
normalviewmatrix_index = glGetUniformLocation(hShader, "NormalViewMatrix");
normalmodelmatrix_index = glGetUniformLocation(hShader, "NormalModelMatrix");
quadmode_index = glGetUniformLocation(hShader, "uQuadMode");
viewheight_index = glGetUniformLocation(hShader, "uViewHeight");
camerapos_index = glGetUniformLocation(hShader, "uCameraPos");
pallightlevels_index = glGetUniformLocation(hShader, "uPalLightLevels");
globvis_index = glGetUniformLocation(hShader, "uGlobVis");
clipheight_index = glGetUniformLocation(hShader, "uClipHeight");
clipheightdirection_index = glGetUniformLocation(hShader, "uClipHeightDirection");
clipline_index = glGetUniformLocation(hShader, "uClipLine");
if (lightbuffertype == GL_UNIFORM_BUFFER)
{
int tempindex = glGetUniformBlockIndex(hShader, "LightBufferUBO");
if (tempindex != -1) glUniformBlockBinding(hShader, tempindex, LIGHTBUF_BINDINGPOINT);
}
int tempindex = glGetUniformBlockIndex(hShader, "ViewpointUBO");
if (tempindex != -1) glUniformBlockBinding(hShader, tempindex, VIEWPOINT_BINDINGPOINT);
glUseProgram(hShader);
if (quadmode_index > 0) glUniform1i(quadmode_index, 0);
@ -448,27 +444,6 @@ FShader *FShaderCollection::Compile (const char *ShaderName, const char *ShaderP
return shader;
}
//==========================================================================
//
//
//
//==========================================================================
void FShader::ApplyMatrices(HWViewpointUniforms *u)
{
Bind();
glUniformMatrix4fv(projectionmatrix_index, 1, false, u->mProjectionMatrix.get());
glUniformMatrix4fv(viewmatrix_index, 1, false, u->mViewMatrix.get());
glUniformMatrix4fv(normalviewmatrix_index, 1, false, u->mNormalViewMatrix.get());
glUniform4fv(camerapos_index, 1, &u->mCameraPos[0]);
glUniform1i(viewheight_index, u->mViewHeight);
glUniform1i(pallightlevels_index, u->mPalLightLevels);
glUniform1f(globvis_index, u->mGlobVis);
glUniform1f(clipheight_index, u->mClipHeight);
glUniform1f(clipheightdirection_index, u->mClipHeightDirection);
}
//==========================================================================
//
//
@ -566,15 +541,6 @@ FShader *FShaderManager::Get(unsigned int eff, bool alphateston, EPassType passT
return nullptr;
}
void FShaderManager::ApplyMatrices(HWViewpointUniforms *u, EPassType passType)
{
if (passType < mPassShaders.Size())
mPassShaders[passType]->ApplyMatrices(u);
if (mActiveShader)
mActiveShader->Bind();
}
//==========================================================================
//
//
@ -706,35 +672,6 @@ FShader *FShaderCollection::BindEffect(int effect)
}
//==========================================================================
//
//
//
//==========================================================================
EXTERN_CVAR(Int, gl_fuzztype)
void FShaderCollection::ApplyMatrices(HWViewpointUniforms *u)
{
for (int i = 0; i < SHADER_NoTexture; i++)
{
mMaterialShaders[i]->ApplyMatrices(u);
mMaterialShadersNAT[i]->ApplyMatrices(u);
}
mMaterialShaders[SHADER_NoTexture]->ApplyMatrices(u);
if (gl_fuzztype != 0)
{
mMaterialShaders[SHADER_NoTexture + gl_fuzztype]->ApplyMatrices(u);
}
for (unsigned i = FIRST_USER_SHADER; i < mMaterialShaders.Size(); i++)
{
mMaterialShaders[i]->ApplyMatrices(u);
}
for (int i = 0; i < MAX_EFFECTS; i++)
{
mEffectShaders[i]->ApplyMatrices(u);
}
}
//==========================================================================
//
//

View file

@ -242,7 +242,6 @@ class FShader
FName mName;
FBufferedUniform1f muDesaturation;
FBufferedUniform1i muFogEnabled;
FBufferedUniform1i muTextureMode;
FBufferedUniform4f muLightParms;
FBufferedUniform2f muClipSplit;
@ -267,16 +266,6 @@ class FShader
int normalmodelmatrix_index;
int texturematrix_index;
int projectionmatrix_index;
int viewmatrix_index;
int normalviewmatrix_index;
int viewheight_index;
int camerapos_index;
int pallightlevels_index;
int globvis_index;
int clipheight_index;
int clipheightdirection_index;
int clipline_index;
public:
int vertexmatrix_index;
@ -308,9 +297,6 @@ public:
bool Bind();
unsigned int GetHandle() const { return hShader; }
void ApplyMatrices(HWViewpointUniforms *u);
};
//==========================================================================
@ -329,7 +315,6 @@ public:
FShader *BindEffect(int effect, EPassType passType);
FShader *Get(unsigned int eff, bool alphateston, EPassType passType);
void ApplyMatrices(HWViewpointUniforms *u, EPassType passType);
private:
FShader *mActiveShader = nullptr;
@ -351,7 +336,6 @@ public:
FShader *Compile(const char *ShaderName, const char *ShaderPath, const char *LightModePath, const char *shaderdefines, bool usediscard, EPassType passType);
int Find(const char *mame);
FShader *BindEffect(int effect);
void ApplyMatrices(HWViewpointUniforms *u);
FShader *Get(unsigned int eff, bool alphateston)
{

View file

@ -151,7 +151,6 @@ void OpenGLFrameBuffer::Update()
twoD.Reset();
Flush3D.Reset();
DrawRateStuff();
Flush3D.Clock();
GLRenderer->Flush();
Flush3D.Unclock();
@ -484,3 +483,71 @@ void OpenGLFrameBuffer::PostProcessScene(int fixedcm, const std::function<void()
{
GLRenderer->PostProcessScene(fixedcm, afterBloomDrawEndScene2D);
}
//==========================================================================
//
// This is just a wrapper around the hardware texture being extracted below so that it can be passed to the 2D code.
//
//==========================================================================
class FGLWipeTexture : public FTexture
{
public:
FGLWipeTexture(int w, int h)
{
Width = w;
Height = h;
WidthBits = 4;
UseType = ETextureType::SWCanvas;
bNoCompress = true;
SystemTexture[0] = screen->CreateHardwareTexture(this);
}
};
//==========================================================================
//
// OpenGLFrameBuffer :: 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.
//
//==========================================================================
FTexture *OpenGLFrameBuffer::WipeStartScreen()
{
const auto &viewport = screen->mScreenViewport;
FGLWipeTexture *tex = new FGLWipeTexture(viewport.width, viewport.height);
tex->SystemTexture[0]->CreateTexture(nullptr, viewport.width, viewport.height, 0, false, 0, "WipeStartScreen");
glFinish();
static_cast<FHardwareTexture*>(tex->SystemTexture[0])->Bind(0, false, false);
GLRenderer->mBuffers->BindCurrentFB();
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, viewport.left, viewport.top, viewport.width, viewport.height);
return tex;
}
//==========================================================================
//
// OpenGLFrameBuffer :: WipeEndScreen
//
// The screen we want to animate to has just been drawn.
//
//==========================================================================
FTexture *OpenGLFrameBuffer::WipeEndScreen()
{
GLRenderer->Flush();
const auto &viewport = screen->mScreenViewport;
FGLWipeTexture *tex = new FGLWipeTexture(viewport.width, viewport.height);
tex->SystemTexture[0]->CreateTexture(NULL, viewport.width, viewport.height, 0, false, 0, "WipeEndScreen");
glFinish();
static_cast<FHardwareTexture*>(tex->SystemTexture[0])->Bind(0, false, false);
GLRenderer->mBuffers->BindCurrentFB();
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, viewport.left, viewport.top, viewport.width, viewport.height);
return tex;
}

View file

@ -20,7 +20,7 @@ public:
~OpenGLFrameBuffer();
void InitializeState();
void Update();
void Update() override;
// Color correction
void SetGamma();
@ -49,10 +49,6 @@ public:
// points to the last row in the buffer, which will be the first row output.
virtual void GetScreenshotBuffer(const uint8_t *&buffer, int &pitch, ESSType &color_type, float &gamma) override;
bool WipeStartScreen(int type);
void WipeEndScreen();
bool WipeDo(int ticks);
void WipeCleanup();
void Swap();
bool IsHWGammaActive() const { return HWGammaActive; }
@ -63,33 +59,11 @@ public:
bool HWGammaActive = false; // Are we using hardware or software gamma?
std::shared_ptr<FGLDebug> mDebug; // Debug API
FTexture *WipeStartScreen() override;
FTexture *WipeEndScreen() override;
private:
int camtexcount = 0;
class Wiper
{
protected:
FSimpleVertexBuffer *mVertexBuf;
void MakeVBO(OpenGLFrameBuffer *fb);
public:
Wiper();
virtual ~Wiper();
virtual bool Run(int ticks, OpenGLFrameBuffer *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;
FHardwareTexture *wipestartscreen;
FHardwareTexture *wipeendscreen;
public:
};

View file

@ -1,536 +0,0 @@
//
//---------------------------------------------------------------------------
//
// Copyright(C) 2008-2016 Christoph Oelckers
// All rights reserved.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with this program. If not, see http://www.gnu.org/licenses/
//
//--------------------------------------------------------------------------
//
/*
** Screen wipe stuff
**
*/
#include "gl_load/gl_system.h"
#include "f_wipe.h"
#include "m_random.h"
#include "w_wad.h"
#include "v_palette.h"
#include "templates.h"
#include "gl_load/gl_interface.h"
#include "gl/renderer/gl_renderer.h"
#include "gl/renderer/gl_renderstate.h"
#include "gl/renderer/gl_renderbuffers.h"
#include "gl/system/gl_framebuffer.h"
#include "gl/textures/gl_samplers.h"
#include "gl/data/gl_vertexbuffer.h"
//===========================================================================
//
// Screen wipes
//
//===========================================================================
// TYPES -------------------------------------------------------------------
class OpenGLFrameBuffer::Wiper_Crossfade : public OpenGLFrameBuffer::Wiper
{
public:
Wiper_Crossfade();
bool Run(int ticks, OpenGLFrameBuffer *fb);
private:
int Clock;
};
class OpenGLFrameBuffer::Wiper_Melt : public OpenGLFrameBuffer::Wiper
{
public:
Wiper_Melt();
int MakeVBO(int ticks, OpenGLFrameBuffer *fb, bool &done);
bool Run(int ticks, OpenGLFrameBuffer *fb);
private:
static const int WIDTH = 320, HEIGHT = 200;
int y[WIDTH];
};
class OpenGLFrameBuffer::Wiper_Burn : public OpenGLFrameBuffer::Wiper
{
public:
Wiper_Burn();
~Wiper_Burn();
bool Run(int ticks, OpenGLFrameBuffer *fb);
private:
static const int WIDTH = 64, HEIGHT = 64;
uint8_t BurnArray[WIDTH * (HEIGHT + 5)];
FHardwareTexture *BurnTexture;
int Density;
int BurnTime;
};
//==========================================================================
//
// OpenGLFrameBuffer :: 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.
//
//==========================================================================
bool OpenGLFrameBuffer::WipeStartScreen(int type)
{
switch (type)
{
case wipe_Burn:
ScreenWipe = new Wiper_Burn;
break;
case wipe_Fade:
ScreenWipe = new Wiper_Crossfade;
break;
case wipe_Melt:
ScreenWipe = new Wiper_Melt;
break;
default:
return false;
}
const auto &viewport = screen->mScreenViewport;
wipestartscreen = new FHardwareTexture(true);
wipestartscreen->CreateTexture(NULL, viewport.width, viewport.height, 0, false, 0, "WipeStartScreen");
GLRenderer->mSamplerManager->Bind(0, CLAMP_NOFILTER, -1);
GLRenderer->mSamplerManager->Bind(1, CLAMP_NONE, -1);
glFinish();
wipestartscreen->Bind(0, false, false);
const auto copyPixels = [&viewport]()
{
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, viewport.left, viewport.top, viewport.width, viewport.height);
};
GLRenderer->mBuffers->BindCurrentFB();
copyPixels();
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
return true;
}
//==========================================================================
//
// OpenGLFrameBuffer :: WipeEndScreen
//
// The screen we want to animate to has just been drawn.
//
//==========================================================================
void OpenGLFrameBuffer::WipeEndScreen()
{
GLRenderer->Flush();
const auto &viewport = screen->mScreenViewport;
wipeendscreen = new FHardwareTexture(true);
wipeendscreen->CreateTexture(NULL, viewport.width, viewport.height, 0, false, 0, "WipeEndScreen");
GLRenderer->mSamplerManager->Bind(0, CLAMP_NOFILTER, -1);
glFinish();
wipeendscreen->Bind(0, false, false);
GLRenderer->mBuffers->BindCurrentFB();
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, viewport.left, viewport.top, viewport.width, viewport.height);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
}
//==========================================================================
//
// OpenGLFrameBuffer :: 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 OpenGLFrameBuffer::WipeDo(int ticks)
{
bool done = true;
// Sanity checks.
if (wipestartscreen != nullptr && wipeendscreen != nullptr)
{
gl_RenderState.EnableTexture(true);
gl_RenderState.EnableFog(false);
glDisable(GL_DEPTH_TEST);
glDepthMask(false);
GLRenderer->mBuffers->BindCurrentFB();
const auto &bounds = screen->mScreenViewport;
glViewport(bounds.left, bounds.top, bounds.width, bounds.height);
done = ScreenWipe->Run(ticks, this);
glDepthMask(true);
}
gl_RenderState.SetVertexBuffer(GLRenderer->mVBO);
return done;
}
//==========================================================================
//
// OpenGLFrameBuffer :: WipeCleanup
//
// Release any resources that were specifically created for the wipe.
//
//==========================================================================
void OpenGLFrameBuffer::WipeCleanup()
{
if (ScreenWipe != NULL)
{
delete ScreenWipe;
ScreenWipe = NULL;
}
if (wipestartscreen != NULL)
{
delete wipestartscreen;
wipestartscreen = NULL;
}
if (wipeendscreen != NULL)
{
delete wipeendscreen;
wipeendscreen = NULL;
}
gl_RenderState.ClearLastMaterial();
}
//==========================================================================
//
// OpenGLFrameBuffer :: Wiper Constructor
//
//==========================================================================
OpenGLFrameBuffer::Wiper::Wiper()
{
mVertexBuf = new FSimpleVertexBuffer;
}
OpenGLFrameBuffer::Wiper::~Wiper()
{
delete mVertexBuf;
}
void OpenGLFrameBuffer::Wiper::MakeVBO(OpenGLFrameBuffer *fb)
{
FSimpleVertex make[4];
FSimpleVertex *ptr = make;
float ur = fb->GetWidth() / FHardwareTexture::GetTexDimension(fb->GetWidth());
float vb = fb->GetHeight() / FHardwareTexture::GetTexDimension(fb->GetHeight());
ptr->Set(0, 0, 0, 0, vb);
ptr++;
ptr->Set(0, fb->GetHeight(), 0, 0, 0);
ptr++;
ptr->Set(fb->GetWidth(), 0, 0, ur, vb);
ptr++;
ptr->Set(fb->GetWidth(), fb->GetHeight(), 0, ur, 0);
mVertexBuf->set(make, 4);
}
// WIPE: CROSSFADE ---------------------------------------------------------
//==========================================================================
//
// OpenGLFrameBuffer :: Wiper_Crossfade Constructor
//
//==========================================================================
OpenGLFrameBuffer::Wiper_Crossfade::Wiper_Crossfade()
: Clock(0)
{
}
//==========================================================================
//
// OpenGLFrameBuffer :: Wiper_Crossfade :: Run
//
// Fades the old screen into the new one over 32 ticks.
//
//==========================================================================
bool OpenGLFrameBuffer::Wiper_Crossfade::Run(int ticks, OpenGLFrameBuffer *fb)
{
Clock += ticks;
MakeVBO(fb);
gl_RenderState.SetTextureMode(TM_OPAQUE);
gl_RenderState.AlphaFunc(GL_GEQUAL, 0.f);
gl_RenderState.ResetColor();
gl_RenderState.Apply();
fb->wipestartscreen->Bind(0, 0, false);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
float a = clamp(Clock / 32.f, 0.f, 1.f);
gl_RenderState.SetColorAlpha(0xffffff, a);
gl_RenderState.Apply();
fb->wipeendscreen->Bind(0, 0, false);
mVertexBuf->EnableColorArray(false);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
gl_RenderState.AlphaFunc(GL_GEQUAL, 0.5f);
gl_RenderState.SetTextureMode(TM_MODULATE);
return Clock >= 32;
}
//==========================================================================
//
// OpenGLFrameBuffer :: Wiper_Melt Constructor
//
//==========================================================================
OpenGLFrameBuffer::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
//
// Fades the old screen into the new one over 32 ticks.
//
//==========================================================================
int OpenGLFrameBuffer::Wiper_Melt::MakeVBO(int ticks, OpenGLFrameBuffer *fb, bool &done)
{
FSimpleVertex *make = new FSimpleVertex[321*4];
FSimpleVertex *ptr = make;
int dy;
float ur = fb->GetWidth() / FHardwareTexture::GetTexDimension(fb->GetWidth());
float vb = fb->GetHeight() / FHardwareTexture::GetTexDimension(fb->GetHeight());
ptr->Set(0, 0, 0, 0, vb);
ptr++;
ptr->Set(0, fb->GetHeight(), 0, 0, 0);
ptr++;
ptr->Set(fb->GetWidth(), 0, 0, ur, vb);
ptr++;
ptr->Set(fb->GetWidth(), fb->GetHeight(), 0, ur, 0);
ptr++;
// 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)
{
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.
dpt.x = i * fb->GetWidth() / WIDTH;
dpt.y = MAX(0, y[i] * fb->GetHeight() / HEIGHT);
rect.left = dpt.x;
rect.top = 0;
rect.right = (i + 1) * fb->GetWidth() / WIDTH;
rect.bottom = fb->GetHeight() - dpt.y;
if (rect.bottom > rect.top)
{
float tw = (float)FHardwareTexture::GetTexDimension(fb->GetWidth());
float th = (float)FHardwareTexture::GetTexDimension(fb->GetHeight());
rect.bottom = fb->GetHeight() - rect.bottom;
rect.top = fb->GetHeight() - rect.top;
ptr->Set(rect.left, rect.bottom, 0, rect.left / tw, rect.top / th);
ptr++;
ptr->Set(rect.left, rect.top, 0, rect.left / tw, rect.bottom / th);
ptr++;
ptr->Set(rect.right, rect.bottom, 0, rect.right / tw, rect.top / th);
ptr++;
ptr->Set(rect.right, rect.top, 0, rect.right / tw, rect.bottom / th);
ptr++;
}
}
}
}
int numverts = int(ptr - make);
mVertexBuf->set(make, numverts);
delete[] make;
return numverts;
}
bool OpenGLFrameBuffer::Wiper_Melt::Run(int ticks, OpenGLFrameBuffer *fb)
{
bool done = false;
int maxvert = MakeVBO(ticks, fb, done);
// Draw the new screen on the bottom.
gl_RenderState.SetTextureMode(TM_OPAQUE);
gl_RenderState.ResetColor();
gl_RenderState.Apply();
fb->wipeendscreen->Bind(0, 0, false);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
fb->wipestartscreen->Bind(0, 0, false);
gl_RenderState.SetTextureMode(TM_MODULATE);
for (int i = 4; i < maxvert; i += 4)
{
glDrawArrays(GL_TRIANGLE_STRIP, i, 4);
}
return done;
}
//==========================================================================
//
// OpenGLFrameBuffer :: Wiper_Burn Constructor
//
//==========================================================================
OpenGLFrameBuffer::Wiper_Burn::Wiper_Burn()
{
Density = 4;
BurnTime = 0;
memset(BurnArray, 0, sizeof(BurnArray));
BurnTexture = NULL;
}
//==========================================================================
//
// OpenGLFrameBuffer :: Wiper_Burn Destructor
//
//==========================================================================
OpenGLFrameBuffer::Wiper_Burn::~Wiper_Burn()
{
if (BurnTexture != NULL)
{
delete BurnTexture;
BurnTexture = NULL;
}
}
//==========================================================================
//
// OpenGLFrameBuffer :: Wiper_Burn :: Run
//
//==========================================================================
bool OpenGLFrameBuffer::Wiper_Burn::Run(int ticks, OpenGLFrameBuffer *fb)
{
bool done;
MakeVBO(fb);
BurnTime += ticks;
ticks *= 2;
// Make the fire burn
done = false;
while (!done && ticks--)
{
Density = wipe_CalcBurn(BurnArray, WIDTH, HEIGHT, Density);
done = (Density < 0);
}
if (BurnTexture != NULL) delete BurnTexture;
BurnTexture = new FHardwareTexture(true);
// Update the burn texture with the new burn data
uint8_t rgb_buffer[WIDTH*HEIGHT*4];
const uint8_t *src = BurnArray;
uint32_t *dest = (uint32_t *)rgb_buffer;
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);
}
}
float ur = fb->GetWidth() / FHardwareTexture::GetTexDimension(fb->GetWidth());
float vb = fb->GetHeight() / FHardwareTexture::GetTexDimension(fb->GetHeight());
// Put the initial screen back to the buffer.
gl_RenderState.SetTextureMode(TM_OPAQUE);
gl_RenderState.AlphaFunc(GL_GEQUAL, 0.f);
gl_RenderState.ResetColor();
gl_RenderState.Apply();
fb->wipestartscreen->Bind(0, 0, false);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
gl_RenderState.SetTextureMode(TM_MODULATE);
gl_RenderState.SetEffect(EFF_BURN);
gl_RenderState.ResetColor();
gl_RenderState.Apply();
// Burn the new screen on top of it.
fb->wipeendscreen->Bind(0, 0, false);
BurnTexture->CreateTexture(rgb_buffer, WIDTH, HEIGHT, 1, true, 0, "BurnTexture");
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
gl_RenderState.SetEffect(EFF_NONE);
// The fire may not always stabilize, so the wipe is forced to end
// after an arbitrary maximum time.
return done || (BurnTime > 40);
}

View file

@ -7,7 +7,8 @@
enum
{
LIGHTBUF_BINDINGPOINT = 1,
POSTPROCESS_BINDINGPOINT = 2
POSTPROCESS_BINDINGPOINT = 2,
VIEWPOINT_BINDINGPOINT = 3
};
enum class UniformType

View file

@ -280,5 +280,6 @@ void HWViewpointUniforms::SetDefaults()
mGlobVis = (float)R_GetGlobVis(r_viewwindow, r_visibility) / 32.f;
mPalLightLevels = static_cast<int>(gl_bandedswlight) | (static_cast<int>(gl_fogmode) << 8);
mClipLine.X = -10000000.0f;
mFogEnabled = gl_fogmode;
}

View file

@ -16,6 +16,7 @@ struct HWViewpointUniforms
int mViewHeight = 0;
float mClipHeight = 0.f;
float mClipHeightDirection = 0.f;
int mFogEnabled = 0;
void CalcDependencies()
{

View file

@ -190,7 +190,7 @@ static WeaponLighting GetWeaponLighting(sector_t *viewsector, const DVector3 &po
if (level.flags3 & LEVEL3_NOCOLOREDSPRITELIGHTING) l.cm.ClearColor();
}
l.lightlevel = hw_CalcLightLevel(l.lightlevel, getExtraLight(), true);
l.lightlevel = hw_CalcLightLevel(l.lightlevel, getExtraLight(), true, 0);
if (level.lightmode == 8 || l.lightlevel < 92)
{

View file

@ -46,7 +46,7 @@ glcycle_t RenderWall,SetupWall,ClipWall;
glcycle_t RenderFlat,SetupFlat;
glcycle_t RenderSprite,SetupSprite;
glcycle_t All, Finish, PortalAll, Bsp;
glcycle_t ProcessAll;
glcycle_t ProcessAll, PostProcess;
glcycle_t RenderAll;
glcycle_t Dirty;
glcycle_t drawcalls;
@ -64,6 +64,7 @@ void ResetProfilingData()
PortalAll.Reset();
RenderAll.Reset();
ProcessAll.Reset();
PostProcess.Reset();
RenderWall.Reset();
SetupWall.Reset();
ClipWall.Reset();
@ -94,13 +95,13 @@ static void AppendRenderTimes(FString &str)
"F: Render=%2.3f, Setup=%2.3f\n"
"S: Render=%2.3f, Setup=%2.3f\n"
"2D: %2.3f Finish3D: %2.3f\n"
"All=%2.3f, Render=%2.3f, Setup=%2.3f, Portal=%2.3f, Drawcalls=%2.3f, Finish=%2.3f\n",
"All=%2.3f, Render=%2.3f, Setup=%2.3f, Portal=%2.3f, Drawcalls=%2.3f, Postprocess=%2.3f, Finish=%2.3f\n",
bsp, clipwall,
RenderWall.TimeMS(), setupwall,
RenderFlat.TimeMS(), SetupFlat.TimeMS(),
RenderSprite.TimeMS(), SetupSprite.TimeMS(),
twoD.TimeMS(), Flush3D.TimeMS() - twoD.TimeMS(),
All.TimeMS() + Finish.TimeMS(), RenderAll.TimeMS(), ProcessAll.TimeMS(), PortalAll.TimeMS(), drawcalls.TimeMS(), Finish.TimeMS());
All.TimeMS() + Finish.TimeMS(), RenderAll.TimeMS(), ProcessAll.TimeMS(), PortalAll.TimeMS(), drawcalls.TimeMS(), PostProcess.TimeMS(), Finish.TimeMS());
}
static void AppendRenderStats(FString &out)

View file

@ -9,7 +9,7 @@ extern glcycle_t RenderWall,SetupWall,ClipWall;
extern glcycle_t RenderFlat,SetupFlat;
extern glcycle_t RenderSprite,SetupSprite;
extern glcycle_t All, Finish, PortalAll, Bsp;
extern glcycle_t ProcessAll;
extern glcycle_t ProcessAll, PostProcess;
extern glcycle_t RenderAll;
extern glcycle_t Dirty;
extern glcycle_t drawcalls, twoD, Flush3D;

View file

@ -82,13 +82,15 @@ CUSTOM_CVAR(Int,gl_fogmode,1,CVAR_ARCHIVE|CVAR_NOINITCALL)
//
//==========================================================================
int hw_CalcLightLevel(int lightlevel, int rellight, bool weapon)
int hw_CalcLightLevel(int lightlevel, int rellight, bool weapon, int blendfactor)
{
int light;
if (lightlevel == 0) return 0;
if ((level.lightmode & 2) && lightlevel < 192 && !weapon)
bool darklightmode = (level.lightmode & 2) || (level.lightmode == 8 && blendfactor > 0);
if (darklightmode && lightlevel < 192 && !weapon)
{
if (lightlevel > 100)
{
@ -126,12 +128,13 @@ PalEntry hw_CalcLightColor(int light, PalEntry pe, int blendfactor)
{
int r,g,b;
if (level.lightmode == 8)
{
return pe;
}
else if (blendfactor == 0)
if (blendfactor == 0)
{
if (level.lightmode == 8)
{
return pe;
}
r = pe.r * light / 255;
g = pe.g * light / 255;
b = pe.b * light / 255;
@ -167,11 +170,14 @@ PalEntry hw_CalcLightColor(int light, PalEntry pe, int blendfactor)
//
//==========================================================================
float hw_GetFogDensity(int lightlevel, PalEntry fogcolor, int sectorfogdensity)
float hw_GetFogDensity(int lightlevel, PalEntry fogcolor, int sectorfogdensity, int blendfactor)
{
float density;
if (level.lightmode & 4)
int lightmode = level.lightmode;
if (lightmode == 8 && blendfactor > 0) lightmode = 2; // The blendfactor feature does not work with software-style lighting.
if (lightmode & 4)
{
// uses approximations of Legacy's default settings.
density = level.fogdensity ? (float)level.fogdensity : 18;
@ -184,7 +190,7 @@ float hw_GetFogDensity(int lightlevel, PalEntry fogcolor, int sectorfogdensity)
else if ((fogcolor.d & 0xffffff) == 0)
{
// case 2: black fog
if (level.lightmode != 8 && !(level.flags3 & LEVEL3_NOLIGHTFADE))
if ((lightmode != 8 || blendfactor > 0) && !(level.flags3 & LEVEL3_NOLIGHTFADE))
{
density = distfogtable[level.lightmode != 0][hw_ClampLight(lightlevel)];
}

View file

@ -7,9 +7,9 @@
struct Colormap;
int hw_CalcLightLevel(int lightlevel, int rellight, bool weapon);
int hw_CalcLightLevel(int lightlevel, int rellight, bool weapon, int blendfactor);
PalEntry hw_CalcLightColor(int light, PalEntry pe, int blendfactor);
float hw_GetFogDensity(int lightlevel, PalEntry fogcolor, int sectorfogdensity);
float hw_GetFogDensity(int lightlevel, PalEntry fogcolor, int sectorfogdensity, int blendfactor);
bool hw_CheckFog(sector_t *frontsector, sector_t *backsector);
inline int hw_ClampLight(int lightlevel)

View file

@ -52,11 +52,7 @@ protected:
static const int MIN_WIDTH = 320;
static const int MIN_HEIGHT = 200;
typedef DECLSPEC int SDLCALL (*SDL_GetWindowBordersSizePtr)(SDL_Window *, int *, int *, int *, int *);
SDL_GetWindowBordersSizePtr SDL_GetWindowBordersSize_;
void *sdl_lib;
};
#endif // __POSIX_SDL_GL_SYSFB_H__

View file

@ -35,6 +35,7 @@
#include "doomtype.h"
#include "i_module.h"
#include "i_system.h"
#include "i_video.h"
#include "m_argv.h"
@ -172,6 +173,11 @@ IVideo *gl_CreateVideo()
// FrameBuffer implementation -----------------------------------------------
FModule sdl_lib("SDL2");
typedef int (*SDL_GetWindowBordersSizePtr)(SDL_Window *, int *, int *, int *, int *);
static TOptProc<sdl_lib, SDL_GetWindowBordersSizePtr> SDL_GetWindowBordersSize_("SDL_GetWindowBordersSize");
SystemGLFrameBuffer::SystemGLFrameBuffer (void *, bool fullscreen)
: DFrameBuffer (vid_defwidth, vid_defheight)
{
@ -180,10 +186,9 @@ SystemGLFrameBuffer::SystemGLFrameBuffer (void *, bool fullscreen)
// SDL_GetWindowBorderSize() is only available since 2.0.5, but because
// GZDoom supports platforms with older SDL2 versions, this function
// has to be dynamically loaded
sdl_lib = SDL_LoadObject("libSDL2.so");
if (sdl_lib != nullptr)
if (!sdl_lib.IsLoaded())
{
SDL_GetWindowBordersSize_ = (SDL_GetWindowBordersSizePtr)SDL_LoadFunction(sdl_lib,"SDL_GetWindowBordersSize");
sdl_lib.Load({ "libSDL2.so", "libSDL2-2.0.so" });
}
// NOTE: Core profiles were added with GL 3.2, so there's no sense trying
@ -261,11 +266,6 @@ SystemGLFrameBuffer::SystemGLFrameBuffer (void *, bool fullscreen)
SystemGLFrameBuffer::~SystemGLFrameBuffer ()
{
if (sdl_lib != nullptr)
{
SDL_UnloadObject(sdl_lib);
}
if (Screen)
{
ResetGammaTable();
@ -391,7 +391,7 @@ void SystemGLFrameBuffer::SetWindowSize(int w, int h)
void SystemGLFrameBuffer::GetWindowBordersSize(int &top, int &left)
{
if (SDL_GetWindowBordersSize_ != nullptr)
if (SDL_GetWindowBordersSize_)
{
SDL_GetWindowBordersSize_(Screen, &top, &left, nullptr, nullptr);
}

View file

@ -1053,7 +1053,7 @@ static int Exec(VMFrameStack *stack, const VMOP *pc, VMReturn *ret, int numret)
NEXTOP;
OP(SRL_KR):
ASSERTD(a); ASSERTKD(B); ASSERTD(C);
reg.d[a] = (unsigned)konstd[B] >> C;
reg.d[a] = (unsigned)konstd[B] >> reg.d[C];
NEXTOP;
OP(SRA_RR):

View file

@ -242,6 +242,7 @@ bool F2DDrawer::SetStyle(FTexture *tex, DrawParms &parms, PalEntry &vertexcolor,
else if (quad.mDrawMode == DTM_Invert) quad.mDrawMode = DTM_InvertOpaque;
}
quad.mRenderStyle = parms.style; // this contains the blend mode and blend equation settings.
if (parms.burn) quad.mFlags |= DTF_Burn;
return true;
}
@ -427,6 +428,7 @@ void F2DDrawer::AddPoly(FTexture *texture, FVector2 *points, int npoints,
// is necessary in order to best reproduce Doom's original lighting.
double fadelevel;
// The hardware renderer's light modes 0, 1 and 4 use a linear light scale which must be used here as well. Otherwise the automap gets too dark.
if (vid_rendermode != 4 || (level.lightmode >= 2 && level.lightmode != 4))
{
double map = (NUMCOLORMAPS * 2.) - ((lightlevel + 12) * (NUMCOLORMAPS / 128.));

View file

@ -53,6 +53,7 @@ public:
{
DTF_Wrap = 1,
DTF_Scissor = 2,
DTF_Burn = 4,
};

View file

@ -511,6 +511,7 @@ bool DFrameBuffer::ParseDrawTextureTags(FTexture *img, double x, double y, uint3
parms->srcy = 0.;
parms->srcwidth = 1.;
parms->srcheight = 1.;
parms->burn = false;
// Parse the tag list for attributes. (For floating point attributes,
// consider that the C ABI dictates that all floats be promoted to
@ -862,6 +863,10 @@ bool DFrameBuffer::ParseDrawTextureTags(FTexture *img, double x, double y, uint3
case DTA_CellY:
parms->celly = ListGetInt(tags);
break;
case DTA_Burn:
parms->burn = true;
break;
}
tag = ListGetInt(tags);

View file

@ -320,9 +320,9 @@ void DFrameBuffer::SetVSync (bool vsync)
//
//==========================================================================
bool DFrameBuffer::WipeStartScreen(int type)
FTexture *DFrameBuffer::WipeStartScreen()
{
return false;
return nullptr;
}
//==========================================================================
@ -334,33 +334,9 @@ bool DFrameBuffer::WipeStartScreen(int type)
//
//==========================================================================
void DFrameBuffer::WipeEndScreen()
{
}
//==========================================================================
//
// DFrameBuffer :: WipeDo
//
// Draws one frame of a screenwipe. Should be called no more than 35
// times per second. If called less than that, ticks indicates how many
// ticks have passed since the last call.
//
//==========================================================================
bool DFrameBuffer::WipeDo(int ticks)
{
return false;
}
//==========================================================================
//
// DFrameBuffer :: WipeCleanup
//
//==========================================================================
void DFrameBuffer::WipeCleanup()
FTexture *DFrameBuffer::WipeEndScreen()
{
return nullptr;
}
//==========================================================================

View file

@ -47,6 +47,7 @@
struct sector_t;
class IShaderProgram;
class FTexture;
enum EHWCaps
{
@ -205,6 +206,7 @@ enum
DTA_SrcWidth,
DTA_SrcHeight,
DTA_LegacyRenderStyle, // takes an old-style STYLE_* constant instead of an FRenderStyle
DTA_Burn, // activates the burn shader for this element
};
@ -261,6 +263,7 @@ struct DrawParms
bool virtBottom;
double srcx, srcy;
double srcwidth, srcheight;
bool burn;
};
struct Va_List
@ -441,14 +444,26 @@ public:
virtual IUniformBuffer *CreateUniformBuffer(size_t size, bool staticuse = false) { return nullptr; }
virtual IShaderProgram *CreateShaderProgram() { return nullptr; }
// Begin 2D drawing operations.
// Returns true if hardware-accelerated 2D has been entered, false if not.
void Begin2D(bool copy3d) { isIn2D = true; }
// Begin/End 2D drawing operations.
void Begin2D() { isIn2D = true; }
void End2D() { isIn2D = false; }
void End2DAndUpdate()
{
DrawRateStuff();
End2D();
Update();
}
// Returns true if Begin2D has been called and 2D drawing is now active
bool HasBegun2D() { return isIn2D; }
// This is overridable in case Vulkan does it differently.
virtual bool RenderTextureIsFlipped() const
{
return true;
}
// Report a game restart
void InitPalette();
@ -460,10 +475,8 @@ public:
virtual sector_t *RenderView(player_t *player) { return nullptr; }
// Screen wiping
virtual bool WipeStartScreen(int type);
virtual void WipeEndScreen();
virtual bool WipeDo(int ticks);
virtual void WipeCleanup();
virtual FTexture *WipeStartScreen();
virtual FTexture *WipeEndScreen();
virtual void PostProcessScene(int fixedcm, const std::function<void()> &afterBloomDrawEndScene2D) { if (afterBloomDrawEndScene2D) afterBloomDrawEndScene2D(); }

View file

@ -15,7 +15,7 @@ void main()
//
// calculate fog factor
//
if (uFogEnabled == -1)
if (uFogEnabled == 1)
{
fogdist = pixelpos.w;
}

View file

@ -358,7 +358,7 @@ vec4 getLightColor(Material material, float fogdist, float fogfactor)
float newlightlevel = 1.0 - R_DoomLightingEquation(uLightLevel);
color.rgb *= newlightlevel;
}
else if (uFogEnabled > 0)
else if (uFogColor.rgb == vec3(0.0))
{
// brightening around the player for light mode 2
if (fogdist < uLightDist)
@ -421,7 +421,7 @@ vec3 AmbientOcclusionColor()
//
// calculate fog factor
//
if (uFogEnabled == -1)
if (uFogEnabled == 1)
{
fogdist = pixelpos.w;
}
@ -449,17 +449,17 @@ void main()
if (frag.a <= uAlphaThreshold) discard;
#endif
if (uFogEnabled != -3) // check for special 2D 'fog' mode.
if (uFogEnabled != 3) // check for special 2D 'fog' mode.
{
float fogdist = 0.0;
float fogfactor = 0.0;
float fogfactor = 1.0;
//
// calculate fog factor
//
if (uFogEnabled != 0)
if (uFogEnabled != 0 && uFogDensity != 0)
{
if (uFogEnabled == 1 || uFogEnabled == -1)
if (uFogEnabled == 1)
{
fogdist = pixelpos.w;
}
@ -476,7 +476,7 @@ void main()
//
// colored fog
//
if (uFogEnabled < 0)
if (uFogColor.rgb != vec3(0.0))
{
frag = applyFog(frag, fogfactor);
}
@ -494,7 +494,7 @@ void main()
vec4 cm = (uObjectColor + gray * (uObjectColor2 - uObjectColor)) * 2;
frag = vec4(clamp(cm.rgb, 0.0, 1.0), frag.a);
}
frag = frag * ProcessLight(material, vColor);
frag = frag * ProcessLight(material, vColor);
frag.rgb = frag.rgb + uFogColor.rgb;
}
FragColor = frag;

View file

@ -87,6 +87,10 @@ void main()
{
gl_ClipDistance[0] = -( (worldcoord.z - uClipLine.y) * uClipLine.z + (uClipLine.x - worldcoord.x) * uClipLine.w ) + 1.0/32768.0; // allow a tiny bit of imprecisions for colinear linedefs.
}
else
{
gl_ClipDistance[0] = 1;
}
// clip planes used for translucency splitting
gl_ClipDistance[1] = worldcoord.y - uClipSplit.x;

View file

@ -73,7 +73,7 @@ class LevelCompatibility play
AddSectorTag(35, 15);
for(int i=605; i<609;i++)
{
SetLineActivation(i, SPAC_PCross);
SetLineActivation(i, SPAC_Cross);
SetLineSpecial(i, Door_Open, 15, 64);
}
break;
@ -187,7 +187,7 @@ class LevelCompatibility play
ClearSectorTags(197);
AddSectorTag(197, 8);
SetLineSpecial(1279, Floor_LowerToLowest, 8, 32);
SetLineActivation(1240, SPAC_PCross);
SetLineActivation(1240, SPAC_Cross);
SetLineSpecial(1240, Floor_LowerToLowest, 38, 32);
break;
}