diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 3b90ec61f..5155cd471 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1058,6 +1058,7 @@ set (PCH_SOURCES hwrenderer/textures/hw_precache.cpp hwrenderer/utility/hw_clock.cpp hwrenderer/utility/hw_cvars.cpp + hwrenderer/utility/hw_lighting.cpp menu/joystickmenu.cpp menu/loadsavemenu.cpp diff --git a/src/gl/compatibility/gl_20.cpp b/src/gl/compatibility/gl_20.cpp index c977b754d..57405e4ab 100644 --- a/src/gl/compatibility/gl_20.cpp +++ b/src/gl/compatibility/gl_20.cpp @@ -495,7 +495,7 @@ bool gl_SetupLightTexture() // //========================================================================== -static bool gl_CheckFog(FColormap *cm, int lightlevel) +static bool CheckFog(FColormap *cm, int lightlevel) { bool frontfog; @@ -549,7 +549,7 @@ bool FDrawInfo::PutWallCompat(GLWall *wall, int passflag) if (wall->sub->lighthead == nullptr) return false; } - bool foggy = gl_CheckFog(&wall->Colormap, wall->lightlevel) || (level.flags&LEVEL_HASFADETABLE) || gl_lights_additive; + bool foggy = CheckFog(&wall->Colormap, wall->lightlevel) || (level.flags&LEVEL_HASFADETABLE) || gl_lights_additive; bool masked = passflag == 2 && wall->gltexture->isMasked(); int list = list_indices[masked][foggy]; @@ -574,7 +574,7 @@ bool GLFlat::PutFlatCompat(bool fog) { { GLLDL_FLATS_PLAIN, GLLDL_FLATS_FOG },{ GLLDL_FLATS_MASKED, GLLDL_FLATS_FOGMASKED } }; bool masked = gltexture->isMasked() && ((renderflags&SSRF_RENDER3DPLANES) || stack); - bool foggy = gl_CheckFog(&Colormap, lightlevel) || (level.flags&LEVEL_HASFADETABLE) || gl_lights_additive; + bool foggy = CheckFog(&Colormap, lightlevel) || (level.flags&LEVEL_HASFADETABLE) || gl_lights_additive; int list = list_indices[masked][foggy]; @@ -600,7 +600,7 @@ void FDrawInfo::RenderFogBoundaryCompat(GLWall *wall) auto ztop = wall->ztop; auto zbottom = wall->zbottom; - float fogdensity = gl_GetFogDensity(wall->lightlevel, Colormap.FadeColor, Colormap.FogDensity); + float fogdensity = hw_GetFogDensity(wall->lightlevel, Colormap.FadeColor, Colormap.FogDensity); float dist1 = Dist2(r_viewpoint.Pos.X, r_viewpoint.Pos.Y, glseg.x1, glseg.y1); float dist2 = Dist2(r_viewpoint.Pos.X, r_viewpoint.Pos.Y, glseg.x2, glseg.y2); @@ -832,7 +832,7 @@ void FDrawInfo::RenderLightsCompat(GLWall *wall, int pass) if (PrepareLight(wall, light, pass)) { wall->vertcount = 0; - wall->RenderWall(GLWall::RWF_TEXTURED); + RenderWall(wall, GLWall::RWF_TEXTURED); } node = node->nextLight; } diff --git a/src/gl/renderer/gl_lightdata.cpp b/src/gl/renderer/gl_lightdata.cpp index 744aa02f0..345fc4c0f 100644 --- a/src/gl/renderer/gl_lightdata.cpp +++ b/src/gl/renderer/gl_lightdata.cpp @@ -28,7 +28,6 @@ #include "gl/system/gl_system.h" #include "gl/system/gl_interface.h" #include "hwrenderer/utility/hw_cvars.h" -#include "gl/renderer/gl_colormap.h" #include "gl/renderer/gl_lightdata.h" #include "gl/renderer/gl_renderstate.h" #include "gl/shaders/gl_shader.h" @@ -36,62 +35,6 @@ #include "p_local.h" #include "r_sky.h" -// externally settable lighting properties -static float distfogtable[2][256]; // light to fog conversion table for black fog - -CVAR(Int, gl_weaponlight, 8, CVAR_ARCHIVE); -CUSTOM_CVAR(Bool, gl_enhanced_nightvision, true, CVAR_ARCHIVE|CVAR_NOINITCALL) -{ - // The fixed colormap state needs to be reset because if this happens when - // a shader is set to CM_LITE or CM_TORCH it won't register the change in behavior caused by this CVAR. - if (GLRenderer != nullptr && GLRenderer->mShaderManager != nullptr) - { - GLRenderer->mShaderManager->ResetFixedColormap(); - } -} - - - -//========================================================================== -// -// Sets up the fog tables -// -//========================================================================== - -CUSTOM_CVAR (Int, gl_distfog, 70, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) -{ - for (int i=0;i<256;i++) - { - - if (i<164) - { - distfogtable[0][i]= (gl_distfog>>1) + (gl_distfog)*(164-i)/164; - } - else if (i<230) - { - distfogtable[0][i]= (gl_distfog>>1) - (gl_distfog>>1)*(i-164)/(230-164); - } - else distfogtable[0][i]=0; - - if (i<128) - { - distfogtable[1][i]= 6.f + (gl_distfog>>1) + (gl_distfog)*(128-i)/48; - } - else if (i<216) - { - distfogtable[1][i]= (216.f-i) / ((216.f-128.f)) * gl_distfog / 10; - } - else distfogtable[1][i]=0; - } -} - -CUSTOM_CVAR(Int,gl_fogmode,1,CVAR_ARCHIVE|CVAR_NOINITCALL) -{ - if (self>2) self=2; - if (self<0) self=0; -} - - @@ -146,79 +89,6 @@ void gl_GetRenderStyle(FRenderStyle style, bool drawopaque, bool allowcolorblend } -//========================================================================== -// -// Get current light level -// -//========================================================================== - -int gl_CalcLightLevel(int lightlevel, int rellight, bool weapon) -{ - int light; - - if (lightlevel == 0) return 0; - - if ((level.lightmode & 2) && lightlevel < 192 && !weapon) - { - if (lightlevel > 100) - { - light = xs_CRoundToInt(192.f - (192 - lightlevel)* 1.87f); - if (light + rellight < 20) - { - light = 20 + (light + rellight - 20) / 5; - } - else - { - light += rellight; - } - } - else - { - light = (lightlevel + rellight) / 5; - } - - } - else - { - light=lightlevel+rellight; - } - - return clamp(light, 0, 255); -} - -//========================================================================== -// -// Get current light color -// -//========================================================================== - -static PalEntry gl_CalcLightColor(int light, PalEntry pe, int blendfactor) -{ - int r,g,b; - - if (level.lightmode == 8) - { - return pe; - } - else if (blendfactor == 0) - { - r = pe.r * light / 255; - g = pe.g * light / 255; - b = pe.b * light / 255; - } - else - { - // This is what Legacy does with colored light in 3D volumes. No, it doesn't really make sense... - // It also doesn't translate well to software style lighting. - int mixlight = light * (255 - blendfactor); - - r = (mixlight + pe.r * blendfactor) / 255; - g = (mixlight + pe.g * blendfactor) / 255; - b = (mixlight + pe.b * blendfactor) / 255; - } - return PalEntry(255, uint8_t(r), uint8_t(g), uint8_t(b)); -} - //========================================================================== // // set current light color @@ -233,144 +103,13 @@ void gl_SetColor(int sectorlightlevel, int rellight, bool fullbright, const FCol } else { - int hwlightlevel = gl_CalcLightLevel(sectorlightlevel, rellight, weapon); - PalEntry pe = gl_CalcLightColor(hwlightlevel, cm.LightColor, cm.BlendFactor); + int hwlightlevel = hw_CalcLightLevel(sectorlightlevel, rellight, weapon); + PalEntry pe = hw_CalcLightColor(hwlightlevel, cm.LightColor, cm.BlendFactor); gl_RenderState.SetColorAlpha(pe, alpha, cm.Desaturation); - gl_RenderState.SetSoftLightLevel(gl_ClampLight(sectorlightlevel + rellight)); + gl_RenderState.SetSoftLightLevel(hw_ClampLight(sectorlightlevel + rellight)); } } -//========================================================================== -// -// calculates the current fog density -// -// Rules for fog: -// -// 1. If bit 4 of gl_lightmode is set always use the level's fog density. -// This is what Legacy's GL render does. -// 2. black fog means no fog and always uses the distfogtable based on the level's fog density setting -// 3. If outside fog is defined and the current fog color is the same as the outside fog -// the engine always uses the outside fog density to make the fog uniform across the level. -// If the outside fog's density is undefined it uses the level's fog density and if that is -// not defined it uses a default of 70. -// 4. If a global fog density is specified it is being used for all fog on the level -// 5. If none of the above apply fog density is based on the light level as for the software renderer. -// -//========================================================================== - -float gl_GetFogDensity(int lightlevel, PalEntry fogcolor, int sectorfogdensity) -{ - float density; - - if (level.lightmode & 4) - { - // uses approximations of Legacy's default settings. - density = level.fogdensity ? level.fogdensity : 18; - } - else if (sectorfogdensity != 0) - { - // case 1: Sector has an explicit fog density set. - density = sectorfogdensity; - } - else if ((fogcolor.d & 0xffffff) == 0) - { - // case 2: black fog - if (level.lightmode != 8 && !(level.flags3 & LEVEL3_NOLIGHTFADE)) - { - density = distfogtable[level.lightmode != 0][gl_ClampLight(lightlevel)]; - } - else - { - density = 0; - } - } - else if (level.outsidefogdensity != 0 && APART(level.info->outsidefog) != 0xff && (fogcolor.d & 0xffffff) == (level.info->outsidefog & 0xffffff)) - { - // case 3. outsidefogdensity has already been set as needed - density = level.outsidefogdensity; - } - else if (level.fogdensity != 0) - { - // case 4: level has fog density set - density = level.fogdensity; - } - else if (lightlevel < 248) - { - // case 5: use light level - density = clamp(255 - lightlevel, 30, 255); - } - else - { - density = 0.f; - } - return density; -} - - -//========================================================================== -// -// Check if the current linedef is a candidate for a fog boundary -// -// Requirements for a fog boundary: -// - front sector has no fog -// - back sector has fog -// - at least one of both does not have a sky ceiling. -// -//========================================================================== - -bool gl_CheckFog(sector_t *frontsector, sector_t *backsector) -{ - if (frontsector == backsector) return false; // there can't be a boundary if both sides are in the same sector. - - // Check for fog boundaries. This needs a few more checks for the sectors - - PalEntry fogcolor = frontsector->Colormap.FadeColor; - - if ((fogcolor.d & 0xffffff) == 0) - { - return false; - } - else if (fogcolor.a != 0) - { - } - else if (level.outsidefogdensity != 0 && APART(level.info->outsidefog) != 0xff && (fogcolor.d & 0xffffff) == (level.info->outsidefog & 0xffffff)) - { - } - else if (level.fogdensity!=0 || (level.lightmode & 4)) - { - // case 3: level has fog density set - } - else - { - // case 4: use light level - if (frontsector->lightlevel >= 248) return false; - } - - fogcolor = backsector->Colormap.FadeColor; - - if ((fogcolor.d & 0xffffff) == 0) - { - } - else if (level.outsidefogdensity != 0 && APART(level.info->outsidefog) != 0xff && (fogcolor.d & 0xffffff) == (level.info->outsidefog & 0xffffff)) - { - return false; - } - else if (level.fogdensity!=0 || (level.lightmode & 4)) - { - // case 3: level has fog density set - return false; - } - else - { - // case 4: use light level - if (backsector->lightlevel < 248) return false; - } - - // in all other cases this might create more problems than it solves. - return ((frontsector->GetTexture(sector_t::ceiling)!=skyflatnum || - backsector->GetTexture(sector_t::ceiling)!=skyflatnum)); -} - //========================================================================== // // Lighting stuff @@ -424,7 +163,7 @@ void gl_SetFog(int lightlevel, int rellight, bool fullbright, const FColormap *c else if (cmap != NULL && !fullbright) { fogcolor = cmap->FadeColor; - fogdensity = gl_GetFogDensity(lightlevel, fogcolor, cmap->FogDensity); + fogdensity = hw_GetFogDensity(lightlevel, fogcolor, cmap->FogDensity); fogcolor.a=0; } else @@ -447,7 +186,7 @@ void gl_SetFog(int lightlevel, int rellight, bool fullbright, const FColormap *c { if (level.lightmode == 2 && fogcolor == 0) { - float light = gl_CalcLightLevel(lightlevel, rellight, false); + float light = hw_CalcLightLevel(lightlevel, rellight, false); gl_SetShaderLight(light, lightlevel); } else diff --git a/src/gl/renderer/gl_lightdata.h b/src/gl/renderer/gl_lightdata.h index d5b55481e..db7a87e19 100644 --- a/src/gl/renderer/gl_lightdata.h +++ b/src/gl/renderer/gl_lightdata.h @@ -4,23 +4,13 @@ #include "v_palette.h" #include "p_3dfloors.h" #include "r_data/renderstyle.h" -#include "gl/renderer/gl_colormap.h" - -inline int gl_ClampLight(int lightlevel) -{ - return clamp(lightlevel, 0, 255); -} +#include "hwrenderer/utility/hw_lighting.h" +#include "r_data/colormaps.h" void gl_GetRenderStyle(FRenderStyle style, bool drawopaque, bool allowcolorblending, int *tm, int *sb, int *db, int *be); -int gl_CalcLightLevel(int lightlevel, int rellight, bool weapon); void gl_SetColor(int light, int rellight, bool fullbright, const FColormap &cm, float alpha, bool weapon=false); - -float gl_GetFogDensity(int lightlevel, PalEntry fogcolor, int sectorfogdensity); -struct sector_t; -bool gl_CheckFog(sector_t *frontsector, sector_t *backsector); - void gl_SetFog(int lightlevel, int rellight, bool fullbright, const FColormap *cm, bool isadditive); diff --git a/src/gl/renderer/gl_renderstate.cpp b/src/gl/renderer/gl_renderstate.cpp index 45bb02033..995c9f2c2 100644 --- a/src/gl/renderer/gl_renderstate.cpp +++ b/src/gl/renderer/gl_renderstate.cpp @@ -27,13 +27,13 @@ #include "templates.h" #include "doomstat.h" +#include "r_data/colormaps.h" #include "gl/system/gl_system.h" #include "gl/system/gl_interface.h" #include "gl/data/gl_vertexbuffer.h" #include "hwrenderer/utility/hw_cvars.h" #include "gl/shaders/gl_shader.h" #include "gl/renderer/gl_renderer.h" -#include "gl/renderer/gl_colormap.h" #include "gl/dynlights//gl_lightbuffer.h" #include "gl/renderer/gl_renderbuffers.h" diff --git a/src/gl/scene/gl_bsp.cpp b/src/gl/scene/gl_bsp.cpp index 06185bdae..c250f607c 100644 --- a/src/gl/scene/gl_bsp.cpp +++ b/src/gl/scene/gl_bsp.cpp @@ -166,7 +166,7 @@ void GLSceneDrawer::AddLine (seg_t *seg, bool portalclip) { SetupWall.Clock(); - GLWall wall(this); + GLWall wall; wall.sub = currentsubsector; wall.Process(gl_drawinfo, seg, currentsector, backsector); rendered_lines++; diff --git a/src/gl/scene/gl_decal.cpp b/src/gl/scene/gl_decal.cpp index 57f8cfd56..0dd0b91f3 100644 --- a/src/gl/scene/gl_decal.cpp +++ b/src/gl/scene/gl_decal.cpp @@ -339,7 +339,7 @@ void FDrawInfo::DrawDecal(GLWall *wall, DBaseDecal *decal) if (low1 < dv[1].z || low2 < dv[2].z) { - int thisll = lightlist[k].caster != NULL ? gl_ClampLight(*lightlist[k].p_lightlevel) : wall->lightlevel; + int thisll = lightlist[k].caster != NULL ? hw_ClampLight(*lightlist[k].p_lightlevel) : wall->lightlevel; FColormap thiscm; thiscm.FadeColor = wall->Colormap.FadeColor; thiscm.CopyFrom3DLight(&lightlist[k]); diff --git a/src/gl/scene/gl_drawinfo.cpp b/src/gl/scene/gl_drawinfo.cpp index 4daed793a..91c364544 100644 --- a/src/gl/scene/gl_drawinfo.cpp +++ b/src/gl/scene/gl_drawinfo.cpp @@ -717,7 +717,7 @@ void GLDrawList::DoDraw(int pass, int i, bool trans) { GLWall * w= walls[drawitems[i].index]; RenderWall.Clock(); - w->Draw(pass); + gl_drawinfo->DrawWall(w, pass); RenderWall.Unclock(); } break; @@ -845,9 +845,9 @@ void GLDrawList::Draw(int pass, bool trans) void GLDrawList::DrawWalls(int pass) { RenderWall.Clock(); - for(unsigned i=0;iDraw(pass); + gl_drawinfo->DrawWall(walls[item.index], pass); } RenderWall.Unclock(); } @@ -1305,7 +1305,7 @@ void FDrawInfo::ProcessLowerMinisegs(TArray &lowersegs) for(unsigned int j=0;jSubsector->render_sector, seg->PartnerSeg->Subsector->render_sector); rendered_lines++; } diff --git a/src/gl/scene/gl_drawinfo.h b/src/gl/scene/gl_drawinfo.h index e08441374..ebedb94a2 100644 --- a/src/gl/scene/gl_drawinfo.h +++ b/src/gl/scene/gl_drawinfo.h @@ -179,6 +179,8 @@ struct FDrawInfo : public HWDrawInfo void AddWall(GLWall *wall) override; void AddMirrorSurface(GLWall *w) override; + void AddPortal(GLWall *w, int portaltype) override; + void ProcessActorsInPortal(FLinePortalSpan *glport) override; std::pair AllocVertices(unsigned int count) override; @@ -197,6 +199,15 @@ struct FDrawInfo : public HWDrawInfo void DrawFloodedPlane(wallseg * ws, float planez, sector_t * sec, bool ceiling); void FloodUpperGap(seg_t * seg) override; void FloodLowerGap(seg_t * seg) override; + + // Wall drawer + void RenderWall(GLWall *wall, int textured); + void RenderFogBoundary(GLWall *wall); + void RenderMirrorSurface(GLWall *wall); + void RenderTranslucentWall(GLWall *wall); + void RenderTexturedWall(GLWall *wall, int rflags); + void DrawWall(GLWall *wall, int pass); + // These two may be moved to the API independent part of the renderer later. void ProcessLowerMinisegs(TArray &lowersegs) override; diff --git a/src/gl/scene/gl_flats.cpp b/src/gl/scene/gl_flats.cpp index 91138057e..b4c73ae16 100644 --- a/src/gl/scene/gl_flats.cpp +++ b/src/gl/scene/gl_flats.cpp @@ -34,6 +34,7 @@ #include "d_player.h" #include "g_levellocals.h" #include "actorinlines.h" +#include "p_lnspec.h" #include "hwrenderer/dynlights/hw_dynlightdata.h" #include "gl/system/gl_interface.h" @@ -543,7 +544,7 @@ void GLFlat::SetFrom3DFloor(F3DFloor *rover, bool top, bool underside) // FF_FOG requires an inverted logic where to get the light from lightlist_t *light = P_GetPlaneLight(sector, plane.plane, underside); - lightlevel = gl_ClampLight(*light->p_lightlevel); + lightlevel = hw_ClampLight(*light->p_lightlevel); if (rover->flags & FF_FOG) { @@ -609,7 +610,7 @@ void GLFlat::ProcessSector(sector_t * frontsector) srf |= SSRF_RENDERFLOOR; - lightlevel = gl_ClampLight(frontsector->GetFloorLight()); + lightlevel = hw_ClampLight(frontsector->GetFloorLight()); Colormap = frontsector->Colormap; FlatColor = frontsector->SpecialColors[sector_t::floor]; port = frontsector->ValidatePortal(sector_t::floor); @@ -646,7 +647,7 @@ void GLFlat::ProcessSector(sector_t * frontsector) if ((!(sector->GetFlags(sector_t::floor)&PLANEF_ABSLIGHTING) || light->lightsource == NULL) && (light->p_lightlevel != &frontsector->lightlevel)) { - lightlevel = gl_ClampLight(*light->p_lightlevel); + lightlevel = hw_ClampLight(*light->p_lightlevel); } Colormap.CopyFrom3DLight(light); @@ -669,7 +670,7 @@ void GLFlat::ProcessSector(sector_t * frontsector) srf |= SSRF_RENDERCEILING; - lightlevel = gl_ClampLight(frontsector->GetCeilingLight()); + lightlevel = hw_ClampLight(frontsector->GetCeilingLight()); Colormap = frontsector->Colormap; FlatColor = frontsector->SpecialColors[sector_t::ceiling]; port = frontsector->ValidatePortal(sector_t::ceiling); @@ -707,7 +708,7 @@ void GLFlat::ProcessSector(sector_t * frontsector) if ((!(sector->GetFlags(sector_t::ceiling)&PLANEF_ABSLIGHTING)) && (light->p_lightlevel != &frontsector->lightlevel)) { - lightlevel = gl_ClampLight(*light->p_lightlevel); + lightlevel = hw_ClampLight(*light->p_lightlevel); } Colormap.CopyFrom3DLight(light); } @@ -801,7 +802,7 @@ void GLFlat::ProcessSector(sector_t * frontsector) if (rover->flags&FF_FIX) { - lightlevel = gl_ClampLight(rover->model->lightlevel); + lightlevel = hw_ClampLight(rover->model->lightlevel); Colormap = rover->GetColormap(); } diff --git a/src/gl/scene/gl_portal.cpp b/src/gl/scene/gl_portal.cpp index d023d365a..47a619b77 100644 --- a/src/gl/scene/gl_portal.cpp +++ b/src/gl/scene/gl_portal.cpp @@ -1240,7 +1240,7 @@ void GLEEHorizonPortal::DrawContents() { GLHorizonInfo horz; horz.plane.GetFromSector(sector, sector_t::ceiling); - horz.lightlevel = gl_ClampLight(sector->GetCeilingLight()); + horz.lightlevel = hw_ClampLight(sector->GetCeilingLight()); horz.colormap = sector->Colormap; horz.specialcolor = 0xffffffff; if (portal->mType == PORTS_PLANE) @@ -1254,7 +1254,7 @@ void GLEEHorizonPortal::DrawContents() { GLHorizonInfo horz; horz.plane.GetFromSector(sector, sector_t::floor); - horz.lightlevel = gl_ClampLight(sector->GetFloorLight()); + horz.lightlevel = hw_ClampLight(sector->GetFloorLight()); horz.colormap = sector->Colormap; horz.specialcolor = 0xffffffff; if (portal->mType == PORTS_PLANE) diff --git a/src/gl/scene/gl_portal.h b/src/gl/scene/gl_portal.h index e001d3270..7401316ad 100644 --- a/src/gl/scene/gl_portal.h +++ b/src/gl/scene/gl_portal.h @@ -40,36 +40,8 @@ #include "actor.h" #include "gl/renderer/gl_renderer.h" #include "gl/scene/gl_drawinfo.h" - -struct GLHorizonInfo -{ - GLSectorPlane plane; - int lightlevel; - FColormap colormap; - PalEntry specialcolor; -}; - -struct GLSkyInfo -{ - float x_offset[2]; - float y_offset; // doubleskies don't have a y-offset - FMaterial * texture[2]; - FTextureID skytexno1; - bool mirrored; - bool doublesky; - bool sky2; - PalEntry fadecolor; // if this isn't made part of the dome things will become more complicated when sky fog is used. - - bool operator==(const GLSkyInfo & inf) - { - return !memcmp(this, &inf, sizeof(*this)); - } - bool operator!=(const GLSkyInfo & inf) - { - return !!memcmp(this, &inf, sizeof(*this)); - } - void init(int sky1, PalEntry fadecolor); -}; +#include "hwrenderer/scene/hw_drawstructs.h" +#include "hwrenderer/scene/hw_portal.h" extern UniqueList UniqueSkies; extern UniqueList UniqueHorizons; diff --git a/src/gl/scene/gl_scenedrawer.h b/src/gl/scene/gl_scenedrawer.h index 8a0f48e8b..0d1759ff7 100644 --- a/src/gl/scene/gl_scenedrawer.h +++ b/src/gl/scene/gl_scenedrawer.h @@ -100,7 +100,7 @@ public: bool CheckFog(sector_t *frontsector, sector_t *backsector) { if (FixedColormap != CM_DEFAULT) return false; - return gl_CheckFog(frontsector, backsector); + return hw_CheckFog(frontsector, backsector); } void SetFog(int lightlevel, int rellight, const FColormap *cmap, bool isadditive) diff --git a/src/gl/scene/gl_sky.cpp b/src/gl/scene/gl_sky.cpp index 36702b6f7..be9e5a13d 100644 --- a/src/gl/scene/gl_sky.cpp +++ b/src/gl/scene/gl_sky.cpp @@ -26,12 +26,16 @@ #include "r_utility.h" #include "doomdata.h" #include "g_levellocals.h" - -#include "gl/renderer/gl_lightdata.h" -#include "gl/scene/gl_drawinfo.h" -#include "gl/scene/gl_portal.h" +#include "p_lnspec.h" +#include "hwrenderer/scene/hw_drawinfo.h" +#include "hwrenderer/scene/hw_drawstructs.h" +#include "hwrenderer/scene/hw_portal.h" +#include "hwrenderer/utility/hw_lighting.h" #include "hwrenderer/textures/hw_material.h" +#include "gl/renderer/gl_renderer.h" +#include "gl/scene/gl_portal.h" + CVAR(Bool,gl_noskyboxes, false, 0) //========================================================================== diff --git a/src/gl/scene/gl_sprite.cpp b/src/gl/scene/gl_sprite.cpp index 13c138d45..9308ed8d4 100644 --- a/src/gl/scene/gl_sprite.cpp +++ b/src/gl/scene/gl_sprite.cpp @@ -310,7 +310,7 @@ void GLSprite::Draw(int pass) if (!Colormap.FadeColor.isBlack()) { float dist=Dist2(r_viewpoint.Pos.X, r_viewpoint.Pos.Y, x,y); - int fogd = gl_GetFogDensity(lightlevel, Colormap.FadeColor, Colormap.FogDensity); + int fogd = hw_GetFogDensity(lightlevel, Colormap.FadeColor, Colormap.FogDensity); // this value was determined by trial and error and is scale dependent! float factor = 0.05f + exp(-fogd*dist / 62500.f); @@ -414,7 +414,7 @@ void GLSprite::Draw(int pass) secplane_t *topplane = i == 0 ? &topp : &(*lightlist)[i].plane; secplane_t *lowplane = i == (*lightlist).Size() - 1 ? &bottomp : &(*lightlist)[i + 1].plane; - int thislight = (*lightlist)[i].caster != NULL ? gl_ClampLight(*(*lightlist)[i].p_lightlevel) : lightlevel; + int thislight = (*lightlist)[i].caster != NULL ? hw_ClampLight(*(*lightlist)[i].p_lightlevel) : lightlevel; int thisll = actor == nullptr? thislight : (uint8_t)actor->Sector->CheckSpriteGlow(thislight, actor->InterpolatedPosition(r_viewpoint.TicFrac)); FColormap thiscm; @@ -545,7 +545,7 @@ void GLSprite::SplitSprite(sector_t * frontsector, bool translucent) if (lightbottomrenderflags & RF_FULLBRIGHT) && (!gltexture || !gltexture->tex->bDisableFullbright)); lightlevel = fullbright ? 255 : - gl_ClampLight(rendersector->GetTexture(sector_t::ceiling) == skyflatnum ? + hw_ClampLight(rendersector->GetTexture(sector_t::ceiling) == skyflatnum ? rendersector->GetCeilingLight() : rendersector->GetFloorLight()); foglevel = (uint8_t)clamp(rendersector->lightlevel, 0, 255); @@ -1146,7 +1146,7 @@ void GLSprite::ProcessParticle (particle_t *particle, sector_t *sector)//, int s if (particle->alpha==0) return; - lightlevel = gl_ClampLight(sector->GetTexture(sector_t::ceiling) == skyflatnum ? + lightlevel = hw_ClampLight(sector->GetTexture(sector_t::ceiling) == skyflatnum ? sector->GetCeilingLight() : sector->GetFloorLight()); foglevel = (uint8_t)clamp(sector->lightlevel, 0, 255); @@ -1167,7 +1167,7 @@ void GLSprite::ProcessParticle (particle_t *particle, sector_t *sector)//, int s if (lightbottom < particle->Pos.Z) { - lightlevel = gl_ClampLight(*lightlist[i].p_lightlevel); + lightlevel = hw_ClampLight(*lightlist[i].p_lightlevel); Colormap.CopyLight(lightlist[i].extra_colormap); break; } diff --git a/src/gl/scene/gl_vertex.cpp b/src/gl/scene/gl_vertex.cpp index ca476982b..576a2fb03 100644 --- a/src/gl/scene/gl_vertex.cpp +++ b/src/gl/scene/gl_vertex.cpp @@ -24,7 +24,7 @@ #include "r_defs.h" #include "hwrenderer/data/flatvertices.h" #include "hwrenderer/scene/hw_drawinfo.h" -#include "gl/scene/gl_wall.h" +#include "hwrenderer/scene/hw_drawstructs.h" EXTERN_CVAR(Bool, gl_seamless) diff --git a/src/gl/scene/gl_wall.h b/src/gl/scene/gl_wall.h index f11d9588c..38ff975ab 100644 --- a/src/gl/scene/gl_wall.h +++ b/src/gl/scene/gl_wall.h @@ -8,7 +8,8 @@ #include "r_defs.h" #include "r_data/renderstyle.h" #include "textures/textures.h" -#include "gl/renderer/gl_colormap.h" +#include "r_data/colormaps.h" +#include "hwrenderer/scene/hw_drawstructs.h" #pragma warning(disable:4244) @@ -28,286 +29,9 @@ struct FLinePortalSpan; class GLSceneDrawer; struct FDynLightData; -enum -{ - GLSector_NoSkyDraw = 89, - GLSector_Skybox = 90, -}; - -enum WallTypes -{ - RENDERWALL_NONE, - RENDERWALL_TOP, - RENDERWALL_M1S, - RENDERWALL_M2S, - RENDERWALL_BOTTOM, - RENDERWALL_FOGBOUNDARY, - RENDERWALL_MIRRORSURFACE, - RENDERWALL_M2SNF, - RENDERWALL_COLOR, - RENDERWALL_FFBLOCK, - // Insert new types at the end! -}; - -enum PortalTypes -{ - PORTALTYPE_SKY, - PORTALTYPE_HORIZON, - PORTALTYPE_SKYBOX, - PORTALTYPE_SECTORSTACK, - PORTALTYPE_PLANEMIRROR, - PORTALTYPE_MIRROR, - PORTALTYPE_LINETOLINE, -}; - -struct GLSeg -{ - float x1,x2; - float y1,y2; - float fracleft, fracright; // fractional offset of the 2 vertices on the linedef - - FVector3 Normal() const - { - // we do not use the vector math inlines here because they are not optimized for speed but accuracy in the playsim and this is called quite frequently. - float x = y2 - y1; - float y = x1 - x2; - float ilength = 1.f / sqrtf(x*x + y*y); - return FVector3(x * ilength, 0, y * ilength); - } -}; - -struct texcoord -{ - float u,v; -}; - -//========================================================================== -// -// One sector plane, still in fixed point -// -//========================================================================== - -struct GLSectorPlane -{ - FTextureID texture; - secplane_t plane; - float Texheight; - float Angle; - FVector2 Offs; - FVector2 Scale; - - void GetFromSector(sector_t * sec, int ceiling) - { - Offs.X = (float)sec->GetXOffset(ceiling); - Offs.Y = (float)sec->GetYOffset(ceiling); - Scale.X = (float)sec->GetXScale(ceiling); - Scale.Y = (float)sec->GetYScale(ceiling); - Angle = (float)sec->GetAngle(ceiling).Degrees; - texture = sec->GetTexture(ceiling); - plane = sec->GetSecPlane(ceiling); - Texheight = (float)((ceiling == sector_t::ceiling)? plane.fD() : -plane.fD()); - } -}; - struct FDrawInfo; struct HWDrawInfo; -class GLWall -{ - friend struct FDrawInfo; -public: - static const char passflag[]; - - enum - { - GLWF_CLAMPX=1, - GLWF_CLAMPY=2, - GLWF_SKYHACK=4, - GLWF_GLOW=8, // illuminated by glowing flats - GLWF_NOSPLITUPPER=16, - GLWF_NOSPLITLOWER=32, - GLWF_NOSPLIT=64, - GLWF_TRANSLUCENT = 128 - }; - - enum - { - RWF_BLANK = 0, - RWF_TEXTURED = 1, // actually not being used anymore because with buffers it's even less efficient not writing the texture coordinates - but leave it here - RWF_NOSPLIT = 4, - RWF_NORENDER = 8, - }; - - enum - { - LOLFT, - UPLFT, - UPRGT, - LORGT, - }; - - friend struct GLDrawList; - friend class GLPortal; - - GLSceneDrawer *mDrawer; - vertex_t * vertexes[2]; // required for polygon splitting - FMaterial *gltexture; - TArray *lightlist; - - GLSeg glseg; - float ztop[2],zbottom[2]; - texcoord tcs[4]; - float alpha; - - FColormap Colormap; - ERenderStyle RenderStyle; - - float ViewDistance; - - int lightlevel; - uint8_t type; - uint8_t flags; - short rellight; - - float topglowcolor[4]; - float bottomglowcolor[4]; - - int dynlightindex; - - union - { - // it's either one of them but never more! - FSectorPortal *secportal; // sector portal (formerly skybox) - GLSkyInfo * sky; // for normal sky - GLHorizonInfo * horizon; // for horizon information - FSectorPortalGroup * portal; // stacked sector portals - secplane_t * planemirror; // for plane mirrors - FLinePortalSpan *lineportal; // line-to-line portals - }; - - - secplane_t topplane, bottomplane; // we need to save these to pass them to the shader for calculating glows. - - // these are not the same as ytop and ybottom!!! - float zceil[2]; - float zfloor[2]; - - unsigned int vertindex; - unsigned int vertcount; - -public: - seg_t * seg; // this gives the easiest access to all other structs involved - subsector_t * sub; // For polyobjects -private: - - void CheckGlowing(); - bool PutWallCompat(int passflag); - void PutWall(HWDrawInfo *di, bool translucent); - void PutPortal(HWDrawInfo *di, int ptype); - void CheckTexturePosition(FTexCoordInfo *tci); - - void Put3DWall(HWDrawInfo *di, lightlist_t * lightlist, bool translucent); - bool SplitWallComplex(HWDrawInfo *di, sector_t * frontsector, bool translucent, float& maplightbottomleft, float& maplightbottomright); - void SplitWall(HWDrawInfo *di, sector_t * frontsector, bool translucent); - - bool SetupLights(FDynLightData &lightdata); - void RenderWall(int textured); - void RenderTextured(int rflags); - - void FloodPlane(int pass); - - void MakeVertices(HWDrawInfo *di, bool nosplit); - - void SkyPlane(HWDrawInfo *di, sector_t *sector, int plane, bool allowmirror); - void SkyLine(HWDrawInfo *di, sector_t *sec, line_t *line); - void SkyNormal(HWDrawInfo *di, sector_t * fs,vertex_t * v1,vertex_t * v2); - void SkyTop(HWDrawInfo *di, seg_t * seg,sector_t * fs,sector_t * bs,vertex_t * v1,vertex_t * v2); - void SkyBottom(HWDrawInfo *di, seg_t * seg,sector_t * fs,sector_t * bs,vertex_t * v1,vertex_t * v2); - - void LightPass(); - bool DoHorizon(HWDrawInfo *di, seg_t * seg,sector_t * fs, vertex_t * v1,vertex_t * v2); - - bool SetWallCoordinates(seg_t * seg, FTexCoordInfo *tci, float ceilingrefheight, - float topleft, float topright, float bottomleft, float bottomright, float t_ofs); - - void DoTexture(HWDrawInfo *di, int type,seg_t * seg,int peg, - float ceilingrefheight, float floorrefheight, - float CeilingHeightstart,float CeilingHeightend, - float FloorHeightstart,float FloorHeightend, - float v_offset); - - void DoMidTexture(HWDrawInfo *di, seg_t * seg, bool drawfogboundary, - sector_t * front, sector_t * back, - sector_t * realfront, sector_t * realback, - float fch1, float fch2, float ffh1, float ffh2, - float bch1, float bch2, float bfh1, float bfh2); - - void GetPlanePos(F3DFloor::planeref * planeref, float & left, float & right); - - void BuildFFBlock(HWDrawInfo *di, seg_t * seg, F3DFloor * rover, - float ff_topleft, float ff_topright, - float ff_bottomleft, float ff_bottomright); - void InverseFloors(HWDrawInfo *di, seg_t * seg, sector_t * frontsector, - float topleft, float topright, - float bottomleft, float bottomright); - void ClipFFloors(HWDrawInfo *di, seg_t * seg, F3DFloor * ffloor, sector_t * frontsector, - float topleft, float topright, - float bottomleft, float bottomright); - void DoFFloorBlocks(HWDrawInfo *di, seg_t * seg, sector_t * frontsector, sector_t * backsector, - float fch1, float fch2, float ffh1, float ffh2, - float bch1, float bch2, float bfh1, float bfh2); - - void RenderFogBoundary(); - void RenderMirrorSurface(); - void RenderTranslucentWall(); - - void CreateVertices(FFlatVertex *&ptr, bool nosplit); - void SplitLeftEdge (FFlatVertex *&ptr); - void SplitRightEdge(FFlatVertex *&ptr); - void SplitUpperEdge(FFlatVertex *&ptr); - void SplitLowerEdge(FFlatVertex *&ptr); - - int CountVertices(); - -public: - - GLWall(GLSceneDrawer *drawer) - { - mDrawer = drawer; - } - - GLWall(const GLWall &other) - { - memcpy(this, &other, sizeof(GLWall)); - } - - GLWall & operator=(const GLWall &other) - { - memcpy(this, &other, sizeof(GLWall)); - return *this; - } - - void Process(HWDrawInfo *di, seg_t *seg, sector_t *frontsector, sector_t *backsector); - void ProcessLowerMiniseg(HWDrawInfo *di, seg_t *seg, sector_t *frontsector, sector_t *backsector); - void Draw(int pass); - - float PointOnSide(float x,float y) - { - return -((y-glseg.y1)*(glseg.x2-glseg.x1)-(x-glseg.x1)*(glseg.y2-glseg.y1)); - } - - // Lines start-end and fdiv must intersect. - double CalcIntersectionVertex(GLWall * w2) - { - float ax = glseg.x1, ay=glseg.y1; - float bx = glseg.x2, by=glseg.y2; - float cx = w2->glseg.x1, cy=w2->glseg.y1; - float dx = w2->glseg.x2, dy=w2->glseg.y2; - return ((ay-cy)*(dx-cx)-(ax-cx)*(dy-cy)) / ((bx-ax)*(dy-cy)-(by-ay)*(dx-cx)); - } - -}; - //========================================================================== // // One flat plane in the draw list @@ -455,11 +179,6 @@ public: }; -inline float Dist2(float x1,float y1,float x2,float y2) -{ - return sqrtf((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2)); -} - // Light + color void gl_SetDynSpriteLight(AActor *self, float x, float y, float z, subsector_t *subsec); diff --git a/src/gl/scene/gl_walls.cpp b/src/gl/scene/gl_walls.cpp index b1dbc8271..1df0a0efc 100644 --- a/src/gl/scene/gl_walls.cpp +++ b/src/gl/scene/gl_walls.cpp @@ -31,61 +31,14 @@ #include "g_levellocals.h" #include "hwrenderer/dynlights/hw_dynlightdata.h" #include "hwrenderer/textures/hw_material.h" - -#include "gl/renderer/gl_lightdata.h" #include "hwrenderer/utility/hw_cvars.h" -#include "gl/system/gl_interface.h" - -#include "gl/scene/gl_drawinfo.h" -#include "gl/scene/gl_portal.h" - #include "hwrenderer/utility/hw_clock.h" +#include "hwrenderer/utility/hw_lighting.h" +#include "hwrenderer/scene/hw_drawinfo.h" +#include "hwrenderer/scene/hw_drawstructs.h" +#include "hwrenderer/scene/hw_portal.h" -void FDrawInfo::AddWall(GLWall *wall) -{ - bool translucent = !!(wall->flags & GLWall::GLWF_TRANSLUCENT); - int list; - - if (translucent) // translucent walls - { - wall->ViewDistance = (r_viewpoint.Pos - (wall->seg->linedef->v1->fPos() + wall->seg->linedef->Delta() / 2)).XY().LengthSquared(); - wall->MakeVertices(this, true); - auto newwall = drawlists[GLDL_TRANSLUCENT].NewWall(); - *newwall = *wall; - } - else - { - if (gl.legacyMode) - { - if (PutWallCompat(wall, GLWall::passflag[wall->type])) return; - } - - bool masked; - - masked = GLWall::passflag[wall->type] == 1 ? false : (wall->gltexture && wall->gltexture->isMasked()); - - if ((wall->flags & GLWall::GLWF_SKYHACK && wall->type == RENDERWALL_M2S)) - { - list = GLDL_MASKEDWALLSOFS; - } - else - { - list = masked ? GLDL_MASKEDWALLS : GLDL_PLAINWALLS; - } - wall->MakeVertices(this, false); - auto newwall = drawlists[list].NewWall(); - *newwall = *wall; - } -} - -void FDrawInfo::AddMirrorSurface(GLWall *w) -{ - w->type=RENDERWALL_MIRRORSURFACE; - auto newwall = drawlists[GLDL_TRANSLUCENTBORDER].NewWall(); - *newwall = *w; - -} const char GLWall::passflag[] = { @@ -131,80 +84,9 @@ void GLWall::PutWall(HWDrawInfo *di, bool translucent) void GLWall::PutPortal(HWDrawInfo *di, int ptype) { - GLPortal * portal; - - MakeVertices(di, false); - switch (ptype) - { - // portals don't go into the draw list. - // Instead they are added to the portal manager - case PORTALTYPE_HORIZON: - horizon=UniqueHorizons.Get(horizon); - portal=GLPortal::FindPortal(horizon); - if (!portal) portal=new GLHorizonPortal(horizon); - portal->AddLine(this); - break; - - case PORTALTYPE_SKYBOX: - portal = GLPortal::FindPortal(secportal); - if (!portal) - { - // either a regular skybox or an Eternity-style horizon - if (secportal->mType != PORTS_SKYVIEWPOINT) portal = new GLEEHorizonPortal(secportal); - else portal = new GLSkyboxPortal(secportal); - } - portal->AddLine(this); - break; - - case PORTALTYPE_SECTORSTACK: - portal = this->portal->GetRenderState(); - portal->AddLine(this); - break; - - case PORTALTYPE_PLANEMIRROR: - if (GLPortal::PlaneMirrorMode * planemirror->fC() <=0) - { - //@sync-portal - planemirror=UniquePlaneMirrors.Get(planemirror); - portal=GLPortal::FindPortal(planemirror); - if (!portal) portal=new GLPlaneMirrorPortal(planemirror); - portal->AddLine(this); - } - break; - - case PORTALTYPE_MIRROR: - portal=GLPortal::FindPortal(seg->linedef); - if (!portal) portal=new GLMirrorPortal(seg->linedef); - portal->AddLine(this); - if (gl_mirror_envmap) - { - // draw a reflective layer over the mirror - di->AddMirrorSurface(this); - } - break; - - case PORTALTYPE_LINETOLINE: - portal=GLPortal::FindPortal(lineportal); - if (!portal) - { - line_t *otherside = lineportal->lines[0]->mDestination; - if (otherside != NULL && otherside->portalindex < level.linePortals.Size()) - { - di->ProcessActorsInPortal(otherside->getPortal()->mGroup); - } - portal = new GLLineToLinePortal(lineportal); - } - portal->AddLine(this); - break; - - case PORTALTYPE_SKY: - portal=GLPortal::FindPortal(sky); - if (!portal) portal=new GLSkyPortal(sky); - portal->AddLine(this); - break; - } - vertcount = 0; + di->AddPortal(this, ptype); } + //========================================================================== // // Sets 3D-floor lighting info @@ -216,7 +98,7 @@ void GLWall::Put3DWall(HWDrawInfo *di, lightlist_t * lightlist, bool translucent // only modify the light level if it doesn't originate from the seg's frontsector. This is to account for light transferring effects if (lightlist->p_lightlevel != &seg->sidedef->sector->lightlevel) { - lightlevel = gl_ClampLight(*lightlist->p_lightlevel); + lightlevel = hw_ClampLight(*lightlist->p_lightlevel); } // relative light won't get changed here. It is constant across the entire wall. @@ -367,7 +249,7 @@ void GLWall::SplitWall(HWDrawInfo *di, sector_t * frontsector, bool translucent) (maplightbottomleftzbottom[1]) || (maplightbottomleft > zbottom[0] && maplightbottomright < zbottom[1])) { - if (!(gl.flags & RFL_NO_CLIP_PLANES)) + if (!(screen->hwcaps & RFL_NO_CLIP_PLANES)) { // Use hardware clipping if this cannot be done cleanly. this->lightlist = &lightlist; @@ -449,7 +331,7 @@ bool GLWall::DoHorizon(HWDrawInfo *di, seg_t * seg,sector_t * fs, vertex_t * v1, else { hi.plane.GetFromSector(fs, sector_t::ceiling); - hi.lightlevel = gl_ClampLight(fs->GetCeilingLight()); + hi.lightlevel = hw_ClampLight(fs->GetCeilingLight()); hi.colormap = fs->Colormap; hi.specialcolor = fs->SpecialColors[sector_t::ceiling]; @@ -457,7 +339,7 @@ bool GLWall::DoHorizon(HWDrawInfo *di, seg_t * seg,sector_t * fs, vertex_t * v1, { light = P_GetPlaneLight(fs, &fs->ceilingplane, true); - if(!(fs->GetFlags(sector_t::ceiling)&PLANEF_ABSLIGHTING)) hi.lightlevel = gl_ClampLight(*light->p_lightlevel); + if(!(fs->GetFlags(sector_t::ceiling)&PLANEF_ABSLIGHTING)) hi.lightlevel = hw_ClampLight(*light->p_lightlevel); hi.colormap.CopyLight(light->extra_colormap); } @@ -478,7 +360,7 @@ bool GLWall::DoHorizon(HWDrawInfo *di, seg_t * seg,sector_t * fs, vertex_t * v1, else { hi.plane.GetFromSector(fs, sector_t::floor); - hi.lightlevel = gl_ClampLight(fs->GetFloorLight()); + hi.lightlevel = hw_ClampLight(fs->GetFloorLight()); hi.colormap = fs->Colormap; hi.specialcolor = fs->SpecialColors[sector_t::floor]; @@ -486,7 +368,7 @@ bool GLWall::DoHorizon(HWDrawInfo *di, seg_t * seg,sector_t * fs, vertex_t * v1, { light = P_GetPlaneLight(fs, &fs->floorplane, false); - if(!(fs->GetFlags(sector_t::floor)&PLANEF_ABSLIGHTING)) hi.lightlevel = gl_ClampLight(*light->p_lightlevel); + if(!(fs->GetFlags(sector_t::floor)&PLANEF_ABSLIGHTING)) hi.lightlevel = hw_ClampLight(*light->p_lightlevel); hi.colormap.CopyLight(light->extra_colormap); } @@ -1124,7 +1006,7 @@ void GLWall::BuildFFBlock(HWDrawInfo *di, seg_t * seg, F3DFloor * rover, Colormap.Clear(); Colormap.LightColor = light->extra_colormap.FadeColor; // the fog plane defines the light level, not the front sector - lightlevel = gl_ClampLight(*light->p_lightlevel); + lightlevel = hw_ClampLight(*light->p_lightlevel); gltexture = NULL; type = RENDERWALL_FFBLOCK; } @@ -1531,9 +1413,9 @@ void GLWall::Process(HWDrawInfo *di, seg_t *seg, sector_t * frontsector, sector_ lightlist = NULL; int rel = 0; - int orglightlevel = gl_ClampLight(frontsector->lightlevel); + int orglightlevel = hw_ClampLight(frontsector->lightlevel); bool foggy = (!Colormap.FadeColor.isBlack() || level.flags&LEVEL_HASFADETABLE); // fog disables fake contrast - lightlevel = gl_ClampLight(seg->sidedef->GetLightLevel(foggy, orglightlevel, false, &rel)); + lightlevel = hw_ClampLight(seg->sidedef->GetLightLevel(foggy, orglightlevel, false, &rel)); if (orglightlevel >= 253) // with the software renderer fake contrast won't be visible above this. { rellight = 0; @@ -1664,7 +1546,7 @@ void GLWall::Process(HWDrawInfo *di, seg_t *seg, sector_t * frontsector, sector_ bool isportal = seg->linedef->isVisualPortal() && seg->sidedef == seg->linedef->sidedef[0]; sector_t *backsec = isportal? seg->linedef->getPortalDestination()->frontsector : backsector; - bool drawfogboundary = di->FixedColormap == CM_DEFAULT && gl_CheckFog(frontsector, backsec); + bool drawfogboundary = di->FixedColormap == CM_DEFAULT && hw_CheckFog(frontsector, backsec); FTexture *tex = TexMan(seg->sidedef->GetTexture(side_t::mid)); if (tex != NULL) { @@ -1781,7 +1663,7 @@ void GLWall::ProcessLowerMiniseg(HWDrawInfo *di, seg_t *seg, sector_t * frontsec flags = 0; // can't do fake contrast without a sidedef - lightlevel = gl_ClampLight(frontsector->lightlevel); + lightlevel = hw_ClampLight(frontsector->lightlevel); rellight = 0; alpha = 1.0f; diff --git a/src/gl/scene/gl_walls_draw.cpp b/src/gl/scene/gl_walls_draw.cpp index 5517df36f..33d050805 100644 --- a/src/gl/scene/gl_walls_draw.cpp +++ b/src/gl/scene/gl_walls_draw.cpp @@ -151,13 +151,13 @@ bool GLWall::SetupLights(FDynLightData &lightdata) // //========================================================================== -void GLWall::RenderWall(int textured) +void FDrawInfo::RenderWall(GLWall *wall, int textured) { assert(vertcount > 0); gl_RenderState.Apply(); - gl_RenderState.ApplyLightIndex(dynlightindex); - GLRenderer->mVBO->RenderArray(GL_TRIANGLE_FAN, vertindex, vertcount); - vertexcount += vertcount; + gl_RenderState.ApplyLightIndex(wall->dynlightindex); + GLRenderer->mVBO->RenderArray(GL_TRIANGLE_FAN, wall->vertindex, wall->vertcount); + vertexcount += wall->vertcount; } //========================================================================== @@ -166,20 +166,20 @@ void GLWall::RenderWall(int textured) // //========================================================================== -void GLWall::RenderFogBoundary() +void FDrawInfo::RenderFogBoundary(GLWall *wall) { if (gl_fogmode && mDrawer->FixedColormap == 0) { if (!gl.legacyMode) { - int rel = rellight + getExtraLight(); - mDrawer->SetFog(lightlevel, rel, &Colormap, false); + int rel = wall->rellight + getExtraLight(); + mDrawer->SetFog(wall->lightlevel, rel, &wall->Colormap, false); gl_RenderState.EnableDrawBuffers(1); gl_RenderState.SetEffect(EFF_FOGBOUNDARY); gl_RenderState.AlphaFunc(GL_GEQUAL, 0.f); glEnable(GL_POLYGON_OFFSET_FILL); glPolygonOffset(-1.0f, -128.0f); - RenderWall(RWF_BLANK); + RenderWall(wall, GLWall::RWF_BLANK); glPolygonOffset(0.0f, 0.0f); glDisable(GL_POLYGON_OFFSET_FILL); gl_RenderState.SetEffect(EFF_NONE); @@ -187,7 +187,7 @@ void GLWall::RenderFogBoundary() } else { - gl_drawinfo->RenderFogBoundaryCompat(this); + RenderFogBoundaryCompat(wall); } } } @@ -198,32 +198,27 @@ void GLWall::RenderFogBoundary() // // //========================================================================== -void GLWall::RenderMirrorSurface() +void FDrawInfo::RenderMirrorSurface(GLWall *wall) { if (!GLRenderer->mirrorTexture.isValid()) return; - // For the sphere map effect we need a normal of the mirror surface, - FVector3 v = glseg.Normal(); - if (!gl.legacyMode) { // we use texture coordinates and texture matrix to pass the normal stuff to the shader so that the default vertex buffer format can be used as is. - tcs[LOLFT].u = tcs[LORGT].u = tcs[UPLFT].u = tcs[UPRGT].u = v.X; - tcs[LOLFT].v = tcs[LORGT].v = tcs[UPLFT].v = tcs[UPRGT].v = v.Z; - gl_RenderState.EnableTextureMatrix(true); gl_RenderState.mTextureMatrix.computeNormalMatrix(gl_RenderState.mViewMatrix); } else { + FVector3 v = wall->glseg.Normal(); glNormal3fv(&v[0]); } // Use sphere mapping for this gl_RenderState.SetEffect(EFF_SPHEREMAP); - mDrawer->SetColor(lightlevel, 0, Colormap ,0.1f); - mDrawer->SetFog(lightlevel, 0, &Colormap, true); + mDrawer->SetColor(wall->lightlevel, 0, wall->Colormap ,0.1f); + mDrawer->SetFog(wall->lightlevel, 0, &wall->Colormap, true); gl_RenderState.BlendFunc(GL_SRC_ALPHA,GL_ONE); gl_RenderState.AlphaFunc(GL_GREATER,0); glDepthFunc(GL_LEQUAL); @@ -231,8 +226,8 @@ void GLWall::RenderMirrorSurface() FMaterial * pat=FMaterial::ValidateTexture(GLRenderer->mirrorTexture, false, false); gl_RenderState.SetMaterial(pat, CLAMP_NONE, 0, -1, false); - flags &= ~GLWF_GLOW; - RenderWall(RWF_BLANK); + wall->flags &= ~GLWall::GLWF_GLOW; + RenderWall(wall, GLWall::RWF_BLANK); gl_RenderState.EnableTextureMatrix(false); gl_RenderState.SetEffect(EFF_NONE); @@ -244,12 +239,12 @@ void GLWall::RenderMirrorSurface() // This is drawn in the translucent pass which is done after the decal pass // As a result the decals have to be drawn here. - if (seg->sidedef->AttachedDecals) + if (wall->seg->sidedef->AttachedDecals) { glEnable(GL_POLYGON_OFFSET_FILL); glPolygonOffset(-1.0f, -128.0f); glDepthMask(false); - gl_drawinfo->DoDrawDecals(this); + gl_drawinfo->DoDrawDecals(wall); glDepthMask(true); glPolygonOffset(0.0f, 0.0f); glDisable(GL_POLYGON_OFFSET_FILL); @@ -264,61 +259,61 @@ void GLWall::RenderMirrorSurface() // //========================================================================== -void GLWall::RenderTextured(int rflags) +void FDrawInfo::RenderTexturedWall(GLWall *wall, int rflags) { int tmode = gl_RenderState.GetTextureMode(); - int rel = rellight + getExtraLight(); + int rel = wall->rellight + getExtraLight(); - if (flags & GLWF_GLOW) + if (wall->flags & GLWall::GLWF_GLOW) { gl_RenderState.EnableGlow(true); - gl_RenderState.SetGlowParams(topglowcolor, bottomglowcolor); + gl_RenderState.SetGlowParams(wall->topglowcolor, wall->bottomglowcolor); } - gl_RenderState.SetGlowPlanes(topplane, bottomplane); - gl_RenderState.SetMaterial(gltexture, flags & 3, 0, -1, false); + gl_RenderState.SetGlowPlanes(wall->topplane, wall->bottomplane); + gl_RenderState.SetMaterial(wall->gltexture, wall->flags & 3, 0, -1, false); - if (type == RENDERWALL_M2SNF) + if (wall->type == RENDERWALL_M2SNF) { - if (flags & GLWF_CLAMPY) + if (wall->flags & GLWall::GLWF_CLAMPY) { if (tmode == TM_MODULATE) gl_RenderState.SetTextureMode(TM_CLAMPY); } - mDrawer->SetFog(255, 0, NULL, false); + mDrawer->SetFog(255, 0, nullptr, false); } - gl_RenderState.SetObjectColor(seg->frontsector->SpecialColors[sector_t::walltop] | 0xff000000); - gl_RenderState.SetObjectColor2(seg->frontsector->SpecialColors[sector_t::wallbottom] | 0xff000000); + gl_RenderState.SetObjectColor(wall->seg->frontsector->SpecialColors[sector_t::walltop] | 0xff000000); + gl_RenderState.SetObjectColor2(wall->seg->frontsector->SpecialColors[sector_t::wallbottom] | 0xff000000); - float absalpha = fabsf(alpha); - if (lightlist == NULL) + float absalpha = fabsf(wall->alpha); + if (wall->lightlist == nullptr) { - if (type != RENDERWALL_M2SNF) mDrawer->SetFog(lightlevel, rel, &Colormap, RenderStyle == STYLE_Add); - mDrawer->SetColor(lightlevel, rel, Colormap, absalpha); - RenderWall(rflags); + if (wall->type != RENDERWALL_M2SNF) mDrawer->SetFog(wall->lightlevel, rel, &wall->Colormap, wall->RenderStyle == STYLE_Add); + mDrawer->SetColor(wall->lightlevel, rel, wall->Colormap, absalpha); + RenderWall(wall, rflags); } else { gl_RenderState.EnableSplit(true); - for (unsigned i = 0; i < lightlist->Size(); i++) + for (unsigned i = 0; i < wall->lightlist->Size(); i++) { - secplane_t &lowplane = i == (*lightlist).Size() - 1 ? bottomplane : (*lightlist)[i + 1].plane; + secplane_t &lowplane = i == (*wall->lightlist).Size() - 1 ? wall->bottomplane : (*wall->lightlist)[i + 1].plane; // this must use the exact same calculation method as GLWall::Process etc. - float low1 = lowplane.ZatPoint(vertexes[0]); - float low2 = lowplane.ZatPoint(vertexes[1]); + float low1 = lowplane.ZatPoint(wall->vertexes[0]); + float low2 = lowplane.ZatPoint(wall->vertexes[1]); - if (low1 < ztop[0] || low2 < ztop[1]) + if (low1 < wall->ztop[0] || low2 < wall->ztop[1]) { - int thisll = (*lightlist)[i].caster != NULL ? gl_ClampLight(*(*lightlist)[i].p_lightlevel) : lightlevel; + int thisll = (*wall->lightlist)[i].caster != NULL ? hw_ClampLight(*(*wall->lightlist)[i].p_lightlevel) : wall->lightlevel; FColormap thiscm; - thiscm.FadeColor = Colormap.FadeColor; - thiscm.FogDensity = Colormap.FogDensity; - thiscm.CopyFrom3DLight(&(*lightlist)[i]); + thiscm.FadeColor = wall->Colormap.FadeColor; + thiscm.FogDensity = wall->Colormap.FogDensity; + thiscm.CopyFrom3DLight(&(*wall->lightlist)[i]); mDrawer->SetColor(thisll, rel, thiscm, absalpha); - if (type != RENDERWALL_M2SNF) mDrawer->SetFog(thisll, rel, &thiscm, RenderStyle == STYLE_Add); - gl_RenderState.SetSplitPlanes((*lightlist)[i].plane, lowplane); - RenderWall(rflags); + if (wall->type != RENDERWALL_M2SNF) mDrawer->SetFog(thisll, rel, &thiscm, wall->RenderStyle == STYLE_Add); + gl_RenderState.SetSplitPlanes((*wall->lightlist)[i].plane, lowplane); + RenderWall(wall, rflags); } - if (low1 <= zbottom[0] && low2 <= zbottom[1]) break; + if (low1 <= wall->zbottom[0] && low2 <= wall->zbottom[1]) break; } gl_RenderState.EnableSplit(false); @@ -335,28 +330,28 @@ void GLWall::RenderTextured(int rflags) // //========================================================================== -void GLWall::RenderTranslucentWall() +void FDrawInfo::RenderTranslucentWall(GLWall *wall) { - if (gltexture) + if (wall->gltexture) { if (mDrawer->FixedColormap == CM_DEFAULT && gl_lights && gl.lightmethod == LM_DIRECT) { - if (SetupLights(lightdata)) - dynlightindex = GLRenderer->mLights->UploadLights(lightdata); + if (wall->SetupLights(lightdata)) + wall->dynlightindex = GLRenderer->mLights->UploadLights(lightdata); } - if (!gltexture->tex->GetTranslucency()) gl_RenderState.AlphaFunc(GL_GEQUAL, gl_mask_threshold); + if (!wall->gltexture->tex->GetTranslucency()) gl_RenderState.AlphaFunc(GL_GEQUAL, gl_mask_threshold); else gl_RenderState.AlphaFunc(GL_GEQUAL, 0.f); - if (RenderStyle == STYLE_Add) gl_RenderState.BlendFunc(GL_SRC_ALPHA,GL_ONE); - RenderTextured(RWF_TEXTURED | RWF_NOSPLIT); - if (RenderStyle == STYLE_Add) gl_RenderState.BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + if (wall->RenderStyle == STYLE_Add) gl_RenderState.BlendFunc(GL_SRC_ALPHA,GL_ONE); + RenderTexturedWall(wall, GLWall::RWF_TEXTURED | GLWall::RWF_NOSPLIT); + if (wall->RenderStyle == STYLE_Add) gl_RenderState.BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); } else { gl_RenderState.AlphaFunc(GL_GEQUAL, 0.f); - mDrawer->SetColor(lightlevel, 0, Colormap, fabsf(alpha)); - mDrawer->SetFog(lightlevel, 0, &Colormap, RenderStyle == STYLE_Add); + mDrawer->SetColor(wall->lightlevel, 0, wall->Colormap, fabsf(wall->alpha)); + mDrawer->SetFog(wall->lightlevel, 0, &wall->Colormap, wall->RenderStyle == STYLE_Add); gl_RenderState.EnableTexture(false); - RenderWall(RWF_NOSPLIT); + RenderWall(wall, GLWall::RWF_NOSPLIT); gl_RenderState.EnableTexture(true); } } @@ -366,38 +361,38 @@ void GLWall::RenderTranslucentWall() // // //========================================================================== -void GLWall::Draw(int pass) +void FDrawInfo::DrawWall(GLWall *wall, int pass) { - gl_RenderState.SetNormal(glseg.Normal()); + gl_RenderState.SetNormal(wall->glseg.Normal()); switch (pass) { case GLPASS_LIGHTSONLY: - if (SetupLights(lightdata)) - dynlightindex = GLRenderer->mLights->UploadLights(lightdata); + if (wall->SetupLights(lightdata)) + wall->dynlightindex = GLRenderer->mLights->UploadLights(lightdata); break; case GLPASS_ALL: - if (SetupLights(lightdata)) - dynlightindex = GLRenderer->mLights->UploadLights(lightdata); + if (wall->SetupLights(lightdata)) + wall->dynlightindex = GLRenderer->mLights->UploadLights(lightdata); // fall through case GLPASS_PLAIN: - RenderTextured(RWF_TEXTURED); + RenderTexturedWall(wall, GLWall::RWF_TEXTURED); break; case GLPASS_TRANSLUCENT: - switch (type) + switch (wall->type) { case RENDERWALL_MIRRORSURFACE: - RenderMirrorSurface(); + RenderMirrorSurface(wall); break; case RENDERWALL_FOGBOUNDARY: - RenderFogBoundary(); + RenderFogBoundary(wall); break; default: - RenderTranslucentWall(); + RenderTranslucentWall(wall); break; } break; @@ -405,12 +400,169 @@ void GLWall::Draw(int pass) case GLPASS_LIGHTTEX: case GLPASS_LIGHTTEX_ADDITIVE: case GLPASS_LIGHTTEX_FOGGY: - gl_drawinfo->RenderLightsCompat(this, pass); + gl_drawinfo->RenderLightsCompat(wall, pass); break; case GLPASS_TEXONLY: - gl_RenderState.SetMaterial(gltexture, flags & 3, 0, -1, false); - RenderWall(RWF_TEXTURED); + gl_RenderState.SetMaterial(wall->gltexture, wall->flags & 3, 0, -1, false); + RenderWall(wall, GLWall::RWF_TEXTURED); break; } } + +//========================================================================== +// +// +// +//========================================================================== + +void FDrawInfo::AddWall(GLWall *wall) +{ + bool translucent = !!(wall->flags & GLWall::GLWF_TRANSLUCENT); + int list; + + if (translucent) // translucent walls + { + if (!gl.legacyMode && mDrawer->FixedColormap == CM_DEFAULT && wall->gltexture != nullptr) + { + if (wall->SetupLights(lightdata)) + wall->dynlightindex = GLRenderer->mLights->UploadLights(lightdata); + } + wall->ViewDistance = (r_viewpoint.Pos - (wall->seg->linedef->v1->fPos() + wall->seg->linedef->Delta() / 2)).XY().LengthSquared(); + wall->MakeVertices(this, true); + auto newwall = drawlists[GLDL_TRANSLUCENT].NewWall(); + *newwall = *wall; + } + else + { + if (gl.legacyMode) + { + if (PutWallCompat(wall, GLWall::passflag[wall->type])) return; + } + else if (mDrawer->FixedColormap == CM_DEFAULT) + { + if (wall->SetupLights(lightdata)) + wall->dynlightindex = GLRenderer->mLights->UploadLights(lightdata); + } + + + bool masked; + + masked = GLWall::passflag[wall->type] == 1 ? false : (wall->gltexture && wall->gltexture->isMasked()); + + if ((wall->flags & GLWall::GLWF_SKYHACK && wall->type == RENDERWALL_M2S)) + { + list = GLDL_MASKEDWALLSOFS; + } + else + { + list = masked ? GLDL_MASKEDWALLS : GLDL_PLAINWALLS; + } + wall->MakeVertices(this, false); + auto newwall = drawlists[list].NewWall(); + *newwall = *wall; + } + wall->dynlightindex = -1; +} + +//========================================================================== +// +// +// +//========================================================================== + +void FDrawInfo::AddMirrorSurface(GLWall *w) +{ + w->type = RENDERWALL_MIRRORSURFACE; + auto newwall = drawlists[GLDL_TRANSLUCENTBORDER].NewWall(); + *newwall = *w; + + FVector3 v = newwall->glseg.Normal(); + auto tcs = newwall->tcs; + tcs[GLWall::LOLFT].u = tcs[GLWall::LORGT].u = tcs[GLWall::UPLFT].u = tcs[GLWall::UPRGT].u = v.X; + tcs[GLWall::LOLFT].v = tcs[GLWall::LORGT].v = tcs[GLWall::UPLFT].v = tcs[GLWall::UPRGT].v = v.Z; + newwall->MakeVertices(this, false); +} + +//========================================================================== +// +// +// +//========================================================================== + +void FDrawInfo::AddPortal(GLWall *wall, int ptype) +{ + GLPortal * portal; + + wall->MakeVertices(this, false); + switch (ptype) + { + // portals don't go into the draw list. + // Instead they are added to the portal manager + case PORTALTYPE_HORIZON: + wall->horizon = UniqueHorizons.Get(wall->horizon); + portal = GLPortal::FindPortal(wall->horizon); + if (!portal) portal = new GLHorizonPortal(wall->horizon); + portal->AddLine(wall); + break; + + case PORTALTYPE_SKYBOX: + portal = GLPortal::FindPortal(wall->secportal); + if (!portal) + { + // either a regular skybox or an Eternity-style horizon + if (wall->secportal->mType != PORTS_SKYVIEWPOINT) portal = new GLEEHorizonPortal(wall->secportal); + else portal = new GLSkyboxPortal(wall->secportal); + } + portal->AddLine(wall); + break; + + case PORTALTYPE_SECTORSTACK: + portal = wall->portal->GetRenderState(); + portal->AddLine(wall); + break; + + case PORTALTYPE_PLANEMIRROR: + if (GLPortal::PlaneMirrorMode * wall->planemirror->fC() <= 0) + { + //@sync-portal + wall->planemirror = UniquePlaneMirrors.Get(wall->planemirror); + portal = GLPortal::FindPortal(wall->planemirror); + if (!portal) portal = new GLPlaneMirrorPortal(wall->planemirror); + portal->AddLine(wall); + } + break; + + case PORTALTYPE_MIRROR: + portal = GLPortal::FindPortal(wall->seg->linedef); + if (!portal) portal = new GLMirrorPortal(wall->seg->linedef); + portal->AddLine(wall); + if (gl_mirror_envmap) + { + // draw a reflective layer over the mirror + AddMirrorSurface(wall); + } + break; + + case PORTALTYPE_LINETOLINE: + portal = GLPortal::FindPortal(wall->lineportal); + if (!portal) + { + line_t *otherside = wall->lineportal->lines[0]->mDestination; + if (otherside != NULL && otherside->portalindex < level.linePortals.Size()) + { + ProcessActorsInPortal(otherside->getPortal()->mGroup); + } + portal = new GLLineToLinePortal(wall->lineportal); + } + portal->AddLine(wall); + break; + + case PORTALTYPE_SKY: + portal = GLPortal::FindPortal(wall->sky); + if (!portal) portal = new GLSkyPortal(wall->sky); + portal->AddLine(wall); + break; + } + wall->vertcount = 0; +} diff --git a/src/gl/scene/gl_weapon.cpp b/src/gl/scene/gl_weapon.cpp index 67e7abd30..f781aa8c7 100644 --- a/src/gl/scene/gl_weapon.cpp +++ b/src/gl/scene/gl_weapon.cpp @@ -275,7 +275,7 @@ void GLSceneDrawer::DrawPlayerSprites(sector_t * viewsector, bool hudModelStep) fakesec = hw_FakeFlat(viewsector, &fs, in_area, false); // calculate light level for weapon sprites - lightlevel = gl_ClampLight(fakesec->lightlevel); + lightlevel = hw_ClampLight(fakesec->lightlevel); // calculate colormap for weapon sprites if (viewsector->e->XFloor.ffloors.Size() && !(level.flags3 & LEVEL3_NOCOLOREDSPRITELIGHTING)) @@ -297,7 +297,7 @@ void GLSceneDrawer::DrawPlayerSprites(sector_t * viewsector, bool hudModelStep) if (lightbottomviewz) { cm = lightlist[i].extra_colormap; - lightlevel = gl_ClampLight(*lightlist[i].p_lightlevel); + lightlevel = hw_ClampLight(*lightlist[i].p_lightlevel); break; } } @@ -308,7 +308,7 @@ void GLSceneDrawer::DrawPlayerSprites(sector_t * viewsector, bool hudModelStep) if (level.flags3 & LEVEL3_NOCOLOREDSPRITELIGHTING) cm.ClearColor(); } - lightlevel = gl_CalcLightLevel(lightlevel, getExtraLight(), true); + lightlevel = hw_CalcLightLevel(lightlevel, getExtraLight(), true); if (level.lightmode == 8 || lightlevel < 92) { diff --git a/src/gl/system/gl_debug.h b/src/gl/system/gl_debug.h index 4b03d0835..4f67eec68 100644 --- a/src/gl/system/gl_debug.h +++ b/src/gl/system/gl_debug.h @@ -5,6 +5,7 @@ #include "gl/system/gl_interface.h" #include "c_cvars.h" #include "r_defs.h" +#include "v_video.h" class FGLDebug { diff --git a/src/gl/system/gl_framebuffer.cpp b/src/gl/system/gl_framebuffer.cpp index 64ac23b4d..a66f10291 100644 --- a/src/gl/system/gl_framebuffer.cpp +++ b/src/gl/system/gl_framebuffer.cpp @@ -86,6 +86,8 @@ OpenGLFrameBuffer::OpenGLFrameBuffer(void *hMonitor, int width, int height, int mDebug = std::make_shared(); mDebug->Update(); DoSetGamma(); + hwcaps = gl.flags; + if (gl.legacyMode) hwcaps |= RFL_NO_SHADERS; } OpenGLFrameBuffer::~OpenGLFrameBuffer() @@ -413,6 +415,13 @@ void OpenGLFrameBuffer::TextureFilterChanged() if (GLRenderer != NULL && GLRenderer->mSamplerManager != NULL) GLRenderer->mSamplerManager->SetTextureFilterMode(); } +void OpenGLFrameBuffer::ResetFixedColormap() +{ + if (GLRenderer != nullptr && GLRenderer->mShaderManager != nullptr) + { + GLRenderer->mShaderManager->ResetFixedColormap(); + } +} void OpenGLFrameBuffer::UpdatePalette() diff --git a/src/gl/system/gl_framebuffer.h b/src/gl/system/gl_framebuffer.h index 6c04fbdcf..6410a3443 100644 --- a/src/gl/system/gl_framebuffer.h +++ b/src/gl/system/gl_framebuffer.h @@ -48,6 +48,7 @@ public: void UnbindTexUnit(int no) override; void FlushTextures() override; void TextureFilterChanged() override; + void ResetFixedColormap() override; // Retrieves a buffer containing image data for a screenshot. // Hint: Pitch can be negative for upside-down images, in which case buffer diff --git a/src/gl/system/gl_interface.cpp b/src/gl/system/gl_interface.cpp index 10e4b1f6f..5f9cf2441 100644 --- a/src/gl/system/gl_interface.cpp +++ b/src/gl/system/gl_interface.cpp @@ -31,6 +31,7 @@ #include "doomtype.h" #include "m_argv.h" #include "version.h" +#include "v_video.h" #include "gl/system/gl_interface.h" #include "hwrenderer/utility/hw_cvars.h" diff --git a/src/gl/system/gl_interface.h b/src/gl/system/gl_interface.h index 258451701..1fa697cdf 100644 --- a/src/gl/system/gl_interface.h +++ b/src/gl/system/gl_interface.h @@ -11,22 +11,6 @@ enum GLCompat CMPT_GL4 }; -enum RenderFlags -{ - // [BB] Added texture compression flags. - RFL_TEXTURE_COMPRESSION=1, - RFL_TEXTURE_COMPRESSION_S3TC=2, - - RFL_SHADER_STORAGE_BUFFER = 4, - RFL_BUFFER_STORAGE = 8, - RFL_SAMPLER_OBJECTS = 16, - - RFL_NO_CLIP_PLANES = 32, - - RFL_INVALIDATE_BUFFER = 64, - RFL_DEBUG = 128 -}; - enum TexMode { TM_SWCANVAS = -1, // special case for the legacy renderer, do not use for anything but the SW renderer's canvas. diff --git a/src/gl/textures/gl_hwtexture.cpp b/src/gl/textures/gl_hwtexture.cpp index 35c7bd27c..0a729813b 100644 --- a/src/gl/textures/gl_hwtexture.cpp +++ b/src/gl/textures/gl_hwtexture.cpp @@ -29,13 +29,13 @@ #include "gl/system/gl_system.h" #include "templates.h" #include "c_cvars.h" +#include "r_data/colormaps.h" #include "hwrenderer/textures/hw_material.h" #include "gl/system/gl_interface.h" #include "hwrenderer/utility/hw_cvars.h" #include "gl/system/gl_debug.h" #include "gl/renderer/gl_renderer.h" -#include "gl/renderer/gl_colormap.h" #include "gl/textures/gl_samplers.h" diff --git a/src/hwrenderer/scene/hw_drawinfo.h b/src/hwrenderer/scene/hw_drawinfo.h index 071bc5f31..13533cbfc 100644 --- a/src/hwrenderer/scene/hw_drawinfo.h +++ b/src/hwrenderer/scene/hw_drawinfo.h @@ -125,6 +125,7 @@ public: virtual void AddSubsectorToPortal(FSectorPortalGroup *portal, subsector_t *sub) = 0; virtual void AddWall(GLWall *w) = 0; + virtual void AddPortal(GLWall *w, int portaltype) = 0; virtual void AddMirrorSurface(GLWall *w) = 0; virtual void ProcessActorsInPortal(FLinePortalSpan *glport) = 0; virtual std::pair AllocVertices(unsigned int count) = 0; diff --git a/src/hwrenderer/utility/hw_lighting.cpp b/src/hwrenderer/utility/hw_lighting.cpp new file mode 100644 index 000000000..a261120de --- /dev/null +++ b/src/hwrenderer/utility/hw_lighting.cpp @@ -0,0 +1,288 @@ +// +//--------------------------------------------------------------------------- +// +// Copyright(C) 2002-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_light.cpp +** Light level / fog management / dynamic lights +** +**/ + +#include "c_cvars.h" +#include "r_sky.h" +#include "g_levellocals.h" +#include "hw_lighting.h" + +// externally settable lighting properties +static float distfogtable[2][256]; // light to fog conversion table for black fog + +CVAR(Int, gl_weaponlight, 8, CVAR_ARCHIVE); +CUSTOM_CVAR(Bool, gl_enhanced_nightvision, true, CVAR_ARCHIVE|CVAR_NOINITCALL) +{ + // The fixed colormap state needs to be reset because if this happens when + // a shader is set to CM_LITE or CM_TORCH it won't register the change in behavior caused by this CVAR. + screen->ResetFixedColormap(); +} + + + +//========================================================================== +// +// Sets up the fog tables +// +//========================================================================== + +CUSTOM_CVAR(Int, gl_distfog, 70, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) +{ + for (int i = 0; i < 256; i++) + { + + if (i < 164) + { + distfogtable[0][i] = (float)((gl_distfog >> 1) + (gl_distfog)*(164 - i) / 164); + } + else if (i < 230) + { + distfogtable[0][i] = (float)((gl_distfog >> 1) - (gl_distfog >> 1)*(i - 164) / (230 - 164)); + } + else distfogtable[0][i] = 0; + + if (i < 128) + { + distfogtable[1][i] = 6.f + (float)((gl_distfog >> 1) + (gl_distfog)*(128 - i) / 48); + } + else if (i < 216) + { + distfogtable[1][i] = (216.f - i) / ((216.f - 128.f)) * gl_distfog / 10; + } + else distfogtable[1][i] = 0; + } +} + +CUSTOM_CVAR(Int,gl_fogmode,1,CVAR_ARCHIVE|CVAR_NOINITCALL) +{ + if (self>2) self=2; + if (self<0) self=0; +} + + +//========================================================================== +// +// Get current light level +// +//========================================================================== + +int hw_CalcLightLevel(int lightlevel, int rellight, bool weapon) +{ + int light; + + if (lightlevel == 0) return 0; + + if ((level.lightmode & 2) && lightlevel < 192 && !weapon) + { + if (lightlevel > 100) + { + light = xs_CRoundToInt(192.f - (192 - lightlevel)* 1.87f); + if (light + rellight < 20) + { + light = 20 + (light + rellight - 20) / 5; + } + else + { + light += rellight; + } + } + else + { + light = (lightlevel + rellight) / 5; + } + + } + else + { + light=lightlevel+rellight; + } + + return clamp(light, 0, 255); +} + +//========================================================================== +// +// Get current light color +// +//========================================================================== + +PalEntry hw_CalcLightColor(int light, PalEntry pe, int blendfactor) +{ + int r,g,b; + + if (level.lightmode == 8) + { + return pe; + } + else if (blendfactor == 0) + { + r = pe.r * light / 255; + g = pe.g * light / 255; + b = pe.b * light / 255; + } + else + { + // This is what Legacy does with colored light in 3D volumes. No, it doesn't really make sense... + // It also doesn't translate well to software style lighting. + int mixlight = light * (255 - blendfactor); + + r = (mixlight + pe.r * blendfactor) / 255; + g = (mixlight + pe.g * blendfactor) / 255; + b = (mixlight + pe.b * blendfactor) / 255; + } + return PalEntry(255, uint8_t(r), uint8_t(g), uint8_t(b)); +} + +//========================================================================== +// +// calculates the current fog density +// +// Rules for fog: +// +// 1. If bit 4 of gl_lightmode is set always use the level's fog density. +// This is what Legacy's GL render does. +// 2. black fog means no fog and always uses the distfogtable based on the level's fog density setting +// 3. If outside fog is defined and the current fog color is the same as the outside fog +// the engine always uses the outside fog density to make the fog uniform across the level. +// If the outside fog's density is undefined it uses the level's fog density and if that is +// not defined it uses a default of 70. +// 4. If a global fog density is specified it is being used for all fog on the level +// 5. If none of the above apply fog density is based on the light level as for the software renderer. +// +//========================================================================== + +float hw_GetFogDensity(int lightlevel, PalEntry fogcolor, int sectorfogdensity) +{ + float density; + + if (level.lightmode & 4) + { + // uses approximations of Legacy's default settings. + density = level.fogdensity ? (float)level.fogdensity : 18; + } + else if (sectorfogdensity != 0) + { + // case 1: Sector has an explicit fog density set. + density = (float)sectorfogdensity; + } + else if ((fogcolor.d & 0xffffff) == 0) + { + // case 2: black fog + if (level.lightmode != 8 && !(level.flags3 & LEVEL3_NOLIGHTFADE)) + { + density = distfogtable[level.lightmode != 0][hw_ClampLight(lightlevel)]; + } + else + { + density = 0; + } + } + else if (level.outsidefogdensity != 0 && APART(level.info->outsidefog) != 0xff && (fogcolor.d & 0xffffff) == (level.info->outsidefog & 0xffffff)) + { + // case 3. outsidefogdensity has already been set as needed + density = (float)level.outsidefogdensity; + } + else if (level.fogdensity != 0) + { + // case 4: level has fog density set + density = (float)level.fogdensity; + } + else if (lightlevel < 248) + { + // case 5: use light level + density = (float)clamp(255 - lightlevel, 30, 255); + } + else + { + density = 0.f; + } + return density; +} + +//========================================================================== +// +// Check if the current linedef is a candidate for a fog boundary +// +// Requirements for a fog boundary: +// - front sector has no fog +// - back sector has fog +// - at least one of both does not have a sky ceiling. +// +//========================================================================== + +bool hw_CheckFog(sector_t *frontsector, sector_t *backsector) +{ + if (frontsector == backsector) return false; // there can't be a boundary if both sides are in the same sector. + + // Check for fog boundaries. This needs a few more checks for the sectors + + PalEntry fogcolor = frontsector->Colormap.FadeColor; + + if ((fogcolor.d & 0xffffff) == 0) + { + return false; + } + else if (fogcolor.a != 0) + { + } + else if (level.outsidefogdensity != 0 && APART(level.info->outsidefog) != 0xff && (fogcolor.d & 0xffffff) == (level.info->outsidefog & 0xffffff)) + { + } + else if (level.fogdensity!=0 || (level.lightmode & 4)) + { + // case 3: level has fog density set + } + else + { + // case 4: use light level + if (frontsector->lightlevel >= 248) return false; + } + + fogcolor = backsector->Colormap.FadeColor; + + if ((fogcolor.d & 0xffffff) == 0) + { + } + else if (level.outsidefogdensity != 0 && APART(level.info->outsidefog) != 0xff && (fogcolor.d & 0xffffff) == (level.info->outsidefog & 0xffffff)) + { + return false; + } + else if (level.fogdensity!=0 || (level.lightmode & 4)) + { + // case 3: level has fog density set + return false; + } + else + { + // case 4: use light level + if (backsector->lightlevel < 248) return false; + } + + // in all other cases this might create more problems than it solves. + return ((frontsector->GetTexture(sector_t::ceiling)!=skyflatnum || + backsector->GetTexture(sector_t::ceiling)!=skyflatnum)); +} + diff --git a/src/hwrenderer/utility/hw_lighting.h b/src/hwrenderer/utility/hw_lighting.h new file mode 100644 index 000000000..43bceaf98 --- /dev/null +++ b/src/hwrenderer/utility/hw_lighting.h @@ -0,0 +1,17 @@ +#pragma once + +#include "v_palette.h" +#include "templates.h" + +struct Colormap; + +int hw_CalcLightLevel(int lightlevel, int rellight, bool weapon); +PalEntry hw_CalcLightColor(int light, PalEntry pe, int blendfactor); +float hw_GetFogDensity(int lightlevel, PalEntry fogcolor, int sectorfogdensity); +bool hw_CheckFog(sector_t *frontsector, sector_t *backsector); + +inline int hw_ClampLight(int lightlevel) +{ + return clamp(lightlevel, 0, 255); +} + diff --git a/src/p_lnspec.h b/src/p_lnspec.h index afb42bf9f..034c5f2b6 100644 --- a/src/p_lnspec.h +++ b/src/p_lnspec.h @@ -108,6 +108,9 @@ typedef enum { hDamage_Sludge = 85, Sector_Outside = 87, + GLSector_NoSkyDraw = 89, + GLSector_Skybox = 90, + // And here are some for Strife sLight_Strobe_Hurt = 104, sDamage_Hellslime = 105, diff --git a/src/r_data/colormaps.h b/src/r_data/colormaps.h index c8ffef872..379e1cfff 100644 --- a/src/r_data/colormaps.h +++ b/src/r_data/colormaps.h @@ -125,4 +125,25 @@ int AddSpecialColormap(float r1, float g1, float b1, float r2, float g2, float b extern uint8_t DesaturateColormap[31][256]; + +enum EColorManipulation +{ + CM_SPECIAL2D = -3, // the special colormaps get passed as color pair from the 2D drawer so they need a different value here. + CM_PLAIN2D = -2, // regular 2D drawing. + CM_INVALID = -1, + CM_DEFAULT = 0, // untranslated + CM_FIRSTSPECIALCOLORMAP, // first special fixed colormap + CM_FIRSTSPECIALCOLORMAPFORCED = 0x08000000, // first special fixed colormap, application forced (for 2D overlays) + + CM_FOGLAYER = 0x10000000, // Sprite shaped fog layer + + // These are not to be passed to the texture manager + CM_LITE = 0x20000000, // special values to handle these items without excessive hacking + CM_TORCH = 0x20000010, // These are not real color manipulations +}; + +#define CM_MAXCOLORMAP int(CM_FIRSTSPECIALCOLORMAP + SpecialColormaps.Size()) +#define CM_MAXCOLORMAPFORCED int(CM_FIRSTSPECIALCOLORMAPFORCED + SpecialColormaps.Size()) + + #endif diff --git a/src/v_video.h b/src/v_video.h index 0c4ecce69..f2c8a711b 100644 --- a/src/v_video.h +++ b/src/v_video.h @@ -44,6 +44,25 @@ #include "v_colortables.h" #include "v_2ddrawer.h" +enum EHWCaps +{ + // [BB] Added texture compression flags. + RFL_TEXTURE_COMPRESSION = 1, + RFL_TEXTURE_COMPRESSION_S3TC = 2, + + RFL_SHADER_STORAGE_BUFFER = 4, + RFL_BUFFER_STORAGE = 8, + RFL_SAMPLER_OBJECTS = 16, + + RFL_NO_CLIP_PLANES = 32, + + RFL_INVALIDATE_BUFFER = 64, + RFL_DEBUG = 128, + RFL_NO_SHADERS = 256 +}; + + + extern int CleanWidth, CleanHeight, CleanXfac, CleanYfac; extern int CleanWidth_1, CleanHeight_1, CleanXfac_1, CleanYfac_1; extern int DisplayWidth, DisplayHeight, DisplayBits; @@ -306,6 +325,9 @@ protected: bool Bgra = 0; int clipleft = 0, cliptop = 0, clipwidth = -1, clipheight = -1; +public: + int hwcaps = 0; + public: DFrameBuffer (int width, int height, bool bgra); virtual ~DFrameBuffer() {} @@ -359,6 +381,7 @@ public: virtual void UnbindTexUnit(int no) {} virtual void FlushTextures() {} virtual void TextureFilterChanged() {} + virtual void ResetFixedColormap() {} // Begin 2D drawing operations. // Returns true if hardware-accelerated 2D has been entered, false if not.