- made wall draw code API independent.

This commit is contained in:
Christoph Oelckers 2018-10-21 13:53:50 +02:00
commit 8ffeb7812f
12 changed files with 275 additions and 264 deletions

View file

@ -132,6 +132,7 @@ void GLDecal::DrawDecal(HWDrawInfo *di, FRenderState &state)
void HWDrawInfo::DrawDecals(FRenderState &state, TArray<GLDecal *> &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<GLDecal *> &decals)
state.EnableSplit(false);
state.ClearDepthBias();
state.SetTextureMode(TM_NORMAL);
SetDepthMask(true);
}
//==========================================================================

View file

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

View file

@ -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<IPortal *> Portals;
TArray<GLDecal *> Decals[2]; // the second slot is for mirrors which get rendered in a separate pass.
TArray<MissingTextureInfo> MissingUpperTextures;
TArray<MissingTextureInfo> MissingLowerTextures;
@ -286,7 +294,6 @@ public:
void DrawDecals(FRenderState &state, TArray<GLDecal *> &decals);
virtual void DrawWall(GLWall *wall, int pass) = 0;
virtual void DrawSprite(GLSprite *sprite, int pass) = 0;
void ProcessLowerMinisegs(TArray<seg_t *> &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<FFlatVertex *, unsigned int> 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;
};

View file

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

View file

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

View file

@ -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<GLDecal *> &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<GLDecal *> &decals);
void DrawWall(HWDrawInfo *di, FRenderState &state, bool translucent);
};

View file

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