diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index c97bce415..e9c996a2a 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -831,6 +831,7 @@ set( FASTMATH_SOURCES hwrenderer/scene/hw_fakeflat.cpp hwrenderer/scene/hw_decal.cpp hwrenderer/scene/hw_clipper.cpp + hwrenderer/scene/hw_flats.cpp hwrenderer/scene/hw_renderhacks.cpp hwrenderer/scene/hw_sky.cpp hwrenderer/scene/hw_walls.cpp diff --git a/src/gl/scene/gl_drawinfo.h b/src/gl/scene/gl_drawinfo.h index 0983825e6..58ea61245 100644 --- a/src/gl/scene/gl_drawinfo.h +++ b/src/gl/scene/gl_drawinfo.h @@ -220,6 +220,7 @@ struct FDrawInfo : public HWDrawInfo void DrawSubsectors(GLFlat *flat, int pass, bool processlights, bool istrans); void ProcessLights(GLFlat *flat, bool istrans); void DrawSubsector(GLFlat *flat, subsector_t * sub); + void SetupSubsectorLights(GLFlat *flat, int pass, subsector_t * sub, int *dli); // These two may be moved to the API independent part of the renderer later. diff --git a/src/gl/scene/gl_flats.cpp b/src/gl/scene/gl_flats.cpp index d9c080d15..5ceee553b 100644 --- a/src/gl/scene/gl_flats.cpp +++ b/src/gl/scene/gl_flats.cpp @@ -48,51 +48,6 @@ #include "gl/scene/gl_scenedrawer.h" #include "gl/renderer/gl_quaddrawer.h" -#ifdef _DEBUG -CVAR(Int, gl_breaksec, -1, 0) -#endif -//========================================================================== -// -// Sets the texture matrix according to the plane's texture positioning -// information -// -//========================================================================== - -bool gl_SetPlaneTextureRotation(const GLSectorPlane * secplane, FMaterial * gltexture, VSMatrix &dest) -{ - // only manipulate the texture matrix if needed. - if (!secplane->Offs.isZero() || - secplane->Scale.X != 1. || secplane->Scale.Y != 1 || - secplane->Angle != 0 || - gltexture->TextureWidth() != 64 || - gltexture->TextureHeight() != 64) - { - float uoffs = secplane->Offs.X / gltexture->TextureWidth(); - float voffs = secplane->Offs.Y / gltexture->TextureHeight(); - - float xscale1 = secplane->Scale.X; - float yscale1 = secplane->Scale.Y; - if (gltexture->tex->bHasCanvas) - { - yscale1 = 0 - yscale1; - } - float angle = -secplane->Angle; - - float xscale2 = 64.f / gltexture->TextureWidth(); - float yscale2 = 64.f / gltexture->TextureHeight(); - - dest.loadIdentity(); - dest.scale(xscale1, yscale1, 1.0f); - dest.translate(uoffs, voffs, 0.0f); - dest.scale(xscale2, yscale2, 1.0f); - dest.rotate(angle, 0.0f, 0.0f, 1.0f); - return true; - } - return false; -} - - - //========================================================================== // // Flats @@ -100,54 +55,25 @@ bool gl_SetPlaneTextureRotation(const GLSectorPlane * secplane, FMaterial * glte //========================================================================== extern FDynLightData lightdata; -void GLFlat::SetupSubsectorLights(int pass, subsector_t * sub, int *dli) +void FDrawInfo::SetupSubsectorLights(GLFlat *flat, int pass, subsector_t * sub, int *dli) { - Plane p; - - if (renderstyle == STYLE_Add && !level.lightadditivesurfaces) return; // no lights on additively blended surfaces. - if (dli != NULL && *dli != -1) { gl_RenderState.ApplyLightIndex(GLRenderer->mLights->GetIndex(*dli)); (*dli)++; return; } - - lightdata.Clear(); - FLightNode * node = sub->lighthead; - while (node) + if (flat->SetupSubsectorLights(pass, sub)) { - ADynamicLight * light = node->lightsource; - - if (light->flags2&MF2_DORMANT) + int d = GLRenderer->mLights->UploadLights(lightdata); + if (pass == GLPASS_LIGHTSONLY) { - node=node->nextLight; - continue; + GLRenderer->mLights->StoreIndex(d); } - iter_dlightf++; - - // we must do the side check here because gl_GetLight needs the correct plane orientation - // which we don't have for Legacy-style 3D-floors - double planeh = plane.plane.ZatPoint(light); - if ((planehZ() && ceiling) || (planeh>light->Z() && !ceiling)) + else { - node = node->nextLight; - continue; + gl_RenderState.ApplyLightIndex(d); } - - p.Set(plane.plane.Normal(), plane.plane.fD()); - lightdata.GetLight(sub->sector->PortalGroup, p, light, false); - node = node->nextLight; - } - - int d = GLRenderer->mLights->UploadLights(lightdata); - if (pass == GLPASS_LIGHTSONLY) - { - GLRenderer->mLights->StoreIndex(d); - } - else - { - gl_RenderState.ApplyLightIndex(d); } } @@ -218,7 +144,7 @@ void FDrawInfo::ProcessLights(GLFlat *flat, bool istrans) subsector_t * sub = flat->sector->subsectors[i]; if (gl_drawinfo->ss_renderflags[sub->Index()]& flat->renderflags || istrans) { - flat->SetupSubsectorLights(GLPASS_LIGHTSONLY, sub); + SetupSubsectorLights(flat, GLPASS_LIGHTSONLY, sub, nullptr); } } @@ -231,7 +157,7 @@ void FDrawInfo::ProcessLights(GLFlat *flat, bool istrans) while (node) { - flat->SetupSubsectorLights(GLPASS_LIGHTSONLY, node->sub); + SetupSubsectorLights(flat, GLPASS_LIGHTSONLY, node->sub, nullptr); node = node->next; } } @@ -258,7 +184,7 @@ void FDrawInfo::DrawSubsectors(GLFlat *flat, int pass, bool processlights, bool if (gl_drawinfo->ss_renderflags[sub->Index()]& flat->renderflags || istrans) { - if (processlights) flat->SetupSubsectorLights(GLPASS_ALL, sub, &dli); + if (processlights) SetupSubsectorLights(flat, GLPASS_ALL, sub, &dli); drawcalls.Clock(); glDrawArrays(GL_TRIANGLE_FAN, index, sub->numlines); drawcalls.Unclock(); @@ -277,7 +203,7 @@ void FDrawInfo::DrawSubsectors(GLFlat *flat, int pass, bool processlights, bool subsector_t * sub = flat->sector->subsectors[i]; if (gl_drawinfo->ss_renderflags[sub->Index()]& flat->renderflags || istrans) { - if (processlights) flat->SetupSubsectorLights(GLPASS_ALL, sub, &dli); + if (processlights) SetupSubsectorLights(flat, GLPASS_ALL, sub, &dli); DrawSubsector(flat, sub); } } @@ -292,7 +218,7 @@ void FDrawInfo::DrawSubsectors(GLFlat *flat, int pass, bool processlights, bool while (node) { - if (processlights) flat->SetupSubsectorLights(GLPASS_ALL, node->sub, &dli); + if (processlights) SetupSubsectorLights(flat, GLPASS_ALL, node->sub, &dli); DrawSubsector(flat, node->sub); node = node->next; } @@ -358,13 +284,6 @@ void FDrawInfo::DrawFlat(GLFlat *flat, int pass, bool trans) // trans only has m { int rel = getExtraLight(); -#ifdef _DEBUG - if (sector->sectornum == gl_breaksec) - { - int a = 0; - } -#endif - auto &plane = flat->plane; gl_RenderState.SetNormal(plane.plane.Normal().X, plane.plane.Normal().Z, plane.plane.Normal().Y); @@ -485,364 +404,3 @@ void FDrawInfo::AddFlat(GLFlat *flat, bool fog) *newflat = *flat; } -//========================================================================== -// -// GLFlat::PutFlat -// -// submit to the renderer -// -//========================================================================== - -inline void GLFlat::PutFlat(HWDrawInfo *di, bool fog) -{ - if (di->FixedColormap) - { - Colormap.Clear(); - } - dynlightindex = -1; // make sure this is always initialized to something proper. - di->AddFlat(this, fog); -} - -//========================================================================== -// -// This draws one flat -// The passed sector does not indicate the area which is rendered. -// It is only used as source for the plane data. -// The whichplane boolean indicates if the flat is a floor(false) or a ceiling(true) -// -//========================================================================== - -void GLFlat::Process(HWDrawInfo *di, sector_t * model, int whichplane, bool fog) -{ - plane.GetFromSector(model, whichplane); - if (whichplane != int(ceiling)) - { - // Flip the normal if the source plane has a different orientation than what we are about to render. - plane.plane.FlipVert(); - } - - if (!fog) - { - gltexture=FMaterial::ValidateTexture(plane.texture, false, true); - if (!gltexture) return; - if (gltexture->tex->isFullbright()) - { - Colormap.MakeWhite(); - lightlevel=255; - } - } - else - { - gltexture = NULL; - lightlevel = abs(lightlevel); - } - - // get height from vplane - if (whichplane == sector_t::floor && sector->transdoor) dz = -1; - else dz = 0; - - z = plane.plane.ZatPoint(0.f, 0.f); - - PutFlat(di, fog); - rendered_flats++; -} - -//========================================================================== -// -// Sets 3D floor info. Common code for all 4 cases -// -//========================================================================== - -void GLFlat::SetFrom3DFloor(F3DFloor *rover, bool top, bool underside) -{ - F3DFloor::planeref & plane = top? rover->top : rover->bottom; - - // FF_FOG requires an inverted logic where to get the light from - lightlist_t *light = P_GetPlaneLight(sector, plane.plane, underside); - lightlevel = hw_ClampLight(*light->p_lightlevel); - - if (rover->flags & FF_FOG) - { - Colormap.LightColor = light->extra_colormap.FadeColor; - FlatColor = 0xffffffff; - } - else - { - Colormap.CopyFrom3DLight(light); - FlatColor = *plane.flatcolor; - } - - - alpha = rover->alpha/255.0f; - renderstyle = rover->flags&FF_ADDITIVETRANS? STYLE_Add : STYLE_Translucent; - if (plane.model->VBOHeightcheck(plane.isceiling)) - { - vboindex = plane.vindex; - } - else - { - vboindex = -1; - } -} - -//========================================================================== -// -// Process a sector's flats for rendering -// This function is only called once per sector. -// Subsequent subsectors are just quickly added to the ss_renderflags array -// -//========================================================================== - -void GLFlat::ProcessSector(HWDrawInfo *di, sector_t * frontsector) -{ - lightlist_t * light; - FSectorPortal *port; - -#ifdef _DEBUG - if (frontsector->sectornum == gl_breaksec) - { - int a = 0; - } -#endif - - // Get the real sector for this one. - sector = &level.sectors[frontsector->sectornum]; - extsector_t::xfloor &x = sector->e->XFloor; - dynlightindex = -1; - - uint8_t &srf = di->sectorrenderflags[sector->sectornum]; - - // - // - // - // do floors - // - // - // - if (frontsector->floorplane.ZatPoint(r_viewpoint.Pos) <= r_viewpoint.Pos.Z) - { - // process the original floor first. - - srf |= SSRF_RENDERFLOOR; - - lightlevel = hw_ClampLight(frontsector->GetFloorLight()); - Colormap = frontsector->Colormap; - FlatColor = frontsector->SpecialColors[sector_t::floor]; - port = frontsector->ValidatePortal(sector_t::floor); - if ((stack = (port != NULL))) - { - if (port->mType == PORTS_STACKEDSECTORTHING) - { - di->AddFloorStack(sector); // stacked sector things require visplane merging. - } - alpha = frontsector->GetAlpha(sector_t::floor); - } - else - { - alpha = 1.0f - frontsector->GetReflect(sector_t::floor); - } - - if (alpha != 0.f && frontsector->GetTexture(sector_t::floor) != skyflatnum) - { - if (frontsector->VBOHeightcheck(sector_t::floor)) - { - vboindex = frontsector->vboindex[sector_t::floor]; - } - else - { - vboindex = -1; - } - - ceiling = false; - renderflags = SSRF_RENDERFLOOR; - - if (x.ffloors.Size()) - { - light = P_GetPlaneLight(sector, &frontsector->floorplane, false); - if ((!(sector->GetFlags(sector_t::floor)&PLANEF_ABSLIGHTING) || light->lightsource == NULL) - && (light->p_lightlevel != &frontsector->lightlevel)) - { - lightlevel = hw_ClampLight(*light->p_lightlevel); - } - - Colormap.CopyFrom3DLight(light); - } - renderstyle = STYLE_Translucent; - Process(di, frontsector, sector_t::floor, false); - } - } - - // - // - // - // do ceilings - // - // - // - if (frontsector->ceilingplane.ZatPoint(r_viewpoint.Pos) >= r_viewpoint.Pos.Z) - { - // process the original ceiling first. - - srf |= SSRF_RENDERCEILING; - - lightlevel = hw_ClampLight(frontsector->GetCeilingLight()); - Colormap = frontsector->Colormap; - FlatColor = frontsector->SpecialColors[sector_t::ceiling]; - port = frontsector->ValidatePortal(sector_t::ceiling); - if ((stack = (port != NULL))) - { - if (port->mType == PORTS_STACKEDSECTORTHING) - { - di->AddCeilingStack(sector); - } - alpha = frontsector->GetAlpha(sector_t::ceiling); - } - else - { - alpha = 1.0f - frontsector->GetReflect(sector_t::ceiling); - } - - if (alpha != 0.f && frontsector->GetTexture(sector_t::ceiling) != skyflatnum) - { - if (frontsector->VBOHeightcheck(sector_t::ceiling)) - { - vboindex = frontsector->vboindex[sector_t::ceiling]; - } - else - { - vboindex = -1; - } - - ceiling = true; - renderflags = SSRF_RENDERCEILING; - - if (x.ffloors.Size()) - { - light = P_GetPlaneLight(sector, §or->ceilingplane, true); - - if ((!(sector->GetFlags(sector_t::ceiling)&PLANEF_ABSLIGHTING)) - && (light->p_lightlevel != &frontsector->lightlevel)) - { - lightlevel = hw_ClampLight(*light->p_lightlevel); - } - Colormap.CopyFrom3DLight(light); - } - renderstyle = STYLE_Translucent; - Process(di, frontsector, sector_t::ceiling, false); - } - } - - // - // - // - // do 3D floors - // - // - // - - stack = false; - if (x.ffloors.Size()) - { - player_t * player = players[consoleplayer].camera->player; - - renderflags = SSRF_RENDER3DPLANES; - srf |= SSRF_RENDER3DPLANES; - // 3d-floors must not overlap! - double lastceilingheight = sector->CenterCeiling(); // render only in the range of the - double lastfloorheight = sector->CenterFloor(); // current sector part (if applicable) - F3DFloor * rover; - int k; - - // floors are ordered now top to bottom so scanning the list for the best match - // is no longer necessary. - - ceiling = true; - Colormap = frontsector->Colormap; - for (k = 0; k < (int)x.ffloors.Size(); k++) - { - rover = x.ffloors[k]; - - if ((rover->flags&(FF_EXISTS | FF_RENDERPLANES | FF_THISINSIDE)) == (FF_EXISTS | FF_RENDERPLANES)) - { - if (rover->flags&FF_FOG && di->FixedColormap) continue; - if (!rover->top.copied && rover->flags&(FF_INVERTPLANES | FF_BOTHPLANES)) - { - double ff_top = rover->top.plane->ZatPoint(sector->centerspot); - if (ff_top < lastceilingheight) - { - if (r_viewpoint.Pos.Z <= rover->top.plane->ZatPoint(r_viewpoint.Pos)) - { - SetFrom3DFloor(rover, true, !!(rover->flags&FF_FOG)); - Colormap.FadeColor = frontsector->Colormap.FadeColor; - Process(di, rover->top.model, rover->top.isceiling, !!(rover->flags&FF_FOG)); - } - lastceilingheight = ff_top; - } - } - if (!rover->bottom.copied && !(rover->flags&FF_INVERTPLANES)) - { - double ff_bottom = rover->bottom.plane->ZatPoint(sector->centerspot); - if (ff_bottom < lastceilingheight) - { - if (r_viewpoint.Pos.Z <= rover->bottom.plane->ZatPoint(r_viewpoint.Pos)) - { - SetFrom3DFloor(rover, false, !(rover->flags&FF_FOG)); - Colormap.FadeColor = frontsector->Colormap.FadeColor; - Process(di, rover->bottom.model, rover->bottom.isceiling, !!(rover->flags&FF_FOG)); - } - lastceilingheight = ff_bottom; - if (rover->alpha < 255) lastceilingheight += EQUAL_EPSILON; - } - } - } - } - - ceiling = false; - for (k = x.ffloors.Size() - 1; k >= 0; k--) - { - rover = x.ffloors[k]; - - if ((rover->flags&(FF_EXISTS | FF_RENDERPLANES | FF_THISINSIDE)) == (FF_EXISTS | FF_RENDERPLANES)) - { - if (rover->flags&FF_FOG && di->FixedColormap) continue; - if (!rover->bottom.copied && rover->flags&(FF_INVERTPLANES | FF_BOTHPLANES)) - { - double ff_bottom = rover->bottom.plane->ZatPoint(sector->centerspot); - if (ff_bottom > lastfloorheight || (rover->flags&FF_FIX)) - { - if (r_viewpoint.Pos.Z >= rover->bottom.plane->ZatPoint(r_viewpoint.Pos)) - { - SetFrom3DFloor(rover, false, !(rover->flags&FF_FOG)); - Colormap.FadeColor = frontsector->Colormap.FadeColor; - - if (rover->flags&FF_FIX) - { - lightlevel = hw_ClampLight(rover->model->lightlevel); - Colormap = rover->GetColormap(); - } - - Process(di, rover->bottom.model, rover->bottom.isceiling, !!(rover->flags&FF_FOG)); - } - lastfloorheight = ff_bottom; - } - } - if (!rover->top.copied && !(rover->flags&FF_INVERTPLANES)) - { - double ff_top = rover->top.plane->ZatPoint(sector->centerspot); - if (ff_top > lastfloorheight) - { - if (r_viewpoint.Pos.Z >= rover->top.plane->ZatPoint(r_viewpoint.Pos)) - { - SetFrom3DFloor(rover, true, !!(rover->flags&FF_FOG)); - Colormap.FadeColor = frontsector->Colormap.FadeColor; - Process(di, rover->top.model, rover->top.isceiling, !!(rover->flags&FF_FOG)); - } - lastfloorheight = ff_top; - if (rover->alpha < 255) lastfloorheight -= EQUAL_EPSILON; - } - } - } - } - } -} - diff --git a/src/hwrenderer/scene/hw_drawstructs.h b/src/hwrenderer/scene/hw_drawstructs.h index f3253d071..0dd95cd69 100644 --- a/src/hwrenderer/scene/hw_drawstructs.h +++ b/src/hwrenderer/scene/hw_drawstructs.h @@ -311,7 +311,7 @@ public: int dynlightindex; - void SetupSubsectorLights(int pass, subsector_t * sub, int *dli = NULL); + bool SetupSubsectorLights(int pass, subsector_t * sub); void PutFlat(HWDrawInfo *di, bool fog = false); void Process(HWDrawInfo *di, sector_t * model, int whichplane, bool notexture); diff --git a/src/hwrenderer/scene/hw_flats.cpp b/src/hwrenderer/scene/hw_flats.cpp new file mode 100644 index 000000000..5f09c6326 --- /dev/null +++ b/src/hwrenderer/scene/hw_flats.cpp @@ -0,0 +1,493 @@ +// +//--------------------------------------------------------------------------- +// +// Copyright(C) 2000-2016 Christoph Oelckers +// All rights reserved. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with this program. If not, see http://www.gnu.org/licenses/ +// +//-------------------------------------------------------------------------- +// +/* +** gl_flat.cpp +** Flat processing +** +*/ + +#include "gl/system/gl_system.h" +#include "a_sharedglobal.h" +#include "r_defs.h" +#include "r_sky.h" +#include "r_utility.h" +#include "doomstat.h" +#include "d_player.h" +#include "g_levellocals.h" +#include "actorinlines.h" +#include "p_lnspec.h" +#include "r_data/matrix.h" +#include "hwrenderer/dynlights/hw_dynlightdata.h" +#include "hwrenderer/utility/hw_cvars.h" +#include "hwrenderer/utility/hw_clock.h" +#include "hwrenderer/utility/hw_lighting.h" +#include "hwrenderer/textures/hw_material.h" +#include "hwrenderer/scene/hw_drawinfo.h" +#include "hw_drawstructs.h" + +#ifdef _DEBUG +CVAR(Int, gl_breaksec, -1, 0) +#endif +//========================================================================== +// +// Sets the texture matrix according to the plane's texture positioning +// information +// +//========================================================================== + +bool gl_SetPlaneTextureRotation(const GLSectorPlane * secplane, FMaterial * gltexture, VSMatrix &dest) +{ + // only manipulate the texture matrix if needed. + if (!secplane->Offs.isZero() || + secplane->Scale.X != 1. || secplane->Scale.Y != 1 || + secplane->Angle != 0 || + gltexture->TextureWidth() != 64 || + gltexture->TextureHeight() != 64) + { + float uoffs = secplane->Offs.X / gltexture->TextureWidth(); + float voffs = secplane->Offs.Y / gltexture->TextureHeight(); + + float xscale1 = secplane->Scale.X; + float yscale1 = secplane->Scale.Y; + if (gltexture->tex->bHasCanvas) + { + yscale1 = 0 - yscale1; + } + float angle = -secplane->Angle; + + float xscale2 = 64.f / gltexture->TextureWidth(); + float yscale2 = 64.f / gltexture->TextureHeight(); + + dest.loadIdentity(); + dest.scale(xscale1, yscale1, 1.0f); + dest.translate(uoffs, voffs, 0.0f); + dest.scale(xscale2, yscale2, 1.0f); + dest.rotate(angle, 0.0f, 0.0f, 1.0f); + return true; + } + return false; +} + +//========================================================================== +// +// Flats +// +//========================================================================== +extern FDynLightData lightdata; + +bool GLFlat::SetupSubsectorLights(int pass, subsector_t * sub) +{ + Plane p; + + if (renderstyle == STYLE_Add && !level.lightadditivesurfaces) return false; // no lights on additively blended surfaces. + + lightdata.Clear(); + FLightNode * node = sub->lighthead; + while (node) + { + ADynamicLight * light = node->lightsource; + + if (light->flags2&MF2_DORMANT) + { + node = node->nextLight; + continue; + } + iter_dlightf++; + + // we must do the side check here because gl_GetLight needs the correct plane orientation + // which we don't have for Legacy-style 3D-floors + double planeh = plane.plane.ZatPoint(light); + if ((planehZ() && ceiling) || (planeh>light->Z() && !ceiling)) + { + node = node->nextLight; + continue; + } + + p.Set(plane.plane.Normal(), plane.plane.fD()); + lightdata.GetLight(sub->sector->PortalGroup, p, light, false); + node = node->nextLight; + } + + return true; +} + +//========================================================================== +// +// GLFlat::PutFlat +// +// submit to the renderer +// +//========================================================================== + +inline void GLFlat::PutFlat(HWDrawInfo *di, bool fog) +{ + if (di->FixedColormap) + { + Colormap.Clear(); + } + dynlightindex = -1; // make sure this is always initialized to something proper. + di->AddFlat(this, fog); +} + +//========================================================================== +// +// This draws one flat +// The passed sector does not indicate the area which is rendered. +// It is only used as source for the plane data. +// The whichplane boolean indicates if the flat is a floor(false) or a ceiling(true) +// +//========================================================================== + +void GLFlat::Process(HWDrawInfo *di, sector_t * model, int whichplane, bool fog) +{ + plane.GetFromSector(model, whichplane); + if (whichplane != int(ceiling)) + { + // Flip the normal if the source plane has a different orientation than what we are about to render. + plane.plane.FlipVert(); + } + + if (!fog) + { + gltexture=FMaterial::ValidateTexture(plane.texture, false, true); + if (!gltexture) return; + if (gltexture->tex->isFullbright()) + { + Colormap.MakeWhite(); + lightlevel=255; + } + } + else + { + gltexture = NULL; + lightlevel = abs(lightlevel); + } + + // get height from vplane + if (whichplane == sector_t::floor && sector->transdoor) dz = -1; + else dz = 0; + + z = plane.plane.ZatPoint(0.f, 0.f); + + PutFlat(di, fog); + rendered_flats++; +} + +//========================================================================== +// +// Sets 3D floor info. Common code for all 4 cases +// +//========================================================================== + +void GLFlat::SetFrom3DFloor(F3DFloor *rover, bool top, bool underside) +{ + F3DFloor::planeref & plane = top? rover->top : rover->bottom; + + // FF_FOG requires an inverted logic where to get the light from + lightlist_t *light = P_GetPlaneLight(sector, plane.plane, underside); + lightlevel = hw_ClampLight(*light->p_lightlevel); + + if (rover->flags & FF_FOG) + { + Colormap.LightColor = light->extra_colormap.FadeColor; + FlatColor = 0xffffffff; + } + else + { + Colormap.CopyFrom3DLight(light); + FlatColor = *plane.flatcolor; + } + + + alpha = rover->alpha/255.0f; + renderstyle = rover->flags&FF_ADDITIVETRANS? STYLE_Add : STYLE_Translucent; + if (plane.model->VBOHeightcheck(plane.isceiling)) + { + vboindex = plane.vindex; + } + else + { + vboindex = -1; + } +} + +//========================================================================== +// +// Process a sector's flats for rendering +// This function is only called once per sector. +// Subsequent subsectors are just quickly added to the ss_renderflags array +// +//========================================================================== + +void GLFlat::ProcessSector(HWDrawInfo *di, sector_t * frontsector) +{ + lightlist_t * light; + FSectorPortal *port; + +#ifdef _DEBUG + if (frontsector->sectornum == gl_breaksec) + { + int a = 0; + } +#endif + + // Get the real sector for this one. + sector = &level.sectors[frontsector->sectornum]; + extsector_t::xfloor &x = sector->e->XFloor; + dynlightindex = -1; + + uint8_t &srf = di->sectorrenderflags[sector->sectornum]; + + // + // + // + // do floors + // + // + // + if (frontsector->floorplane.ZatPoint(r_viewpoint.Pos) <= r_viewpoint.Pos.Z) + { + // process the original floor first. + + srf |= SSRF_RENDERFLOOR; + + lightlevel = hw_ClampLight(frontsector->GetFloorLight()); + Colormap = frontsector->Colormap; + FlatColor = frontsector->SpecialColors[sector_t::floor]; + port = frontsector->ValidatePortal(sector_t::floor); + if ((stack = (port != NULL))) + { + if (port->mType == PORTS_STACKEDSECTORTHING) + { + di->AddFloorStack(sector); // stacked sector things require visplane merging. + } + alpha = frontsector->GetAlpha(sector_t::floor); + } + else + { + alpha = 1.0f - frontsector->GetReflect(sector_t::floor); + } + + if (alpha != 0.f && frontsector->GetTexture(sector_t::floor) != skyflatnum) + { + if (frontsector->VBOHeightcheck(sector_t::floor)) + { + vboindex = frontsector->vboindex[sector_t::floor]; + } + else + { + vboindex = -1; + } + + ceiling = false; + renderflags = SSRF_RENDERFLOOR; + + if (x.ffloors.Size()) + { + light = P_GetPlaneLight(sector, &frontsector->floorplane, false); + if ((!(sector->GetFlags(sector_t::floor)&PLANEF_ABSLIGHTING) || light->lightsource == NULL) + && (light->p_lightlevel != &frontsector->lightlevel)) + { + lightlevel = hw_ClampLight(*light->p_lightlevel); + } + + Colormap.CopyFrom3DLight(light); + } + renderstyle = STYLE_Translucent; + Process(di, frontsector, sector_t::floor, false); + } + } + + // + // + // + // do ceilings + // + // + // + if (frontsector->ceilingplane.ZatPoint(r_viewpoint.Pos) >= r_viewpoint.Pos.Z) + { + // process the original ceiling first. + + srf |= SSRF_RENDERCEILING; + + lightlevel = hw_ClampLight(frontsector->GetCeilingLight()); + Colormap = frontsector->Colormap; + FlatColor = frontsector->SpecialColors[sector_t::ceiling]; + port = frontsector->ValidatePortal(sector_t::ceiling); + if ((stack = (port != NULL))) + { + if (port->mType == PORTS_STACKEDSECTORTHING) + { + di->AddCeilingStack(sector); + } + alpha = frontsector->GetAlpha(sector_t::ceiling); + } + else + { + alpha = 1.0f - frontsector->GetReflect(sector_t::ceiling); + } + + if (alpha != 0.f && frontsector->GetTexture(sector_t::ceiling) != skyflatnum) + { + if (frontsector->VBOHeightcheck(sector_t::ceiling)) + { + vboindex = frontsector->vboindex[sector_t::ceiling]; + } + else + { + vboindex = -1; + } + + ceiling = true; + renderflags = SSRF_RENDERCEILING; + + if (x.ffloors.Size()) + { + light = P_GetPlaneLight(sector, §or->ceilingplane, true); + + if ((!(sector->GetFlags(sector_t::ceiling)&PLANEF_ABSLIGHTING)) + && (light->p_lightlevel != &frontsector->lightlevel)) + { + lightlevel = hw_ClampLight(*light->p_lightlevel); + } + Colormap.CopyFrom3DLight(light); + } + renderstyle = STYLE_Translucent; + Process(di, frontsector, sector_t::ceiling, false); + } + } + + // + // + // + // do 3D floors + // + // + // + + stack = false; + if (x.ffloors.Size()) + { + player_t * player = players[consoleplayer].camera->player; + + renderflags = SSRF_RENDER3DPLANES; + srf |= SSRF_RENDER3DPLANES; + // 3d-floors must not overlap! + double lastceilingheight = sector->CenterCeiling(); // render only in the range of the + double lastfloorheight = sector->CenterFloor(); // current sector part (if applicable) + F3DFloor * rover; + int k; + + // floors are ordered now top to bottom so scanning the list for the best match + // is no longer necessary. + + ceiling = true; + Colormap = frontsector->Colormap; + for (k = 0; k < (int)x.ffloors.Size(); k++) + { + rover = x.ffloors[k]; + + if ((rover->flags&(FF_EXISTS | FF_RENDERPLANES | FF_THISINSIDE)) == (FF_EXISTS | FF_RENDERPLANES)) + { + if (rover->flags&FF_FOG && di->FixedColormap) continue; + if (!rover->top.copied && rover->flags&(FF_INVERTPLANES | FF_BOTHPLANES)) + { + double ff_top = rover->top.plane->ZatPoint(sector->centerspot); + if (ff_top < lastceilingheight) + { + if (r_viewpoint.Pos.Z <= rover->top.plane->ZatPoint(r_viewpoint.Pos)) + { + SetFrom3DFloor(rover, true, !!(rover->flags&FF_FOG)); + Colormap.FadeColor = frontsector->Colormap.FadeColor; + Process(di, rover->top.model, rover->top.isceiling, !!(rover->flags&FF_FOG)); + } + lastceilingheight = ff_top; + } + } + if (!rover->bottom.copied && !(rover->flags&FF_INVERTPLANES)) + { + double ff_bottom = rover->bottom.plane->ZatPoint(sector->centerspot); + if (ff_bottom < lastceilingheight) + { + if (r_viewpoint.Pos.Z <= rover->bottom.plane->ZatPoint(r_viewpoint.Pos)) + { + SetFrom3DFloor(rover, false, !(rover->flags&FF_FOG)); + Colormap.FadeColor = frontsector->Colormap.FadeColor; + Process(di, rover->bottom.model, rover->bottom.isceiling, !!(rover->flags&FF_FOG)); + } + lastceilingheight = ff_bottom; + if (rover->alpha < 255) lastceilingheight += EQUAL_EPSILON; + } + } + } + } + + ceiling = false; + for (k = x.ffloors.Size() - 1; k >= 0; k--) + { + rover = x.ffloors[k]; + + if ((rover->flags&(FF_EXISTS | FF_RENDERPLANES | FF_THISINSIDE)) == (FF_EXISTS | FF_RENDERPLANES)) + { + if (rover->flags&FF_FOG && di->FixedColormap) continue; + if (!rover->bottom.copied && rover->flags&(FF_INVERTPLANES | FF_BOTHPLANES)) + { + double ff_bottom = rover->bottom.plane->ZatPoint(sector->centerspot); + if (ff_bottom > lastfloorheight || (rover->flags&FF_FIX)) + { + if (r_viewpoint.Pos.Z >= rover->bottom.plane->ZatPoint(r_viewpoint.Pos)) + { + SetFrom3DFloor(rover, false, !(rover->flags&FF_FOG)); + Colormap.FadeColor = frontsector->Colormap.FadeColor; + + if (rover->flags&FF_FIX) + { + lightlevel = hw_ClampLight(rover->model->lightlevel); + Colormap = rover->GetColormap(); + } + + Process(di, rover->bottom.model, rover->bottom.isceiling, !!(rover->flags&FF_FOG)); + } + lastfloorheight = ff_bottom; + } + } + if (!rover->top.copied && !(rover->flags&FF_INVERTPLANES)) + { + double ff_top = rover->top.plane->ZatPoint(sector->centerspot); + if (ff_top > lastfloorheight) + { + if (r_viewpoint.Pos.Z >= rover->top.plane->ZatPoint(r_viewpoint.Pos)) + { + SetFrom3DFloor(rover, true, !!(rover->flags&FF_FOG)); + Colormap.FadeColor = frontsector->Colormap.FadeColor; + Process(di, rover->top.model, rover->top.isceiling, !!(rover->flags&FF_FOG)); + } + lastfloorheight = ff_top; + if (rover->alpha < 255) lastfloorheight -= EQUAL_EPSILON; + } + } + } + } + } +} +