// // Copyright (C) 1993-1996 by id Software, Inc. // // This source is available for distribution and/or modification // only under the terms of the DOOM Source Code License as // published by id Software. All rights reserved. // // The source is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License // for more details. // #include #include #include "templates.h" #include "i_system.h" #include "w_wad.h" #include "doomdef.h" #include "doomstat.h" #include "r_sky.h" #include "stats.h" #include "v_video.h" #include "a_sharedglobal.h" #include "c_console.h" #include "c_dispatch.h" #include "cmdlib.h" #include "d_net.h" #include "g_level.h" #include "r_utility.h" #include "d_player.h" #include "swrenderer/scene/r_light.h" #include "swrenderer/viewport/r_viewport.h" #include "gl/data/gl_data.h" CVAR(Bool, r_shadercolormaps, true, CVAR_ARCHIVE) EXTERN_CVAR(Bool, r_fullbrightignoresectorcolor) namespace swrenderer { CameraLight *CameraLight::Instance() { static CameraLight instance; return &instance; } void CameraLight::SetCamera(AActor *actor) { player_t *player = actor->player; if (camera && camera->player != nullptr) player = camera->player; realfixedcolormap = nullptr; fixedcolormap = nullptr; fixedlightlev = -1; if (player != nullptr && camera == player->mo) { if (player->fixedcolormap >= 0 && player->fixedcolormap < (int)SpecialColormaps.Size()) { realfixedcolormap = &SpecialColormaps[player->fixedcolormap]; auto viewport = RenderViewport::Instance(); if (viewport->RenderTarget == screen && (viewport->RenderTarget->IsBgra() || ((DFrameBuffer *)screen->Accel2D && r_shadercolormaps))) { // Render everything fullbright. The copy to video memory will // apply the special colormap, so it won't be restricted to the // palette. fixedcolormap = &realcolormaps; } else { fixedcolormap = &SpecialColormaps[player->fixedcolormap]; } } else if (player->fixedlightlevel >= 0 && player->fixedlightlevel < NUMCOLORMAPS) { fixedlightlev = player->fixedlightlevel * 256; // [SP] Emulate GZDoom's light-amp goggles. if (r_fullbrightignoresectorcolor && fixedlightlev >= 0) { fixedcolormap = &FullNormalLight; } } } // [RH] Inverse light for shooting the Sigil if (fixedcolormap == nullptr && extralight == INT_MIN) { fixedcolormap = &SpecialColormaps[INVERSECOLORMAP]; extralight = 0; } } ///////////////////////////////////////////////////////////////////////// LightVisibility *LightVisibility::Instance() { static LightVisibility instance; return &instance; } // Changes how rapidly things get dark with distance void LightVisibility::SetVisibility(double vis) { // Allow negative visibilities, just for novelty's sake vis = clamp(vis, -204.7, 204.7); // (205 and larger do not work in 5:4 aspect ratio) CurrentVisibility = vis; auto viewport = RenderViewport::Instance(); if (FocalTangent == 0 || viewport->FocalLengthY == 0) { // If r_visibility is called before the renderer is all set up, don't // divide by zero. This will be called again later, and the proper // values can be initialized then. return; } BaseVisibility = vis; MaxVisForWall = (viewport->InvZtoScale * (SCREENWIDTH*r_Yaspect) / (viewwidth*SCREENHEIGHT * FocalTangent)); MaxVisForWall = 32767.0 / MaxVisForWall; MaxVisForFloor = 32767.0 / (viewheight >> 2) * viewport->FocalLengthY / 160; // Prevent overflow on walls if (BaseVisibility < 0 && BaseVisibility < -MaxVisForWall) WallVisibility = -MaxVisForWall; else if (BaseVisibility > 0 && BaseVisibility > MaxVisForWall) WallVisibility = MaxVisForWall; else WallVisibility = BaseVisibility; WallVisibility = (viewport->InvZtoScale * SCREENWIDTH*AspectBaseHeight(WidescreenRatio) / (viewwidth*SCREENHEIGHT * 3)) * (WallVisibility * FocalTangent); // Prevent overflow on floors/ceilings. Note that the calculation of // MaxVisForFloor means that planes less than two units from the player's // view could still overflow, but there is no way to totally eliminate // that while still using fixed point math. if (BaseVisibility < 0 && BaseVisibility < -MaxVisForFloor) FloorVisibility = -MaxVisForFloor; else if (BaseVisibility > 0 && BaseVisibility > MaxVisForFloor) FloorVisibility = MaxVisForFloor; else FloorVisibility = BaseVisibility; FloorVisibility = 160.0 * FloorVisibility / viewport->FocalLengthY; TiltVisibility = float(vis * FocalTangent * (16.f * 320.f) / viewwidth); NoLightFade = glset.nolightfade; } fixed_t LightVisibility::LightLevelToShade(int lightlevel, bool foggy) { bool nolightfade = !foggy && (glset.nolightfade); if (nolightfade) { return (MAX(255 - lightlevel, 0) * NUMCOLORMAPS) << (FRACBITS - 8); } else { // Convert a light level into an unbounded colormap index (shade). Result is // fixed point. Why the +12? I wish I knew, but experimentation indicates it // is necessary in order to best reproduce Doom's original lighting. return (NUMCOLORMAPS * 2 * FRACUNIT) - ((lightlevel + 12) * (FRACUNIT*NUMCOLORMAPS / 128)); } } // Controls how quickly light ramps across a 1/z range. Set this, and it // sets all the r_*Visibility variables (except r_SkyVisibilily, which is // currently unused). CCMD(r_visibility) { if (argv.argc() < 2) { Printf("Visibility is %g\n", LightVisibility::Instance()->GetVisibility()); } else if (!netgame) { LightVisibility::Instance()->SetVisibility(atof(argv[1])); } else { Printf("Visibility cannot be changed in net games.\n"); } } ///////////////////////////////////////////////////////////////////////// void ColormapLight::SetColormap(double visibility, int shade, FDynamicColormap *basecolormap, bool fullbright, bool invertColormap, bool fadeToBlack) { if (fadeToBlack) { if (invertColormap) // Fade to white { basecolormap = GetSpecialLights(basecolormap->Color, MAKERGB(255, 255, 255), basecolormap->Desaturate); invertColormap = false; } else // Fade to black { basecolormap = GetSpecialLights(basecolormap->Color, MAKERGB(0, 0, 0), basecolormap->Desaturate); } } if (invertColormap) { basecolormap = GetSpecialLights(basecolormap->Color, basecolormap->Fade.InverseColor(), basecolormap->Desaturate); } CameraLight *cameraLight = CameraLight::Instance(); if (cameraLight->FixedColormap()) { BaseColormap = cameraLight->FixedColormap(); ColormapNum = 0; } else if (cameraLight->FixedLightLevel() >= 0) { BaseColormap = (r_fullbrightignoresectorcolor) ? &FullNormalLight : basecolormap; ColormapNum = cameraLight->FixedLightLevel() >> COLORMAPSHIFT; } else if (fullbright) { BaseColormap = (r_fullbrightignoresectorcolor) ? &FullNormalLight : basecolormap; ColormapNum = 0; } else { BaseColormap = basecolormap; ColormapNum = GETPALOOKUP(visibility, shade); } } }