diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index d377fd09e..55ebc6a09 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -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 diff --git a/src/d_main.cpp b/src/d_main.cpp index 4d113c4d7..01c97b2ae 100644 --- a/src/d_main.cpp +++ b/src/d_main.cpp @@ -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 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 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; } diff --git a/src/f_wipe.cpp b/src/f_wipe.cpp index 31edce0fd..6d34936fd 100644 --- a/src/f_wipe.cpp +++ b/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,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((*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); +} diff --git a/src/f_wipe.h b/src/f_wipe.h index dc4cfb8cc..c639307aa 100644 --- a/src/f_wipe.h +++ b/src/f_wipe.h @@ -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 diff --git a/src/gl/data/gl_viewpointbuffer.cpp b/src/gl/data/gl_viewpointbuffer.cpp new file mode 100644 index 000000000..eb4d8c92e --- /dev/null +++ b/src/gl/data/gl_viewpointbuffer.cpp @@ -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); +} + diff --git a/src/gl/data/gl_viewpointbuffer.h b/src/gl/data/gl_viewpointbuffer.h new file mode 100644 index 000000000..3ec1093df --- /dev/null +++ b/src/gl/data/gl_viewpointbuffer.h @@ -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 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; } +}; + diff --git a/src/gl/renderer/gl_lightdata.cpp b/src/gl/renderer/gl_lightdata.cpp index 7566c0f12..4668af261 100644 --- a/src/gl/renderer/gl_lightdata.cpp +++ b/src/gl/renderer/gl_lightdata.cpp @@ -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); } diff --git a/src/gl/renderer/gl_renderer.cpp b/src/gl/renderer/gl_renderer.cpp index 47d82c965..d4b6197f9 100644 --- a/src/gl/renderer/gl_renderer.cpp +++ b/src/gl/renderer/gl_renderer.cpp @@ -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); diff --git a/src/gl/renderer/gl_renderer.h b/src/gl/renderer/gl_renderer.h index 7551d4428..3a48a9ccb 100644 --- a/src/gl/renderer/gl_renderer.h +++ b/src/gl/renderer/gl_renderer.h @@ -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; diff --git a/src/gl/renderer/gl_renderstate.cpp b/src/gl/renderer/gl_renderstate.cpp index e585296f6..a5de63896 100644 --- a/src/gl/renderer/gl_renderstate.cpp +++ b/src/gl/renderer/gl_renderstate.cpp @@ -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); diff --git a/src/gl/renderer/gl_renderstate.h b/src/gl/renderer/gl_renderstate.h index e3a7615b3..c046d3f61 100644 --- a/src/gl/renderer/gl_renderstate.h +++ b/src/gl/renderer/gl_renderstate.h @@ -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; } diff --git a/src/gl/scene/gl_drawinfo.cpp b/src/gl/scene/gl_drawinfo.cpp index fbc5aa60c..7cddfdec4 100644 --- a/src/gl/scene/gl_drawinfo.cpp +++ b/src/gl/scene/gl_drawinfo.cpp @@ -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; diff --git a/src/gl/scene/gl_drawinfo.h b/src/gl/scene/gl_drawinfo.h index e41e718a2..702c3981c 100644 --- a/src/gl/scene/gl_drawinfo.h +++ b/src/gl/scene/gl_drawinfo.h @@ -38,6 +38,7 @@ struct FDrawInfo : public HWDrawInfo HWDrawList drawlists[GLDL_TYPES]; TArray hudsprites; // These may just be stored by value. TArray decals[2]; // the second slot is for mirrors which get rendered in a separate pass. + int vpIndex; void ApplyVPUniforms() override; diff --git a/src/gl/scene/gl_portal.cpp b/src/gl/scene/gl_portal.cpp index 6f721a7dc..5820f11df 100644 --- a/src/gl/scene/gl_portal.cpp +++ b/src/gl/scene/gl_portal.cpp @@ -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(di)->EndDrawInfo(); - di->ApplyVPUniforms(); + GLRenderer->mViewpoints->Bind(static_cast(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); diff --git a/src/gl/scene/gl_scene.cpp b/src/gl/scene/gl_scene.cpp index fa7b9f7a7..3044d4bd6 100644 --- a/src/gl/scene/gl_scene.cpp +++ b/src/gl/scene/gl_scene.cpp @@ -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) diff --git a/src/gl/scene/gl_skydome.cpp b/src/gl/scene/gl_skydome.cpp index 9feaad5b0..afc4d16dd 100644 --- a/src/gl/scene/gl_skydome.cpp +++ b/src/gl/scene/gl_skydome.cpp @@ -269,7 +269,6 @@ void GLSkyPortal::DrawContents(HWDrawInfo *di) } } gl_RenderState.SetVertexBuffer(GLRenderer->mVBO); - di->ApplyVPUniforms(); ::level.lightmode = oldlightmode; gl_RenderState.SetDepthClamp(oldClamp); } diff --git a/src/gl/scene/gl_sprite.cpp b/src/gl/scene/gl_sprite.cpp index a17241142..985286a2a 100644 --- a/src/gl/scene/gl_sprite.cpp +++ b/src/gl/scene/gl_sprite.cpp @@ -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); diff --git a/src/gl/shaders/gl_shader.cpp b/src/gl/shaders/gl_shader.cpp index 5f3fae934..19d30ed47 100644 --- a/src/gl/shaders/gl_shader.cpp +++ b/src/gl/shaders/gl_shader.cpp @@ -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); - } -} - //========================================================================== // // diff --git a/src/gl/shaders/gl_shader.h b/src/gl/shaders/gl_shader.h index cb63b502d..2d1d28f76 100644 --- a/src/gl/shaders/gl_shader.h +++ b/src/gl/shaders/gl_shader.h @@ -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) { diff --git a/src/gl/system/gl_framebuffer.cpp b/src/gl/system/gl_framebuffer.cpp index cb5c92534..729ecad1f 100644 --- a/src/gl/system/gl_framebuffer.cpp +++ b/src/gl/system/gl_framebuffer.cpp @@ -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::functionPostProcessScene(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(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(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; +} + diff --git a/src/gl/system/gl_framebuffer.h b/src/gl/system/gl_framebuffer.h index e1cd3a18e..44a380b3a 100644 --- a/src/gl/system/gl_framebuffer.h +++ b/src/gl/system/gl_framebuffer.h @@ -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 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: }; diff --git a/src/gl/system/gl_wipe.cpp b/src/gl/system/gl_wipe.cpp deleted file mode 100644 index ac5b924cd..000000000 --- a/src/gl/system/gl_wipe.cpp +++ /dev/null @@ -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((*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); -} diff --git a/src/hwrenderer/data/shaderuniforms.h b/src/hwrenderer/data/shaderuniforms.h index 9400fa0a5..4ec9c2393 100644 --- a/src/hwrenderer/data/shaderuniforms.h +++ b/src/hwrenderer/data/shaderuniforms.h @@ -7,7 +7,8 @@ enum { LIGHTBUF_BINDINGPOINT = 1, - POSTPROCESS_BINDINGPOINT = 2 + POSTPROCESS_BINDINGPOINT = 2, + VIEWPOINT_BINDINGPOINT = 3 }; enum class UniformType diff --git a/src/hwrenderer/scene/hw_drawinfo.cpp b/src/hwrenderer/scene/hw_drawinfo.cpp index b5dce2247..bf04aef6c 100644 --- a/src/hwrenderer/scene/hw_drawinfo.cpp +++ b/src/hwrenderer/scene/hw_drawinfo.cpp @@ -280,5 +280,6 @@ void HWViewpointUniforms::SetDefaults() mGlobVis = (float)R_GetGlobVis(r_viewwindow, r_visibility) / 32.f; mPalLightLevels = static_cast(gl_bandedswlight) | (static_cast(gl_fogmode) << 8); mClipLine.X = -10000000.0f; + mFogEnabled = gl_fogmode; } diff --git a/src/hwrenderer/scene/hw_viewpointuniforms.h b/src/hwrenderer/scene/hw_viewpointuniforms.h index 27a78aef4..675ee71eb 100644 --- a/src/hwrenderer/scene/hw_viewpointuniforms.h +++ b/src/hwrenderer/scene/hw_viewpointuniforms.h @@ -16,6 +16,7 @@ struct HWViewpointUniforms int mViewHeight = 0; float mClipHeight = 0.f; float mClipHeightDirection = 0.f; + int mFogEnabled = 0; void CalcDependencies() { diff --git a/src/hwrenderer/scene/hw_weapon.cpp b/src/hwrenderer/scene/hw_weapon.cpp index b0861e8bd..8e3650310 100644 --- a/src/hwrenderer/scene/hw_weapon.cpp +++ b/src/hwrenderer/scene/hw_weapon.cpp @@ -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) { diff --git a/src/hwrenderer/utility/hw_clock.cpp b/src/hwrenderer/utility/hw_clock.cpp index 74aa096a4..40c61924b 100644 --- a/src/hwrenderer/utility/hw_clock.cpp +++ b/src/hwrenderer/utility/hw_clock.cpp @@ -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) diff --git a/src/hwrenderer/utility/hw_clock.h b/src/hwrenderer/utility/hw_clock.h index 7cb82fedc..243ec4924 100644 --- a/src/hwrenderer/utility/hw_clock.h +++ b/src/hwrenderer/utility/hw_clock.h @@ -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; diff --git a/src/hwrenderer/utility/hw_lighting.cpp b/src/hwrenderer/utility/hw_lighting.cpp index 04836a51c..83e2acd7d 100644 --- a/src/hwrenderer/utility/hw_lighting.cpp +++ b/src/hwrenderer/utility/hw_lighting.cpp @@ -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)]; } diff --git a/src/hwrenderer/utility/hw_lighting.h b/src/hwrenderer/utility/hw_lighting.h index 9acb1578d..94304b014 100644 --- a/src/hwrenderer/utility/hw_lighting.h +++ b/src/hwrenderer/utility/hw_lighting.h @@ -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) diff --git a/src/posix/sdl/gl_sysfb.h b/src/posix/sdl/gl_sysfb.h index ee2713bc5..44b92cf1a 100644 --- a/src/posix/sdl/gl_sysfb.h +++ b/src/posix/sdl/gl_sysfb.h @@ -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__ + diff --git a/src/posix/sdl/sdlglvideo.cpp b/src/posix/sdl/sdlglvideo.cpp index 15c0e4944..b270fcdab 100644 --- a/src/posix/sdl/sdlglvideo.cpp +++ b/src/posix/sdl/sdlglvideo.cpp @@ -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_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); } diff --git a/src/scripting/vm/vmexec.h b/src/scripting/vm/vmexec.h index 1b6c49480..0d58f95f9 100644 --- a/src/scripting/vm/vmexec.h +++ b/src/scripting/vm/vmexec.h @@ -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): diff --git a/src/v_2ddrawer.cpp b/src/v_2ddrawer.cpp index a09ecd5fd..a2388b65b 100644 --- a/src/v_2ddrawer.cpp +++ b/src/v_2ddrawer.cpp @@ -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.)); diff --git a/src/v_2ddrawer.h b/src/v_2ddrawer.h index f60665e9e..5cef4f719 100644 --- a/src/v_2ddrawer.h +++ b/src/v_2ddrawer.h @@ -53,6 +53,7 @@ public: { DTF_Wrap = 1, DTF_Scissor = 2, + DTF_Burn = 4, }; diff --git a/src/v_draw.cpp b/src/v_draw.cpp index 765b20003..e3babb060 100644 --- a/src/v_draw.cpp +++ b/src/v_draw.cpp @@ -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); diff --git a/src/v_framebuffer.cpp b/src/v_framebuffer.cpp index 6debe64e0..0b1338d37 100644 --- a/src/v_framebuffer.cpp +++ b/src/v_framebuffer.cpp @@ -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; } //========================================================================== diff --git a/src/v_video.h b/src/v_video.h index ec0e43f3d..72ae6e0a5 100644 --- a/src/v_video.h +++ b/src/v_video.h @@ -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 &afterBloomDrawEndScene2D) { if (afterBloomDrawEndScene2D) afterBloomDrawEndScene2D(); } diff --git a/wadsrc/static/shaders/glsl/fogboundary.fp b/wadsrc/static/shaders/glsl/fogboundary.fp index 9dcdb4850..81880f984 100644 --- a/wadsrc/static/shaders/glsl/fogboundary.fp +++ b/wadsrc/static/shaders/glsl/fogboundary.fp @@ -15,7 +15,7 @@ void main() // // calculate fog factor // - if (uFogEnabled == -1) + if (uFogEnabled == 1) { fogdist = pixelpos.w; } diff --git a/wadsrc/static/shaders/glsl/main.fp b/wadsrc/static/shaders/glsl/main.fp index d5283b26c..c4caa785e 100644 --- a/wadsrc/static/shaders/glsl/main.fp +++ b/wadsrc/static/shaders/glsl/main.fp @@ -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; diff --git a/wadsrc/static/shaders/glsl/main.vp b/wadsrc/static/shaders/glsl/main.vp index 1089cadcb..e25438c02 100644 --- a/wadsrc/static/shaders/glsl/main.vp +++ b/wadsrc/static/shaders/glsl/main.vp @@ -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; diff --git a/wadsrc/static/zscript/level_compatibility.txt b/wadsrc/static/zscript/level_compatibility.txt index 08ac52a15..a932a0b18 100644 --- a/wadsrc/static/zscript/level_compatibility.txt +++ b/wadsrc/static/zscript/level_compatibility.txt @@ -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; }