From def123823b025f2e1d65993947183d0c282147ef Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 11 Apr 2020 19:49:09 +0200 Subject: [PATCH] - cleanup of 2D code. --- src/am_map.cpp | 20 +++- src/d_main.cpp | 2 +- src/g_game.cpp | 3 +- src/r_data/v_palette.h | 5 + src/rendering/2d/v_2ddrawer.cpp | 78 +++++++-------- src/rendering/2d/v_2ddrawer.h | 2 +- src/rendering/2d/v_blend.cpp | 167 ++++++++++++++++++++++++++++++++ src/rendering/2d/v_drawtext.cpp | 10 +- src/rendering/v_video.cpp | 166 ------------------------------- src/rendering/v_video.h | 5 - 10 files changed, 229 insertions(+), 229 deletions(-) diff --git a/src/am_map.cpp b/src/am_map.cpp index 0fcd9a207..bfaa40ea5 100644 --- a/src/am_map.cpp +++ b/src/am_map.cpp @@ -2132,6 +2132,24 @@ void DAutomap::drawSubsectors() } else indices.clear(); + // Use an equation similar to player sprites to determine shade + + // Convert a light level into an unbounded colormap index (shade). + // Why the +12? I wish I knew, but experimentation indicates it + // is necessary in order to best reproduce Doom's original lighting. + double fadelevel; + + if (vid_rendermode != 4 || primaryLevel->lightMode == ELightMode::Doom || primaryLevel->lightMode == ELightMode::ZDoomSoftware || primaryLevel->lightMode == ELightMode::DoomSoftware) + { + double map = (NUMCOLORMAPS * 2.) - ((floorlight + 12) * (NUMCOLORMAPS / 128.)); + fadelevel = clamp((map - 12) / NUMCOLORMAPS, 0.0, 1.0); + } + else + { + // 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. + fadelevel = 1. - clamp(floorlight, 0, 255) / 255.f; + } + twod->AddPoly(TexMan.GetTexture(maptex, true), &points[0], points.Size(), originx, originy, @@ -2140,7 +2158,7 @@ void DAutomap::drawSubsectors() rotation, colormap, flatcolor, - floorlight, + fadelevel, indices.data(), indices.size()); } } diff --git a/src/d_main.cpp b/src/d_main.cpp index bbb70c758..cbd37addb 100644 --- a/src/d_main.cpp +++ b/src/d_main.cpp @@ -924,7 +924,7 @@ void D_Display () screen->Begin2D(); if (!hud_toggled) { - screen->DrawBlend(viewsec); + V_DrawBlend(viewsec); if (automapactive) { primaryLevel->automap->Drawer ((hud_althud && viewheight == SCREENHEIGHT) ? viewheight : StatusBar->GetTopOfStatusbar()); diff --git a/src/g_game.cpp b/src/g_game.cpp index 0c9baf9ea..0bf781260 100644 --- a/src/g_game.cpp +++ b/src/g_game.cpp @@ -74,6 +74,7 @@ #include "a_dynlight.h" #include "i_system.h" #include "p_conversation.h" +#include "v_palette.h" #include "v_video.h" #include "g_hub.h" @@ -2255,7 +2256,7 @@ void DoWriteSavePic(FileWriter *file, ESSType ssformat, uint8_t *scr, int width, { PalEntry palette[256]; PalEntry modulateColor; - auto blend = screen->CalcBlend(viewsector, &modulateColor); + auto blend = V_CalcBlend(viewsector, &modulateColor); int pixelsize = 1; // Apply the screen blend, because the renderer does not provide this. if (ssformat == SS_RGB) diff --git a/src/r_data/v_palette.h b/src/r_data/v_palette.h index 07b1f477a..648f205a4 100644 --- a/src/r_data/v_palette.h +++ b/src/r_data/v_palette.h @@ -37,6 +37,7 @@ #include "doomtype.h" #include "c_cvars.h" #include "palutil.h" +#include "vectors.h" @@ -56,8 +57,12 @@ enum PaletteFlashFlags }; class player_t; +struct sector_t; void V_AddBlend (float r, float g, float b, float a, float v_blend[4]); void V_AddPlayerBlend (player_t *CPlayer, float blend[4], float maxinvalpha, int maxpainblend); +// Dim part of the canvas +FVector4 V_CalcBlend(sector_t* viewsector, PalEntry* modulateColor); +void V_DrawBlend(sector_t* viewsector); #endif //__V_PALETTE_H__ diff --git a/src/rendering/2d/v_2ddrawer.cpp b/src/rendering/2d/v_2ddrawer.cpp index 7330aa9a9..40dbd8492 100644 --- a/src/rendering/2d/v_2ddrawer.cpp +++ b/src/rendering/2d/v_2ddrawer.cpp @@ -1,38 +1,43 @@ -// -//--------------------------------------------------------------------------- -// -// Copyright(C) 2016-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/ -// -//-------------------------------------------------------------------------- -// /* ** v_2ddrawer.h ** Device independent 2D draw list ** -**/ +**--------------------------------------------------------------------------- +** Copyright 2016-2020 Christoph Oelckers +** All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** 1. Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** 2. Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** 3. The name of the author may not be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +**--------------------------------------------------------------------------- +** +*/ #include -#include "doomtype.h" #include "templates.h" -#include "r_utility.h" -#include "v_video.h" -#include "g_levellocals.h" #include "vm.h" -#include "c_buttons.h" +#include "c_cvars.h" +#include "v_draw.h" +#include "fcolormap.h" F2DDrawer* twod; @@ -538,26 +543,9 @@ void F2DDrawer::AddShape( FTexture *img, DShape2D *shape, DrawParms &parms ) void F2DDrawer::AddPoly(FTexture *texture, FVector2 *points, int npoints, double originx, double originy, double scalex, double scaley, - DAngle rotation, const FColormap &colormap, PalEntry flatcolor, int lightlevel, + DAngle rotation, const FColormap &colormap, PalEntry flatcolor, double fadelevel, uint32_t *indices, size_t indexcount) { - // Use an equation similar to player sprites to determine shade - - // Convert a light level into an unbounded colormap index (shade). - // Why the +12? I wish I knew, but experimentation indicates it - // is necessary in order to best reproduce Doom's original lighting. - double fadelevel; - - if (vid_rendermode != 4 || primaryLevel->lightMode == ELightMode::Doom || primaryLevel->lightMode == ELightMode::ZDoomSoftware || primaryLevel->lightMode == ELightMode::DoomSoftware) - { - double map = (NUMCOLORMAPS * 2.) - ((lightlevel + 12) * (NUMCOLORMAPS / 128.)); - fadelevel = clamp((map - 12) / NUMCOLORMAPS, 0.0, 1.0); - } - else - { - // 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. - fadelevel = 1. - clamp(lightlevel, 0, 255) / 255.f; - } RenderCommand poly; diff --git a/src/rendering/2d/v_2ddrawer.h b/src/rendering/2d/v_2ddrawer.h index ff25e7dee..1bf60ff9b 100644 --- a/src/rendering/2d/v_2ddrawer.h +++ b/src/rendering/2d/v_2ddrawer.h @@ -162,7 +162,7 @@ public: void AddShape(FTexture *img, DShape2D *shape, DrawParms &parms); void AddPoly(FTexture *texture, FVector2 *points, int npoints, double originx, double originy, double scalex, double scaley, - DAngle rotation, const FColormap &colormap, PalEntry flatcolor, int lightlevel, uint32_t *indices, size_t indexcount); + DAngle rotation, const FColormap &colormap, PalEntry flatcolor, double lightlevel, uint32_t *indices, size_t indexcount); void AddFlatFill(int left, int top, int right, int bottom, FTexture *src, bool local_origin = false); void AddColorOnlyQuad(int left, int top, int width, int height, PalEntry color, FRenderStyle *style); diff --git a/src/rendering/2d/v_blend.cpp b/src/rendering/2d/v_blend.cpp index b6fddcee1..95780e31c 100644 --- a/src/rendering/2d/v_blend.cpp +++ b/src/rendering/2d/v_blend.cpp @@ -45,7 +45,10 @@ #include "g_levellocals.h" #include "vm.h" #include "v_palette.h" +#include "r_utility.h" +#include "hwrenderer/utility/hw_cvars.h" +CVAR(Float, underwater_fade_scalar, 1.0f, CVAR_ARCHIVE) // [Nash] user-settable underwater blend intensity CVAR( Float, blood_fade_scalar, 1.0f, CVAR_ARCHIVE ) // [SP] Pulled from Skulltag - changed default from 0.5 to 1.0 CVAR( Float, pickup_fade_scalar, 1.0f, CVAR_ARCHIVE ) // [SP] Uses same logic as blood_fade_scalar except for pickups @@ -208,3 +211,167 @@ void V_AddPlayerBlend (player_t *CPlayer, float blend[4], float maxinvalpha, int // cap opacity if desired if (blend[3] > maxinvalpha) blend[3] = maxinvalpha; } + +//========================================================================== +// +// Draws a blend over the entire view +// +//========================================================================== + +FVector4 V_CalcBlend(sector_t* viewsector, PalEntry* modulateColor) +{ + float blend[4] = { 0,0,0,0 }; + PalEntry blendv = 0; + float extra_red; + float extra_green; + float extra_blue; + player_t* player = nullptr; + bool fullbright = false; + + if (modulateColor) *modulateColor = 0xffffffff; + + if (players[consoleplayer].camera != nullptr) + { + player = players[consoleplayer].camera->player; + if (player) + fullbright = (player->fixedcolormap != NOFIXEDCOLORMAP || player->extralight == INT_MIN || player->fixedlightlevel != -1); + } + + // don't draw sector based blends when any fullbright screen effect is active. + if (!fullbright) + { + const auto& vpp = r_viewpoint.Pos; + if (!viewsector->e->XFloor.ffloors.Size()) + { + if (viewsector->GetHeightSec()) + { + auto s = viewsector->heightsec; + blendv = s->floorplane.PointOnSide(vpp) < 0 ? s->bottommap : s->ceilingplane.PointOnSide(vpp) < 0 ? s->topmap : s->midmap; + } + } + else + { + TArray& lightlist = viewsector->e->XFloor.lightlist; + + for (unsigned int i = 0; i < lightlist.Size(); i++) + { + double lightbottom; + if (i < lightlist.Size() - 1) + lightbottom = lightlist[i + 1].plane.ZatPoint(vpp); + else + lightbottom = viewsector->floorplane.ZatPoint(vpp); + + if (lightbottom < vpp.Z && (!lightlist[i].caster || !(lightlist[i].caster->flags & FF_FADEWALLS))) + { + // 3d floor 'fog' is rendered as a blending value + blendv = lightlist[i].blend; + // If this is the same as the sector's it doesn't apply! + if (blendv == viewsector->Colormap.FadeColor) blendv = 0; + // a little hack to make this work for Legacy maps. + if (blendv.a == 0 && blendv != 0) blendv.a = 128; + break; + } + } + } + + if (blendv.a == 0 && V_IsTrueColor()) // The paletted software renderer uses the original colormap as this frame's palette, but in true color that isn't doable. + { + blendv = R_BlendForColormap(blendv); + } + + if (blendv.a == 255) + { + + extra_red = blendv.r / 255.0f; + extra_green = blendv.g / 255.0f; + extra_blue = blendv.b / 255.0f; + + // If this is a multiplicative blend do it separately and add the additive ones on top of it. + + // black multiplicative blends are ignored + if (extra_red || extra_green || extra_blue) + { + if (modulateColor) *modulateColor = blendv; + } + blendv = 0; + } + else if (blendv.a) + { + // [Nash] allow user to set blend intensity + int cnt = blendv.a; + cnt = (int)(cnt * underwater_fade_scalar); + + V_AddBlend(blendv.r / 255.f, blendv.g / 255.f, blendv.b / 255.f, cnt / 255.0f, blend); + } + } + else if (player && player->fixedlightlevel != -1 && player->fixedcolormap == NOFIXEDCOLORMAP) + { + // Draw fixedlightlevel effects as a 2D overlay. The hardware renderer just processes such a scene fullbright without any lighting. + auto torchtype = PClass::FindActor(NAME_PowerTorch); + auto litetype = PClass::FindActor(NAME_PowerLightAmp); + PalEntry color = 0xffffffff; + for (AActor* in = player->mo->Inventory; in; in = in->Inventory) + { + // Need special handling for light amplifiers + if (in->IsKindOf(torchtype)) + { + // The software renderer already bakes the torch flickering into its output, so this must be omitted here. + float r = vid_rendermode < 4 ? 1.f : (0.8f + (7 - player->fixedlightlevel) / 70.0f); + if (r > 1.0f) r = 1.0f; + int rr = (int)(r * 255); + int b = rr; + if (gl_enhanced_nightvision) b = b * 3 / 4; + color = PalEntry(255, rr, rr, b); + } + else if (in->IsKindOf(litetype)) + { + if (gl_enhanced_nightvision) + { + color = PalEntry(255, 104, 255, 104); + } + } + } + if (modulateColor) + { + *modulateColor = color; + } + } + + if (player) + { + V_AddPlayerBlend(player, blend, 0.5, 175); + } + + if (players[consoleplayer].camera != NULL) + { + // except for fadeto effects + player_t* player = (players[consoleplayer].camera->player != NULL) ? players[consoleplayer].camera->player : &players[consoleplayer]; + V_AddBlend(player->BlendR, player->BlendG, player->BlendB, player->BlendA, blend); + } + + const float br = clamp(blend[0] * 255.f, 0.f, 255.f); + const float bg = clamp(blend[1] * 255.f, 0.f, 255.f); + const float bb = clamp(blend[2] * 255.f, 0.f, 255.f); + return { br, bg, bb, blend[3] }; +} + +//========================================================================== +// +// Draws a blend over the entire view +// +//========================================================================== + +void V_DrawBlend(sector_t* viewsector) +{ + auto drawer = twod; + PalEntry modulateColor; + auto blend = V_CalcBlend(viewsector, &modulateColor); + if (modulateColor != 0xffffffff) + { + Dim(twod, modulateColor, 1, 0, 0, drawer->GetWidth(), drawer->GetHeight(), &LegacyRenderStyles[STYLE_Multiply]); + } + + const PalEntry bcolor(255, uint8_t(blend.X), uint8_t(blend.Y), uint8_t(blend.Z)); + Dim(drawer, bcolor, blend.W, 0, 0, drawer->GetWidth(), drawer->GetHeight()); +} + diff --git a/src/rendering/2d/v_drawtext.cpp b/src/rendering/2d/v_drawtext.cpp index 1e50fdccd..056f96036 100644 --- a/src/rendering/2d/v_drawtext.cpp +++ b/src/rendering/2d/v_drawtext.cpp @@ -39,17 +39,9 @@ #include "v_text.h" #include "utf8.h" - - -#include "v_video.h" -#include "filesystem.h" -#include "image.h" -#include "multipatchtexture.h" - +#include "v_draw.h" #include "gstrings.h" #include "vm.h" -#include "serializer.h" - int ListGetInt(VMVa_List &tags); diff --git a/src/rendering/v_video.cpp b/src/rendering/v_video.cpp index 93a11357d..6458c7638 100644 --- a/src/rendering/v_video.cpp +++ b/src/rendering/v_video.cpp @@ -70,11 +70,8 @@ #include "g_levellocals.h" #include "am_map.h" #include "texturemanager.h" -#include "hwrenderer/utility/hw_cvars.h" #include "v_palette.h" -CVAR(Float, underwater_fade_scalar, 1.0f, CVAR_ARCHIVE) // [Nash] user-settable underwater blend intensity - EXTERN_CVAR(Int, menu_resolution_custom_width) EXTERN_CVAR(Int, menu_resolution_custom_height) @@ -514,169 +511,6 @@ IHardwareTexture* CreateHardwareTexture() return screen->CreateHardwareTexture(); } -//========================================================================== -// -// Draws a blend over the entire view -// -//========================================================================== - -FVector4 DFrameBuffer::CalcBlend(sector_t* viewsector, PalEntry* modulateColor) -{ - float blend[4] = { 0,0,0,0 }; - PalEntry blendv = 0; - float extra_red; - float extra_green; - float extra_blue; - player_t* player = nullptr; - bool fullbright = false; - - if (modulateColor) *modulateColor = 0xffffffff; - - if (players[consoleplayer].camera != nullptr) - { - player = players[consoleplayer].camera->player; - if (player) - fullbright = (player->fixedcolormap != NOFIXEDCOLORMAP || player->extralight == INT_MIN || player->fixedlightlevel != -1); - } - - // don't draw sector based blends when any fullbright screen effect is active. - if (!fullbright) - { - const auto& vpp = r_viewpoint.Pos; - if (!viewsector->e->XFloor.ffloors.Size()) - { - if (viewsector->GetHeightSec()) - { - auto s = viewsector->heightsec; - blendv = s->floorplane.PointOnSide(vpp) < 0 ? s->bottommap : s->ceilingplane.PointOnSide(vpp) < 0 ? s->topmap : s->midmap; - } - } - else - { - TArray& lightlist = viewsector->e->XFloor.lightlist; - - for (unsigned int i = 0; i < lightlist.Size(); i++) - { - double lightbottom; - if (i < lightlist.Size() - 1) - lightbottom = lightlist[i + 1].plane.ZatPoint(vpp); - else - lightbottom = viewsector->floorplane.ZatPoint(vpp); - - if (lightbottom < vpp.Z && (!lightlist[i].caster || !(lightlist[i].caster->flags & FF_FADEWALLS))) - { - // 3d floor 'fog' is rendered as a blending value - blendv = lightlist[i].blend; - // If this is the same as the sector's it doesn't apply! - if (blendv == viewsector->Colormap.FadeColor) blendv = 0; - // a little hack to make this work for Legacy maps. - if (blendv.a == 0 && blendv != 0) blendv.a = 128; - break; - } - } - } - - if (blendv.a == 0 && V_IsTrueColor()) // The paletted software renderer uses the original colormap as this frame's palette, but in true color that isn't doable. - { - blendv = R_BlendForColormap(blendv); - } - - if (blendv.a == 255) - { - - extra_red = blendv.r / 255.0f; - extra_green = blendv.g / 255.0f; - extra_blue = blendv.b / 255.0f; - - // If this is a multiplicative blend do it separately and add the additive ones on top of it. - - // black multiplicative blends are ignored - if (extra_red || extra_green || extra_blue) - { - if (modulateColor) *modulateColor = blendv; - } - blendv = 0; - } - else if (blendv.a) - { - // [Nash] allow user to set blend intensity - int cnt = blendv.a; - cnt = (int)(cnt * underwater_fade_scalar); - - V_AddBlend(blendv.r / 255.f, blendv.g / 255.f, blendv.b / 255.f, cnt / 255.0f, blend); - } - } - else if (player && player->fixedlightlevel != -1 && player->fixedcolormap == NOFIXEDCOLORMAP) - { - // Draw fixedlightlevel effects as a 2D overlay. The hardware renderer just processes such a scene fullbright without any lighting. - auto torchtype = PClass::FindActor(NAME_PowerTorch); - auto litetype = PClass::FindActor(NAME_PowerLightAmp); - PalEntry color = 0xffffffff; - for (AActor* in = player->mo->Inventory; in; in = in->Inventory) - { - // Need special handling for light amplifiers - if (in->IsKindOf(torchtype)) - { - // The software renderer already bakes the torch flickering into its output, so this must be omitted here. - float r = vid_rendermode < 4 ? 1.f : (0.8f + (7 - player->fixedlightlevel) / 70.0f); - if (r > 1.0f) r = 1.0f; - int rr = (int)(r * 255); - int b = rr; - if (gl_enhanced_nightvision) b = b * 3 / 4; - color = PalEntry(255, rr, rr, b); - } - else if (in->IsKindOf(litetype)) - { - if (gl_enhanced_nightvision) - { - color = PalEntry(255, 104, 255, 104); - } - } - } - if (modulateColor) - { - *modulateColor = color; - } - } - - if (player) - { - V_AddPlayerBlend(player, blend, 0.5, 175); - } - - if (players[consoleplayer].camera != NULL) - { - // except for fadeto effects - player_t* player = (players[consoleplayer].camera->player != NULL) ? players[consoleplayer].camera->player : &players[consoleplayer]; - V_AddBlend(player->BlendR, player->BlendG, player->BlendB, player->BlendA, blend); - } - - const float br = clamp(blend[0] * 255.f, 0.f, 255.f); - const float bg = clamp(blend[1] * 255.f, 0.f, 255.f); - const float bb = clamp(blend[2] * 255.f, 0.f, 255.f); - return { br, bg, bb, blend[3] }; -} - -//========================================================================== -// -// Draws a blend over the entire view -// -//========================================================================== - -void DFrameBuffer::DrawBlend(sector_t* viewsector) -{ - PalEntry modulateColor; - auto blend = CalcBlend(viewsector, &modulateColor); - if (modulateColor != 0xffffffff) - { - Dim(twod, modulateColor, 1, 0, 0, GetWidth(), GetHeight(), &LegacyRenderStyles[STYLE_Multiply]); - } - - const PalEntry bcolor(255, uint8_t(blend.X), uint8_t(blend.Y), uint8_t(blend.Z)); - Dim(twod, bcolor, blend.W, 0, 0, GetWidth(), GetHeight()); -} - - //========================================================================== // // V_DrawFrame diff --git a/src/rendering/v_video.h b/src/rendering/v_video.h index 9d14c5bdc..1030e4d62 100644 --- a/src/rendering/v_video.h +++ b/src/rendering/v_video.h @@ -330,11 +330,6 @@ public: virtual void Draw2D() {} void Clear2D() { m2DDrawer.Clear(); } - // Dim part of the canvas - FVector4 CalcBlend(sector_t * viewsector, PalEntry *modulateColor); - void DrawBlend(sector_t * viewsector); - - // Calculate gamma table void CalcGamma(float gamma, uint8_t gammalookup[256]);