- GLWall is mostly clean, except some smaller things in gl_sky.cpp

This commit is contained in:
Christoph Oelckers 2018-04-27 00:22:00 +02:00
parent 937a2cf69f
commit dd524b046e
32 changed files with 674 additions and 854 deletions

View file

@ -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

View file

@ -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;
}

View file

@ -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<int>(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

View file

@ -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);

View file

@ -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"

View file

@ -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++;

View file

@ -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]);

View file

@ -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;i<drawitems.Size();i++)
for(auto &item : drawitems)
{
walls[drawitems[i].index]->Draw(pass);
gl_drawinfo->DrawWall(walls[item.index], pass);
}
RenderWall.Unclock();
}
@ -1305,7 +1305,7 @@ void FDrawInfo::ProcessLowerMinisegs(TArray<seg_t *> &lowersegs)
for(unsigned int j=0;j<lowersegs.Size();j++)
{
seg_t * seg=lowersegs[j];
GLWall wall(mDrawer);
GLWall wall;
wall.ProcessLowerMiniseg(this, seg, seg->Subsector->render_sector, seg->PartnerSeg->Subsector->render_sector);
rendered_lines++;
}

View file

@ -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<FFlatVertex *, unsigned int> 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<seg_t *> &lowersegs) override;

View file

@ -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();
}

View file

@ -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)

View file

@ -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<GLSkyInfo> UniqueSkies;
extern UniqueList<GLHorizonInfo> UniqueHorizons;

View file

@ -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)

View file

@ -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)
//==========================================================================

View file

@ -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 (lightbottom<z1)
{
copySprite=*this;
copySprite.lightlevel = gl_ClampLight(*lightlist[i].p_lightlevel);
copySprite.lightlevel = hw_ClampLight(*lightlist[i].p_lightlevel);
copySprite.Colormap.CopyLight(lightlist[i].extra_colormap);
if (level.flags3 & LEVEL3_NOCOLOREDSPRITELIGHTING)
@ -936,7 +936,7 @@ void GLSprite::Process(AActor* thing, sector_t * sector, int thruportal)
((thing->renderflags & 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<short>(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<short>(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;
}

View file

@ -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)

View file

@ -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_t> *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);

View file

@ -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)
(maplightbottomleft<zbottom[0] && maplightbottomright>zbottom[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;

View file

@ -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;
}

View file

@ -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 (lightbottom<player->viewz)
{
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)
{

View file

@ -5,6 +5,7 @@
#include "gl/system/gl_interface.h"
#include "c_cvars.h"
#include "r_defs.h"
#include "v_video.h"
class FGLDebug
{

View file

@ -86,6 +86,8 @@ OpenGLFrameBuffer::OpenGLFrameBuffer(void *hMonitor, int width, int height, int
mDebug = std::make_shared<FGLDebug>();
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()

View file

@ -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

View file

@ -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"

View file

@ -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.

View file

@ -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"

View file

@ -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<FFlatVertex *, unsigned int> AllocVertices(unsigned int count) = 0;

View file

@ -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<int>(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));
}

View file

@ -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);
}

View file

@ -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,

View file

@ -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

View file

@ -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.