From 8ffeb7812f3fe54eccb00bbfc063f2d1db01de0c Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 21 Oct 2018 13:53:50 +0200 Subject: [PATCH] - made wall draw code API independent. --- src/gl/scene/gl_drawinfo.cpp | 15 +- src/gl/scene/gl_drawinfo.h | 12 +- src/gl/scene/gl_scene.cpp | 16 +- src/gl/scene/gl_sprite.cpp | 2 - src/gl/scene/gl_walls_draw.cpp | 225 -------------------------- src/hwrenderer/scene/hw_decal.cpp | 2 + src/hwrenderer/scene/hw_drawinfo.cpp | 18 +++ src/hwrenderer/scene/hw_drawinfo.h | 12 +- src/hwrenderer/scene/hw_drawlist.cpp | 6 +- src/hwrenderer/scene/hw_drawlist.h | 2 +- src/hwrenderer/scene/hw_drawstructs.h | 9 +- src/hwrenderer/scene/hw_walls.cpp | 220 +++++++++++++++++++++++++ 12 files changed, 275 insertions(+), 264 deletions(-) diff --git a/src/gl/scene/gl_drawinfo.cpp b/src/gl/scene/gl_drawinfo.cpp index 221b2e3e3..7e2609b4e 100644 --- a/src/gl/scene/gl_drawinfo.cpp +++ b/src/gl/scene/gl_drawinfo.cpp @@ -209,8 +209,6 @@ void FDrawInfo::StartScene() outer = gl_drawinfo; gl_drawinfo = this; for (int i = 0; i < GLDL_TYPES; i++) drawlists[i].Reset(); - decals[0].Clear(); - decals[1].Clear(); hudsprites.Clear(); vpIndex = 0; @@ -256,13 +254,6 @@ std::pair FDrawInfo::AllocVertices(unsigned int cou return std::make_pair(p, index); } -GLDecal *FDrawInfo::AddDecal(bool onmirror) -{ - auto decal = (GLDecal*)RenderDataAllocator.Alloc(sizeof(GLDecal)); - decals[onmirror ? 1 : 0].Push(decal); - return decal; -} - int FDrawInfo::UploadLights(FDynLightData &data) { return GLRenderer->mLights->UploadLights(data); @@ -312,6 +303,12 @@ void FDrawInfo::SetDepthMask(bool on) glDepthMask(on); } +void FDrawInfo::SetDepthFunc(int func) +{ + static int df2gl[] = { GL_LESS, GL_LEQUAL, GL_ALWAYS }; + glDepthFunc(df2gl[func]); +} + void FDrawInfo::EnableDrawBufferAttachments(bool on) { gl_RenderState.EnableDrawBuffers(on? gl_RenderState.GetPassDrawBufferCount() : 1); diff --git a/src/gl/scene/gl_drawinfo.h b/src/gl/scene/gl_drawinfo.h index b1e07de0c..98b385d87 100644 --- a/src/gl/scene/gl_drawinfo.h +++ b/src/gl/scene/gl_drawinfo.h @@ -30,7 +30,6 @@ enum DrawListType enum Drawpasses { GLPASS_ALL, // Main pass with dynamic lights - GLPASS_DECALS, // Draws a decal GLPASS_TRANSLUCENT, // Draws translucent objects }; @@ -38,14 +37,12 @@ struct FDrawInfo : public HWDrawInfo { HWDrawList drawlists[GLDL_TYPES]; TArray hudsprites; // These may just be stored by value. - TArray decals[2]; // the second slot is for mirrors which get rendered in a separate pass. int vpIndex; void ApplyVPUniforms() override; void AddWall(GLWall *wall) override; void AddMirrorSurface(GLWall *w) override; - GLDecal *AddDecal(bool onmirror) override; void AddPortal(GLWall *w, int portaltype) override; void AddFlat(GLFlat *flat, bool fog) override; void AddSprite(GLSprite *sprite, bool translucent) override; @@ -57,18 +54,11 @@ struct FDrawInfo : public HWDrawInfo void Draw(EDrawType dt, FRenderState &state, int index, int count, bool apply = true) override; void DrawIndexed(EDrawType dt, FRenderState &state, int index, int count, bool apply = true) override; void SetDepthMask(bool on) override; + void SetDepthFunc(int func) override; void EnableDrawBufferAttachments(bool on) override; void StartScene(); - // Wall drawer - void RenderWall(GLWall *wall, FRenderState &state, int textured); - void RenderFogBoundary(GLWall *wall, FRenderState &state); - void RenderMirrorSurface(GLWall *wall, FRenderState &state); - void RenderTranslucentWall(GLWall *wall, FRenderState &state); - void RenderTexturedWall(GLWall *wall, FRenderState &state, int rflags); - void DrawWall(GLWall *wall, int pass) override; - // Sprite drawer void DrawSprite(GLSprite *sprite, int pass); void DrawPSprite(HUDSprite *huds); diff --git a/src/gl/scene/gl_scene.cpp b/src/gl/scene/gl_scene.cpp index 609653bad..529ed13a3 100644 --- a/src/gl/scene/gl_scene.cpp +++ b/src/gl/scene/gl_scene.cpp @@ -173,7 +173,7 @@ void FDrawInfo::RenderScene(int recursion) gl_RenderState.EnableTexture(gl_texture); gl_RenderState.EnableBrightmap(true); - drawlists[GLDL_PLAINWALLS].DrawWalls(this, pass); + drawlists[GLDL_PLAINWALLS].DrawWalls(this, gl_RenderState, false); drawlists[GLDL_PLAINFLATS].DrawFlats(this, gl_RenderState, false); @@ -184,17 +184,15 @@ void FDrawInfo::RenderScene(int recursion) gl_RenderState.SetTextureMode(TM_STENCIL); } gl_RenderState.AlphaFunc(Alpha_GEqual, gl_mask_threshold); - drawlists[GLDL_MASKEDWALLS].DrawWalls(this, pass); + drawlists[GLDL_MASKEDWALLS].DrawWalls(this, gl_RenderState, false); drawlists[GLDL_MASKEDFLATS].DrawFlats(this, gl_RenderState, false); // Part 3: masked geometry with polygon offset. This list is empty most of the time so only waste time on it when in use. if (drawlists[GLDL_MASKEDWALLSOFS].Size() > 0) { - glEnable(GL_POLYGON_OFFSET_FILL); - glPolygonOffset(-1.0f, -128.0f); - drawlists[GLDL_MASKEDWALLSOFS].DrawWalls(this, pass); - glDisable(GL_POLYGON_OFFSET_FILL); - glPolygonOffset(0, 0); + gl_RenderState.SetDepthBias(-1, -128); + drawlists[GLDL_MASKEDWALLSOFS].DrawWalls(this, gl_RenderState, false); + gl_RenderState.ClearDepthBias(); } drawlists[GLDL_MODELS].Draw(this, gl_RenderState, false, pass); @@ -203,10 +201,8 @@ void FDrawInfo::RenderScene(int recursion) // Part 4: Draw decals (not a real pass) glDepthFunc(GL_LEQUAL); - glDepthMask(false); - DrawDecals(gl_RenderState, decals[0]); + DrawDecals(gl_RenderState, Decals[0]); - glDepthMask(true); RenderAll.Unclock(); } diff --git a/src/gl/scene/gl_sprite.cpp b/src/gl/scene/gl_sprite.cpp index 1762c54f4..66741e880 100644 --- a/src/gl/scene/gl_sprite.cpp +++ b/src/gl/scene/gl_sprite.cpp @@ -70,8 +70,6 @@ void gl_SetRenderStyle(FRenderStyle style, bool drawopaque, bool allowcolorblend void FDrawInfo::DrawSprite(GLSprite *sprite, int pass) { - if (pass == GLPASS_DECALS) return; - auto RenderStyle = sprite->RenderStyle; bool additivefog = false; diff --git a/src/gl/scene/gl_walls_draw.cpp b/src/gl/scene/gl_walls_draw.cpp index b0da2a841..575d7d029 100644 --- a/src/gl/scene/gl_walls_draw.cpp +++ b/src/gl/scene/gl_walls_draw.cpp @@ -40,231 +40,6 @@ EXTERN_CVAR(Bool, gl_seamless) -//========================================================================== -// -// General purpose wall rendering function -// everything goes through here -// -//========================================================================== - -void FDrawInfo::RenderWall(GLWall *wall, FRenderState &state, int textured) -{ - assert(wall->vertcount > 0); - state.SetLightIndex(wall->dynlightindex); - Draw(DT_TriangleFan, gl_RenderState, wall->vertindex, wall->vertcount); - vertexcount += wall->vertcount; -} - -//========================================================================== -// -// -// -//========================================================================== - -void FDrawInfo::RenderFogBoundary(GLWall *wall, FRenderState &state) -{ - if (gl_fogmode && !isFullbrightScene()) - { - int rel = wall->rellight + getExtraLight(); - EnableDrawBufferAttachments(false); - state.SetFog(wall->lightlevel, rel, false, &wall->Colormap, false); - state.SetEffect(EFF_FOGBOUNDARY); - state.AlphaFunc(Alpha_GEqual, 0.f); - state.SetDepthBias(-1, -128); - RenderWall(wall, state, GLWall::RWF_BLANK); - state.ClearDepthBias(); - state.SetEffect(EFF_NONE); - EnableDrawBufferAttachments(true); - } -} - - -//========================================================================== -// -// -// -//========================================================================== -void FDrawInfo::RenderMirrorSurface(GLWall *wall, FRenderState &state) -{ - if (!TexMan.mirrorTexture.isValid()) return; - - // 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. - state.EnableTextureMatrix(true); - - // Use sphere mapping for this - state.SetEffect(EFF_SPHEREMAP); - - state.SetColor(wall->lightlevel, 0, isFullbrightScene(), wall->Colormap ,0.1f); - state.SetFog(wall->lightlevel, 0, isFullbrightScene(), &wall->Colormap, true); - state.SetRenderStyle(STYLE_Add); - state.AlphaFunc(Alpha_Greater,0); - glDepthFunc(GL_LEQUAL); - - FMaterial * pat=FMaterial::ValidateTexture(TexMan.mirrorTexture, false, false); - gl_RenderState.ApplyMaterial(pat, CLAMP_NONE, 0, -1); - - wall->flags &= ~GLWall::GLWF_GLOW; - RenderWall(wall, state, GLWall::RWF_BLANK); - - state.EnableTextureMatrix(false); - state.SetEffect(EFF_NONE); - - // Restore the defaults for the translucent pass - state.AlphaFunc(Alpha_GEqual, gl_mask_sprite_threshold); - glDepthFunc(GL_LESS); - - // This is drawn in the translucent pass which is done after the decal pass - // As a result the decals have to be drawn here, right after the wall they are on, - // because the depth buffer won't get set by translucent items. - if (wall->seg->sidedef->AttachedDecals) - { - wall->DrawDecalsForMirror(this, gl_RenderState, decals[1]); - } - state.SetRenderStyle(STYLE_Translucent); -} - -//========================================================================== -// -// -// -//========================================================================== - -void FDrawInfo::RenderTexturedWall(GLWall *wall, FRenderState &state, int rflags) -{ - int tmode = state.GetTextureMode(); - int rel = wall->rellight + getExtraLight(); - - if (wall->flags & GLWall::GLWF_GLOW) - { - state.EnableGlow(true); - state.SetGlowParams(wall->topglowcolor, wall->bottomglowcolor); - } - state.SetGlowPlanes(wall->topplane, wall->bottomplane); - state.SetMaterial(wall->gltexture, wall->flags & 3, 0, -1); - - if (wall->type == RENDERWALL_M2SNF) - { - if (wall->flags & GLWall::GLWF_CLAMPY) - { - if (tmode == TM_NORMAL) state.SetTextureMode(TM_CLAMPY); - } - SetFog(255, 0, nullptr, false); - } - state.SetObjectColor(wall->seg->frontsector->SpecialColors[sector_t::walltop] | 0xff000000); - state.SetObjectColor2(wall->seg->frontsector->SpecialColors[sector_t::wallbottom] | 0xff000000); - - float absalpha = fabsf(wall->alpha); - if (wall->lightlist == nullptr) - { - if (wall->type != RENDERWALL_M2SNF) SetFog(wall->lightlevel, rel, &wall->Colormap, wall->RenderStyle == STYLE_Add); - SetColor(wall->lightlevel, rel, wall->Colormap, absalpha); - RenderWall(wall, state, rflags); - } - else - { - state.EnableSplit(true); - - for (unsigned i = 0; i < wall->lightlist->Size(); i++) - { - 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(wall->vertexes[0]); - float low2 = lowplane.ZatPoint(wall->vertexes[1]); - - if (low1 < wall->ztop[0] || low2 < wall->ztop[1]) - { - int thisll = (*wall->lightlist)[i].caster != NULL ? hw_ClampLight(*(*wall->lightlist)[i].p_lightlevel) : wall->lightlevel; - FColormap thiscm; - thiscm.FadeColor = wall->Colormap.FadeColor; - thiscm.FogDensity = wall->Colormap.FogDensity; - thiscm.CopyFrom3DLight(&(*wall->lightlist)[i]); - state.SetColor(thisll, rel, false, thiscm, absalpha); - if (wall->type != RENDERWALL_M2SNF) state.SetFog(thisll, rel, false, &thiscm, wall->RenderStyle == STYLE_Add); - state.SetSplitPlanes((*wall->lightlist)[i].plane, lowplane); - RenderWall(wall, state, rflags); - } - if (low1 <= wall->zbottom[0] && low2 <= wall->zbottom[1]) break; - } - - state.EnableSplit(false); - } - state.SetObjectColor(0xffffffff); - state.SetObjectColor2(0); - state.SetTextureMode(tmode); - state.EnableGlow(false); -} - -//========================================================================== -// -// -// -//========================================================================== - -void FDrawInfo::RenderTranslucentWall(GLWall *wall, FRenderState &state) -{ - state.SetRenderStyle(wall->RenderStyle); - if (wall->gltexture) - { - if (!wall->gltexture->tex->GetTranslucency()) state.AlphaFunc(Alpha_GEqual, gl_mask_threshold); - else state.AlphaFunc(Alpha_GEqual, 0.f); - RenderTexturedWall(wall, state, GLWall::RWF_TEXTURED | GLWall::RWF_NOSPLIT); - } - else - { - state.AlphaFunc(Alpha_GEqual, 0.f); - state.SetColor(wall->lightlevel, 0, false, wall->Colormap, fabsf(wall->alpha)); - state.SetFog(wall->lightlevel, 0, false, &wall->Colormap, wall->RenderStyle == STYLE_Add); - state.EnableTexture(false); - RenderWall(wall, state, GLWall::RWF_NOSPLIT); - state.EnableTexture(true); - } - state.SetRenderStyle(STYLE_Translucent); -} - -//========================================================================== -// -// -// -//========================================================================== -void FDrawInfo::DrawWall(GLWall *wall, int pass) -{ - FRenderState &state = gl_RenderState; - if (screen->BuffersArePersistent()) - { - if (level.HasDynamicLights && !isFullbrightScene() && wall->gltexture != nullptr) - { - wall->SetupLights(this, lightdata); - } - wall->MakeVertices(this, !!(wall->flags & GLWall::GLWF_TRANSLUCENT)); - } - - gl_RenderState.SetNormal(wall->glseg.Normal()); - switch (pass) - { - case GLPASS_ALL: - RenderTexturedWall(wall, state, GLWall::RWF_TEXTURED); - break; - - case GLPASS_TRANSLUCENT: - - switch (wall->type) - { - case RENDERWALL_MIRRORSURFACE: - RenderMirrorSurface(wall, state); - break; - - case RENDERWALL_FOGBOUNDARY: - RenderFogBoundary(wall, state); - break; - - default: - RenderTranslucentWall(wall, state); - break; - } - break; - } -} - //========================================================================== // // diff --git a/src/hwrenderer/scene/hw_decal.cpp b/src/hwrenderer/scene/hw_decal.cpp index 5694a038c..d534d15e8 100644 --- a/src/hwrenderer/scene/hw_decal.cpp +++ b/src/hwrenderer/scene/hw_decal.cpp @@ -132,6 +132,7 @@ void GLDecal::DrawDecal(HWDrawInfo *di, FRenderState &state) void HWDrawInfo::DrawDecals(FRenderState &state, TArray &decals) { side_t *wall = nullptr; + SetDepthMask(false); state.SetDepthBias(-1, -128); for (auto gldecal : decals) { @@ -153,6 +154,7 @@ void HWDrawInfo::DrawDecals(FRenderState &state, TArray &decals) state.EnableSplit(false); state.ClearDepthBias(); state.SetTextureMode(TM_NORMAL); + SetDepthMask(true); } //========================================================================== diff --git a/src/hwrenderer/scene/hw_drawinfo.cpp b/src/hwrenderer/scene/hw_drawinfo.cpp index 05f5830a1..fe6918f3a 100644 --- a/src/hwrenderer/scene/hw_drawinfo.cpp +++ b/src/hwrenderer/scene/hw_drawinfo.cpp @@ -33,6 +33,7 @@ #include "hw_fakeflat.h" #include "hw_drawinfo.h" #include "hw_portal.h" +#include "hw_drawlist.h" #include "hwrenderer/utility/hw_clock.h" #include "hwrenderer/utility/hw_cvars.h" @@ -94,6 +95,9 @@ void HWDrawInfo::ClearBuffers() memset(&ss_renderflags[0], 0, level.subsectors.Size() * sizeof(ss_renderflags[0])); memset(&no_renderflags[0], 0, level.nodes.Size() * sizeof(no_renderflags[0])); + Decals[0].Clear(); + Decals[1].Clear(); + mClipPortal = nullptr; mCurrentPortal = nullptr; } @@ -282,3 +286,17 @@ void HWViewpointUniforms::SetDefaults() mShadowmapFilter = gl_shadowmap_filter; } + +//----------------------------------------------------------------------------- +// +// +// +//----------------------------------------------------------------------------- + +GLDecal *HWDrawInfo::AddDecal(bool onmirror) +{ + auto decal = (GLDecal*)RenderDataAllocator.Alloc(sizeof(GLDecal)); + Decals[onmirror ? 1 : 0].Push(decal); + return decal; +} + diff --git a/src/hwrenderer/scene/hw_drawinfo.h b/src/hwrenderer/scene/hw_drawinfo.h index 9782cc1b9..586300ddc 100644 --- a/src/hwrenderer/scene/hw_drawinfo.h +++ b/src/hwrenderer/scene/hw_drawinfo.h @@ -16,6 +16,13 @@ enum EDrawType DT_TriangleStrip = 4 }; +enum EDepthFunc +{ + DF_Less, + DF_LEqual, + DF_Always +}; + struct FSectorPortalGroup; struct FLinePortalSpan; struct FFlatVertex; @@ -130,6 +137,7 @@ struct HWDrawInfo FRenderViewpoint Viewpoint; HWViewpointUniforms VPUniforms; // per-viewpoint uniform state TArray Portals; + TArray Decals[2]; // the second slot is for mirrors which get rendered in a separate pass. TArray MissingUpperTextures; TArray MissingLowerTextures; @@ -286,7 +294,6 @@ public: void DrawDecals(FRenderState &state, TArray &decals); - virtual void DrawWall(GLWall *wall, int pass) = 0; virtual void DrawSprite(GLSprite *sprite, int pass) = 0; void ProcessLowerMinisegs(TArray &lowersegs); @@ -303,7 +310,7 @@ public: virtual void ApplyVPUniforms() = 0; virtual bool SetDepthClamp(bool on) = 0; - virtual GLDecal *AddDecal(bool onmirror) = 0; + GLDecal *AddDecal(bool onmirror); virtual std::pair AllocVertices(unsigned int count) = 0; virtual void Draw(EDrawType dt, FRenderState &state, int index, int count, bool apply = true) = 0; @@ -311,6 +318,7 @@ public: // Immediate render state change commands. These only change infrequently and should not clutter the render state. virtual void SetDepthMask(bool on) = 0; + virtual void SetDepthFunc(int func) = 0; virtual void EnableDrawBufferAttachments(bool on) = 0; }; diff --git a/src/hwrenderer/scene/hw_drawlist.cpp b/src/hwrenderer/scene/hw_drawlist.cpp index aab639bdb..0b5d676b4 100644 --- a/src/hwrenderer/scene/hw_drawlist.cpp +++ b/src/hwrenderer/scene/hw_drawlist.cpp @@ -788,7 +788,7 @@ void HWDrawList::DoDraw(HWDrawInfo *di, FRenderState &state, bool translucent, i { GLWall * w= walls[drawitems[i].index]; RenderWall.Clock(); - di->DrawWall(w, pass); + w->DrawWall(di, state, translucent); RenderWall.Unclock(); } break; @@ -822,12 +822,12 @@ void HWDrawList::Draw(HWDrawInfo *di, FRenderState &state, bool translucent, int // // //========================================================================== -void HWDrawList::DrawWalls(HWDrawInfo *di, int pass) +void HWDrawList::DrawWalls(HWDrawInfo *di, FRenderState &state, bool translucent) { RenderWall.Clock(); for (auto &item : drawitems) { - di->DrawWall(walls[item.index], pass); + walls[item.index]->DrawWall(di, state, translucent); } RenderWall.Unclock(); } diff --git a/src/hwrenderer/scene/hw_drawlist.h b/src/hwrenderer/scene/hw_drawlist.h index bfab10371..ebda38095 100644 --- a/src/hwrenderer/scene/hw_drawlist.h +++ b/src/hwrenderer/scene/hw_drawlist.h @@ -105,7 +105,7 @@ public: void DoDraw(HWDrawInfo *di, FRenderState &state, bool translucent, int pass, int i, bool trans); void Draw(HWDrawInfo *di, FRenderState &state, bool translucent, int pass, bool trans = false); - void DrawWalls(HWDrawInfo *di, int pass); + void DrawWalls(HWDrawInfo *di, FRenderState &state, bool translucent); void DrawFlats(HWDrawInfo *di, FRenderState &state, bool translucent); HWDrawList * next; diff --git a/src/hwrenderer/scene/hw_drawstructs.h b/src/hwrenderer/scene/hw_drawstructs.h index 4e99c7515..4d4b2df68 100644 --- a/src/hwrenderer/scene/hw_drawstructs.h +++ b/src/hwrenderer/scene/hw_drawstructs.h @@ -263,6 +263,13 @@ public: int CountVertices(); + void RenderWall(HWDrawInfo *di, FRenderState &state, int textured); + void RenderFogBoundary(HWDrawInfo *di, FRenderState &state); + void RenderMirrorSurface(HWDrawInfo *di, FRenderState &state); + void RenderTexturedWall(HWDrawInfo *di, FRenderState &state, int rflags); + void RenderTranslucentWall(HWDrawInfo *di, FRenderState &state); + void DrawDecalsForMirror(HWDrawInfo *di, FRenderState &state, TArray &decals); + public: GLWall() {} @@ -285,7 +292,7 @@ public: return -((y-glseg.y1)*(glseg.x2-glseg.x1)-(x-glseg.x1)*(glseg.y2-glseg.y1)); } - void DrawDecalsForMirror(HWDrawInfo *di, FRenderState &state, TArray &decals); + void DrawWall(HWDrawInfo *di, FRenderState &state, bool translucent); }; diff --git a/src/hwrenderer/scene/hw_walls.cpp b/src/hwrenderer/scene/hw_walls.cpp index 87fbf38ea..96fe46d2d 100644 --- a/src/hwrenderer/scene/hw_walls.cpp +++ b/src/hwrenderer/scene/hw_walls.cpp @@ -38,7 +38,227 @@ #include "hwrenderer/scene/hw_drawinfo.h" #include "hwrenderer/scene/hw_drawstructs.h" #include "hwrenderer/scene/hw_portal.h" +#include "hw_renderstate.h" +//========================================================================== +// +// General purpose wall rendering function +// everything goes through here +// +//========================================================================== + +void GLWall::RenderWall(HWDrawInfo *di, FRenderState &state, int textured) +{ + assert(vertcount > 0); + state.SetLightIndex(dynlightindex); + di->Draw(DT_TriangleFan, state, vertindex, vertcount); + vertexcount += vertcount; +} + +//========================================================================== +// +// +// +//========================================================================== + +void GLWall::RenderFogBoundary(HWDrawInfo *di, FRenderState &state) +{ + if (gl_fogmode && !di->isFullbrightScene()) + { + int rel = rellight + getExtraLight(); + di->EnableDrawBufferAttachments(false); + state.SetFog(lightlevel, rel, false, &Colormap, false); + state.SetEffect(EFF_FOGBOUNDARY); + state.AlphaFunc(Alpha_GEqual, 0.f); + state.SetDepthBias(-1, -128); + RenderWall(di, state, GLWall::RWF_BLANK); + state.ClearDepthBias(); + state.SetEffect(EFF_NONE); + di->EnableDrawBufferAttachments(true); + } +} + + +//========================================================================== +// +// +// +//========================================================================== +void GLWall::RenderMirrorSurface(HWDrawInfo *di, FRenderState &state) +{ + if (!TexMan.mirrorTexture.isValid()) return; + + di->SetDepthFunc(DF_LEqual); + + // 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. + state.EnableTextureMatrix(true); + + // Use sphere mapping for this + state.SetEffect(EFF_SPHEREMAP); + state.SetColor(lightlevel, 0, di->isFullbrightScene(), Colormap, 0.1f); + state.SetFog(lightlevel, 0, di->isFullbrightScene(), &Colormap, true); + state.SetRenderStyle(STYLE_Add); + state.AlphaFunc(Alpha_Greater, 0); + + FMaterial * pat = FMaterial::ValidateTexture(TexMan.mirrorTexture, false, false); + state.SetMaterial(pat, CLAMP_NONE, 0, -1); + + flags &= ~GLWall::GLWF_GLOW; + RenderWall(di, state, GLWall::RWF_BLANK); + + state.EnableTextureMatrix(false); + state.SetEffect(EFF_NONE); + state.AlphaFunc(Alpha_GEqual, gl_mask_sprite_threshold); + + di->SetDepthFunc(DF_Less); + + // This is drawn in the translucent pass which is done after the decal pass + // As a result the decals have to be drawn here, right after the wall they are on, + // because the depth buffer won't get set by translucent items. + if (seg->sidedef->AttachedDecals) + { + DrawDecalsForMirror(di, state, di->Decals[1]); + } + state.SetRenderStyle(STYLE_Translucent); +} + +//========================================================================== +// +// +// +//========================================================================== + +void GLWall::RenderTexturedWall(HWDrawInfo *di, FRenderState &state, int rflags) +{ + int tmode = state.GetTextureMode(); + int rel = rellight + getExtraLight(); + + if (flags & GLWall::GLWF_GLOW) + { + state.EnableGlow(true); + state.SetGlowParams(topglowcolor, bottomglowcolor); + } + state.SetGlowPlanes(topplane, bottomplane); + state.SetMaterial(gltexture, flags & 3, 0, -1); + + if (type == RENDERWALL_M2SNF) + { + if (flags & GLWall::GLWF_CLAMPY) + { + if (tmode == TM_NORMAL) state.SetTextureMode(TM_CLAMPY); + } + state.SetFog(255, 0, di->isFullbrightScene(), nullptr, false); + } + state.SetObjectColor(seg->frontsector->SpecialColors[sector_t::walltop] | 0xff000000); + state.SetObjectColor2(seg->frontsector->SpecialColors[sector_t::wallbottom] | 0xff000000); + + float absalpha = fabsf(alpha); + if (lightlist == nullptr) + { + if (type != RENDERWALL_M2SNF) state.SetFog(lightlevel, rel, di->isFullbrightScene(), &Colormap, RenderStyle == STYLE_Add); + state.SetColor(lightlevel, rel, di->isFullbrightScene(), Colormap, absalpha); + RenderWall(di, state, rflags); + } + else + { + state.EnableSplit(true); + + for (unsigned i = 0; i < lightlist->Size(); i++) + { + secplane_t &lowplane = i == (*lightlist).Size() - 1 ? bottomplane : (*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]); + + if (low1 < ztop[0] || low2 < ztop[1]) + { + int thisll = (*lightlist)[i].caster != NULL ? hw_ClampLight(*(*lightlist)[i].p_lightlevel) : lightlevel; + FColormap thiscm; + thiscm.FadeColor = Colormap.FadeColor; + thiscm.FogDensity = Colormap.FogDensity; + thiscm.CopyFrom3DLight(&(*lightlist)[i]); + state.SetColor(thisll, rel, false, thiscm, absalpha); + if (type != RENDERWALL_M2SNF) state.SetFog(thisll, rel, false, &thiscm, RenderStyle == STYLE_Add); + state.SetSplitPlanes((*lightlist)[i].plane, lowplane); + RenderWall(di, state, rflags); + } + if (low1 <= zbottom[0] && low2 <= zbottom[1]) break; + } + + state.EnableSplit(false); + } + state.SetObjectColor(0xffffffff); + state.SetObjectColor2(0); + state.SetTextureMode(tmode); + state.EnableGlow(false); +} + +//========================================================================== +// +// +// +//========================================================================== + +void GLWall::RenderTranslucentWall(HWDrawInfo *di, FRenderState &state) +{ + state.SetRenderStyle(RenderStyle); + if (gltexture) + { + if (!gltexture->tex->GetTranslucency()) state.AlphaFunc(Alpha_GEqual, gl_mask_threshold); + else state.AlphaFunc(Alpha_GEqual, 0.f); + RenderTexturedWall(di, state, GLWall::RWF_TEXTURED | GLWall::RWF_NOSPLIT); + } + else + { + state.AlphaFunc(Alpha_GEqual, 0.f); + state.SetColor(lightlevel, 0, false, Colormap, fabsf(alpha)); + state.SetFog(lightlevel, 0, false, &Colormap, RenderStyle == STYLE_Add); + state.EnableTexture(false); + RenderWall(di, state, GLWall::RWF_NOSPLIT); + state.EnableTexture(true); + } + state.SetRenderStyle(STYLE_Translucent); +} + +//========================================================================== +// +// +// +//========================================================================== +void GLWall::DrawWall(HWDrawInfo *di, FRenderState &state, bool translucent) +{ + if (screen->BuffersArePersistent()) + { + if (level.HasDynamicLights && !di->isFullbrightScene() && gltexture != nullptr) + { + SetupLights(di, lightdata); + } + MakeVertices(di, !!(flags & GLWall::GLWF_TRANSLUCENT)); + } + + state.SetNormal(glseg.Normal()); + if (!translucent) + { + RenderTexturedWall(di, state, GLWall::RWF_TEXTURED); + } + else + { + switch (type) + { + case RENDERWALL_MIRRORSURFACE: + RenderMirrorSurface(di, state); + break; + + case RENDERWALL_FOGBOUNDARY: + RenderFogBoundary(di, state); + break; + + default: + RenderTranslucentWall(di, state); + break; + } + } +} //========================================================================== //