- moved sprite drawer to hwrenderer as well.

This commit is contained in:
Christoph Oelckers 2018-10-21 17:50:01 +02:00
parent 346a9ce149
commit 3775c4756e
11 changed files with 281 additions and 340 deletions

View file

@ -821,7 +821,6 @@ set( FASTMATH_SOURCES
textures/hires/xbr/xbrz.cpp textures/hires/xbr/xbrz.cpp
textures/hires/xbr/xbrz_old.cpp textures/hires/xbr/xbrz_old.cpp
gl/scene/gl_drawinfo.cpp gl/scene/gl_drawinfo.cpp
gl/scene/gl_sprite.cpp
gl/scene/gl_skydome.cpp gl/scene/gl_skydome.cpp
gl/scene/gl_weapon.cpp gl/scene/gl_weapon.cpp
gl/scene/gl_scene.cpp gl/scene/gl_scene.cpp

View file

@ -41,6 +41,7 @@
#include "gl/scene/gl_portal.h" #include "gl/scene/gl_portal.h"
#include "gl/renderer/gl_renderstate.h" #include "gl/renderer/gl_renderstate.h"
#include "gl/dynlights/gl_lightbuffer.h" #include "gl/dynlights/gl_lightbuffer.h"
#include "gl/models/gl_models.h"
class FDrawInfoList class FDrawInfoList
{ {
@ -90,13 +91,13 @@ void FDrawInfo::DoDrawSorted(HWDrawList *dl, SortNode * head)
DoDrawSorted(dl, head->left); DoDrawSorted(dl, head->left);
gl_RenderState.SetClipSplit(clipsplit); gl_RenderState.SetClipSplit(clipsplit);
} }
dl->DoDraw(this, gl_RenderState, true, GLPASS_TRANSLUCENT, head->itemindex, true); dl->DoDraw(this, gl_RenderState, true, head->itemindex);
if (head->equal) if (head->equal)
{ {
SortNode * ehead=head->equal; SortNode * ehead=head->equal;
while (ehead) while (ehead)
{ {
dl->DoDraw(this, gl_RenderState, true, GLPASS_TRANSLUCENT, ehead->itemindex, true); dl->DoDraw(this, gl_RenderState, true, ehead->itemindex);
ehead=ehead->equal; ehead=ehead->equal;
} }
} }
@ -298,6 +299,12 @@ void FDrawInfo::DrawIndexed(EDrawType dt, FRenderState &state, int index, int co
drawcalls.Unclock(); drawcalls.Unclock();
} }
void FDrawInfo::DrawModel(GLSprite *spr, FRenderState &state)
{
FGLModelRenderer renderer(this, spr->dynlightindex);
renderer.RenderModel(spr->x, spr->y, spr->z, spr->modelframe, spr->actor, Viewpoint.TicFrac);
}
void FDrawInfo::SetDepthMask(bool on) void FDrawInfo::SetDepthMask(bool on)
{ {
glDepthMask(on); glDepthMask(on);
@ -357,3 +364,26 @@ void FDrawInfo::AddFlat(GLFlat *flat, bool fog)
*newflat = *flat; *newflat = *flat;
} }
//==========================================================================
//
//
//
//==========================================================================
void FDrawInfo::AddSprite(GLSprite *sprite, bool translucent)
{
int list;
// [BB] Allow models to be drawn in the GLDL_TRANSLUCENT pass.
if (translucent || sprite->actor == nullptr || (!sprite->modelframe && (sprite->actor->renderflags & RF_SPRITETYPEMASK) != RF_WALLSPRITE))
{
list = GLDL_TRANSLUCENT;
}
else
{
list = GLDL_MODELS;
}
auto newsprt = drawlists[list].NewSprite();
*newsprt = *sprite;
}

View file

@ -26,11 +26,6 @@ enum DrawListType
GLDL_TYPES, GLDL_TYPES,
}; };
enum Drawpasses
{
GLPASS_ALL, // Main pass with dynamic lights
GLPASS_TRANSLUCENT, // Draws translucent objects
};
struct FDrawInfo : public HWDrawInfo struct FDrawInfo : public HWDrawInfo
{ {
@ -52,14 +47,14 @@ struct FDrawInfo : public HWDrawInfo
void Draw(EDrawType dt, FRenderState &state, int index, int count, bool apply = true) override; 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 DrawIndexed(EDrawType dt, FRenderState &state, int index, int count, bool apply = true) override;
void DrawModel(GLSprite *spr, FRenderState &state) override;
void SetDepthMask(bool on) override; void SetDepthMask(bool on) override;
void SetDepthFunc(int func) override; void SetDepthFunc(int func) override;
void EnableDrawBufferAttachments(bool on) override; void EnableDrawBufferAttachments(bool on) override;
void StartScene(); void StartScene();
// Sprite drawer
void DrawSprite(GLSprite *sprite, int pass);
void DrawPSprite(HUDSprite *huds); void DrawPSprite(HUDSprite *huds);
void DrawPlayerSprites(bool hudModelStep); void DrawPlayerSprites(bool hudModelStep);

View file

@ -168,8 +168,6 @@ void FDrawInfo::RenderScene(int recursion)
gl_RenderState.AlphaFunc(Alpha_GEqual, 0.f); gl_RenderState.AlphaFunc(Alpha_GEqual, 0.f);
glDisable(GL_POLYGON_OFFSET_FILL); glDisable(GL_POLYGON_OFFSET_FILL);
int pass = GLPASS_ALL;
gl_RenderState.EnableTexture(gl_texture); gl_RenderState.EnableTexture(gl_texture);
gl_RenderState.EnableBrightmap(true); gl_RenderState.EnableBrightmap(true);
drawlists[GLDL_PLAINWALLS].DrawWalls(this, gl_RenderState, false); drawlists[GLDL_PLAINWALLS].DrawWalls(this, gl_RenderState, false);
@ -189,7 +187,7 @@ void FDrawInfo::RenderScene(int recursion)
gl_RenderState.ClearDepthBias(); gl_RenderState.ClearDepthBias();
} }
drawlists[GLDL_MODELS].Draw(this, gl_RenderState, false, pass); drawlists[GLDL_MODELS].Draw(this, gl_RenderState, false);
gl_RenderState.SetRenderStyle(STYLE_Translucent); gl_RenderState.SetRenderStyle(STYLE_Translucent);
@ -215,7 +213,7 @@ void FDrawInfo::RenderTranslucent()
gl_RenderState.SetRenderStyle(STYLE_Translucent); gl_RenderState.SetRenderStyle(STYLE_Translucent);
gl_RenderState.EnableBrightmap(true); gl_RenderState.EnableBrightmap(true);
drawlists[GLDL_TRANSLUCENTBORDER].Draw(this, gl_RenderState, true, GLPASS_TRANSLUCENT); drawlists[GLDL_TRANSLUCENTBORDER].Draw(this, gl_RenderState, true);
glDepthMask(false); glDepthMask(false);
DrawSorted(GLDL_TRANSLUCENT); DrawSorted(GLDL_TRANSLUCENT);
gl_RenderState.EnableBrightmap(false); gl_RenderState.EnableBrightmap(false);

View file

@ -1,316 +0,0 @@
//
//---------------------------------------------------------------------------
//
// Copyright(C) 2002-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_sprite.cpp
** Sprite/Particle rendering
**
*/
#include "gl_load/gl_system.h"
#include "p_local.h"
#include "p_effect.h"
#include "g_level.h"
#include "doomstat.h"
#include "r_defs.h"
#include "r_sky.h"
#include "r_utility.h"
#include "a_pickups.h"
#include "d_player.h"
#include "g_levellocals.h"
#include "events.h"
#include "actorinlines.h"
#include "r_data/r_vanillatrans.h"
#include "gl_load/gl_interface.h"
#include "hwrenderer/utility/hw_cvars.h"
#include "hwrenderer/scene/hw_drawstructs.h"
#include "gl/renderer/gl_renderstate.h"
#include "gl/renderer/gl_renderer.h"
#include "gl/scene/gl_drawinfo.h"
#include "gl/models/gl_models.h"
#include "gl/dynlights/gl_lightbuffer.h"
#include "hwrenderer/utility/hw_lighting.h"
extern uint32_t r_renderercaps;
//==========================================================================
//
//
//
//==========================================================================
void FDrawInfo::DrawSprite(GLSprite *sprite, int pass)
{
auto RenderStyle = sprite->RenderStyle;
bool additivefog = false;
bool foglayer = false;
int rel = sprite->fullbright? 0 : getExtraLight();
auto &vp = Viewpoint;
if (pass==GLPASS_TRANSLUCENT)
{
// The translucent pass requires special setup for the various modes.
// for special render styles brightmaps would not look good - especially for subtractive.
if (RenderStyle.BlendOp != STYLEOP_Add)
{
gl_RenderState.EnableBrightmap(false);
}
// Optionally use STYLE_ColorBlend in place of STYLE_Add for fullbright items.
if (RenderStyle == LegacyRenderStyles[STYLE_Add] && sprite->trans > 1.f - FLT_EPSILON &&
gl_usecolorblending && !isFullbrightScene() && sprite->actor &&
sprite->fullbright && sprite->gltexture && !sprite->gltexture->tex->GetTranslucency())
{
RenderStyle = LegacyRenderStyles[STYLE_ColorBlend];
}
gl_RenderState.SetRenderStyle(RenderStyle);
gl_RenderState.SetTextureMode(RenderStyle);
if (sprite->hw_styleflags == STYLEHW_NoAlphaTest)
{
gl_RenderState.AlphaFunc(Alpha_GEqual, 0.f);
}
else
{
gl_RenderState.AlphaFunc(Alpha_GEqual, gl_mask_sprite_threshold);
}
if (RenderStyle.BlendOp == STYLEOP_Shadow)
{
float fuzzalpha=0.44f;
float minalpha=0.1f;
// fog + fuzz don't work well without some fiddling with the alpha value!
if (!sprite->Colormap.FadeColor.isBlack())
{
float dist=Dist2(vp.Pos.X, vp.Pos.Y, sprite->x, sprite->y);
int fogd = hw_GetFogDensity(sprite->lightlevel, sprite->Colormap.FadeColor, sprite->Colormap.FogDensity, sprite->Colormap.BlendFactor);
// this value was determined by trial and error and is scale dependent!
float factor = 0.05f + exp(-fogd*dist / 62500.f);
fuzzalpha*=factor;
minalpha*=factor;
}
gl_RenderState.AlphaFunc(Alpha_GEqual, gl_mask_sprite_threshold);
gl_RenderState.SetColor(0.2f,0.2f,0.2f,fuzzalpha, sprite->Colormap.Desaturation);
additivefog = true;
sprite->lightlist = nullptr; // the fuzz effect does not use the sector's light level so splitting is not needed.
}
else if (RenderStyle.BlendOp == STYLEOP_Add && RenderStyle.DestAlpha == STYLEALPHA_One)
{
additivefog = true;
}
}
else if (sprite->modelframe == nullptr)
{
// This still needs to set the texture mode. As blend mode it will always use GL_ONE/GL_ZERO
gl_RenderState.SetTextureMode(RenderStyle);
gl_RenderState.SetDepthBias(-1, -128);
}
if (RenderStyle.BlendOp != STYLEOP_Shadow)
{
if (level.HasDynamicLights && !isFullbrightScene() && !sprite->fullbright)
{
if ( sprite->dynlightindex == -1) // only set if we got no light buffer index. This covers all cases where sprite lighting is used.
{
float out[3];
GetDynSpriteLight(gl_light_sprites ? sprite->actor : nullptr, gl_light_particles ? sprite->particle : nullptr, out);
gl_RenderState.SetDynLight(out[0], out[1], out[2]);
}
}
sector_t *cursec = sprite->actor ? sprite->actor->Sector : sprite->particle ? sprite->particle->subsector->sector : nullptr;
if (cursec != nullptr)
{
const PalEntry finalcol = sprite->fullbright
? sprite->ThingColor
: sprite->ThingColor.Modulate(cursec->SpecialColors[sector_t::sprites]);
gl_RenderState.SetObjectColor(finalcol);
}
SetColor(sprite->lightlevel, rel, sprite->Colormap, sprite->trans);
}
if (sprite->Colormap.FadeColor.isBlack()) sprite->foglevel = sprite->lightlevel;
if (RenderStyle.Flags & STYLEF_FadeToBlack)
{
sprite->Colormap.FadeColor=0;
additivefog = true;
}
if (RenderStyle.BlendOp == STYLEOP_RevSub || RenderStyle.BlendOp == STYLEOP_Sub)
{
if (!sprite->modelframe)
{
// non-black fog with subtractive style needs special treatment
if (!sprite->Colormap.FadeColor.isBlack())
{
foglayer = true;
// Due to the two-layer approach we need to force an alpha test that lets everything pass
gl_RenderState.AlphaFunc(Alpha_Greater, 0);
}
}
else RenderStyle.BlendOp = STYLEOP_Fuzz; // subtractive with models is not going to work.
}
if (!foglayer) SetFog(sprite->foglevel, rel, &sprite->Colormap, additivefog);
else
{
gl_RenderState.EnableFog(false);
gl_RenderState.SetFog(0, 0);
}
if (sprite->gltexture) gl_RenderState.ApplyMaterial(sprite->gltexture, CLAMP_XY, sprite->translation, sprite->OverrideShader);
else if (!sprite->modelframe) gl_RenderState.EnableTexture(false);
//SetColor(lightlevel, rel, Colormap, trans);
unsigned int iter = sprite->lightlist? sprite->lightlist->Size() : 1;
bool clipping = false;
auto lightlist = sprite->lightlist;
if (lightlist || sprite->topclip != LARGE_VALUE || sprite->bottomclip != -LARGE_VALUE)
{
clipping = true;
gl_RenderState.EnableSplit(true);
}
secplane_t bottomp = { { 0, 0, -1. }, sprite->bottomclip };
secplane_t topp = { { 0, 0, -1. }, sprite->topclip };
for (unsigned i = 0; i < iter; i++)
{
if (lightlist)
{
// set up the light slice
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 != nullptr ? hw_ClampLight(*(*lightlist)[i].p_lightlevel) : sprite->lightlevel;
int thisll = sprite->actor == nullptr? thislight : (uint8_t)sprite->actor->Sector->CheckSpriteGlow(thislight, sprite->actor->InterpolatedPosition(vp.TicFrac));
FColormap thiscm;
thiscm.CopyFog(sprite->Colormap);
thiscm.CopyFrom3DLight(&(*lightlist)[i]);
if (level.flags3 & LEVEL3_NOCOLOREDSPRITELIGHTING)
{
thiscm.Decolorize();
}
SetColor(thisll, rel, thiscm, sprite->trans);
if (!foglayer)
{
SetFog(thislight, rel, &thiscm, additivefog);
}
gl_RenderState.SetSplitPlanes(*topplane, *lowplane);
}
else if (clipping)
{
gl_RenderState.SetSplitPlanes(topp, bottomp);
}
if (!sprite->modelframe)
{
gl_RenderState.Apply();
gl_RenderState.SetNormal(0, 0, 0);
if (screen->BuffersArePersistent())
{
sprite->CreateVertices(this);
}
if (sprite->polyoffset)
{
gl_RenderState.SetDepthBias(-1, -128);
}
glDrawArrays(GL_TRIANGLE_STRIP, sprite->vertexindex, 4);
if (foglayer)
{
// If we get here we know that we have colored fog and no fixed colormap.
SetFog(sprite->foglevel, rel, &sprite->Colormap, additivefog);
gl_RenderState.SetTextureMode(TM_FOGLAYER);
gl_RenderState.SetRenderStyle(STYLE_Translucent);
gl_RenderState.Apply();
glDrawArrays(GL_TRIANGLE_STRIP, sprite->vertexindex, 4);
gl_RenderState.SetTextureMode(TM_NORMAL);
}
}
else
{
FGLModelRenderer renderer(this, sprite->dynlightindex);
renderer.RenderModel(sprite->x, sprite->y, sprite->z, sprite->modelframe, sprite->actor, vp.TicFrac);
}
}
if (clipping)
{
gl_RenderState.EnableSplit(false);
}
if (pass==GLPASS_TRANSLUCENT)
{
gl_RenderState.EnableBrightmap(true);
gl_RenderState.SetRenderStyle(STYLE_Translucent);
gl_RenderState.SetTextureMode(TM_NORMAL);
if (sprite->actor != nullptr && (sprite->actor->renderflags & RF_SPRITETYPEMASK) == RF_FLATSPRITE)
{
gl_RenderState.ClearDepthBias();
}
}
else if (sprite->modelframe == nullptr)
{
gl_RenderState.ClearDepthBias();
}
gl_RenderState.SetObjectColor(0xffffffff);
gl_RenderState.EnableTexture(true);
gl_RenderState.SetDynLight(0,0,0);
}
//==========================================================================
//
//
//
//==========================================================================
void FDrawInfo::AddSprite(GLSprite *sprite, bool translucent)
{
int list;
// [BB] Allow models to be drawn in the GLDL_TRANSLUCENT pass.
if (translucent || sprite->actor == nullptr || (!sprite->modelframe && (sprite->actor->renderflags & RF_SPRITETYPEMASK) != RF_WALLSPRITE))
{
list = GLDL_TRANSLUCENT;
}
else
{
list = GLDL_MODELS;
}
auto newsprt = drawlists[list].NewSprite();
*newsprt = *sprite;
}

View file

@ -30,7 +30,6 @@
#include "gl_load/gl_interface.h" #include "gl_load/gl_interface.h"
#include "hwrenderer/utility/hw_cvars.h" #include "hwrenderer/utility/hw_cvars.h"
#include "gl/renderer/gl_renderstate.h"
#include "gl/renderer/gl_renderer.h" #include "gl/renderer/gl_renderer.h"
#include "gl/data/gl_vertexbuffer.h" #include "gl/data/gl_vertexbuffer.h"
#include "gl/dynlights/gl_lightbuffer.h" #include "gl/dynlights/gl_lightbuffer.h"

View file

@ -294,8 +294,6 @@ public:
void DrawDecals(FRenderState &state, TArray<GLDecal *> &decals); void DrawDecals(FRenderState &state, TArray<GLDecal *> &decals);
virtual void DrawSprite(GLSprite *sprite, int pass) = 0;
void ProcessLowerMinisegs(TArray<seg_t *> &lowersegs); void ProcessLowerMinisegs(TArray<seg_t *> &lowersegs);
virtual void AddSubsectorToPortal(FSectorPortalGroup *portal, subsector_t *sub) = 0; virtual void AddSubsectorToPortal(FSectorPortalGroup *portal, subsector_t *sub) = 0;
@ -315,6 +313,9 @@ public:
virtual void Draw(EDrawType dt, FRenderState &state, int index, int count, bool apply = true) = 0; virtual void Draw(EDrawType dt, FRenderState &state, int index, int count, bool apply = true) = 0;
virtual void DrawIndexed(EDrawType dt, FRenderState &state, int index, int count, bool apply = true) = 0; virtual void DrawIndexed(EDrawType dt, FRenderState &state, int index, int count, bool apply = true) = 0;
virtual void DrawModel(GLSprite *spr, FRenderState &state) = 0;
// Immediate render state change commands. These only change infrequently and should not clutter the render state. // Immediate render state change commands. These only change infrequently and should not clutter the render state.
virtual void SetDepthMask(bool on) = 0; virtual void SetDepthMask(bool on) = 0;

View file

@ -771,7 +771,7 @@ GLSprite *HWDrawList::NewSprite()
// //
// //
//========================================================================== //==========================================================================
void HWDrawList::DoDraw(HWDrawInfo *di, FRenderState &state, bool translucent, int pass, int i, bool trans) void HWDrawList::DoDraw(HWDrawInfo *di, FRenderState &state, bool translucent, int i)
{ {
switch(drawitems[i].rendertype) switch(drawitems[i].rendertype)
{ {
@ -797,7 +797,7 @@ void HWDrawList::DoDraw(HWDrawInfo *di, FRenderState &state, bool translucent, i
{ {
GLSprite * s= sprites[drawitems[i].index]; GLSprite * s= sprites[drawitems[i].index];
RenderSprite.Clock(); RenderSprite.Clock();
di->DrawSprite(s, pass); s->DrawSprite(di, state, translucent);
RenderSprite.Unclock(); RenderSprite.Unclock();
} }
break; break;
@ -809,11 +809,11 @@ void HWDrawList::DoDraw(HWDrawInfo *di, FRenderState &state, bool translucent, i
// //
// //
//========================================================================== //==========================================================================
void HWDrawList::Draw(HWDrawInfo *di, FRenderState &state, bool translucent, int pass, bool trans) void HWDrawList::Draw(HWDrawInfo *di, FRenderState &state, bool translucent)
{ {
for (unsigned i = 0; i < drawitems.Size(); i++) for (unsigned i = 0; i < drawitems.Size(); i++)
{ {
DoDraw(di, state, translucent, pass, i, trans); DoDraw(di, state, translucent, i);
} }
} }

View file

@ -103,8 +103,8 @@ public:
SortNode * DoSort(HWDrawInfo *di, SortNode * head); SortNode * DoSort(HWDrawInfo *di, SortNode * head);
void Sort(HWDrawInfo *di); void Sort(HWDrawInfo *di);
void DoDraw(HWDrawInfo *di, FRenderState &state, bool translucent, int pass, int i, bool trans); void DoDraw(HWDrawInfo *di, FRenderState &state, bool translucent, int i);
void Draw(HWDrawInfo *di, FRenderState &state, bool translucent, int pass, bool trans = false); void Draw(HWDrawInfo *di, FRenderState &state, bool translucent);
void DrawWalls(HWDrawInfo *di, FRenderState &state, bool translucent); void DrawWalls(HWDrawInfo *di, FRenderState &state, bool translucent);
void DrawFlats(HWDrawInfo *di, FRenderState &state, bool translucent); void DrawFlats(HWDrawInfo *di, FRenderState &state, bool translucent);

View file

@ -401,12 +401,14 @@ public:
public: public:
GLSprite() {} GLSprite() = default;
void CreateVertices(HWDrawInfo *di); void CreateVertices(HWDrawInfo *di);
void PutSprite(HWDrawInfo *di, bool translucent); void PutSprite(HWDrawInfo *di, bool translucent);
void Process(HWDrawInfo *di, AActor* thing,sector_t * sector, area_t in_area, int thruportal = false); void Process(HWDrawInfo *di, AActor* thing,sector_t * sector, area_t in_area, int thruportal = false);
void ProcessParticle (HWDrawInfo *di, particle_t *particle, sector_t *sector);//, int shade, int fakeside) void ProcessParticle (HWDrawInfo *di, particle_t *particle, sector_t *sector);//, int shade, int fakeside)
void DrawSprite(HWDrawInfo *di, FRenderState &state, bool translucent);
GLSprite(const GLSprite &other) GLSprite(const GLSprite &other)
{ {
memcpy(this, &other, sizeof(GLSprite)); memcpy(this, &other, sizeof(GLSprite));

View file

@ -52,6 +52,7 @@
#include "hwrenderer/utility/hw_lighting.h" #include "hwrenderer/utility/hw_lighting.h"
#include "hwrenderer/textures/hw_material.h" #include "hwrenderer/textures/hw_material.h"
#include "hwrenderer/dynlights/hw_dynlightdata.h" #include "hwrenderer/dynlights/hw_dynlightdata.h"
#include "hw_renderstate.h"
extern TArray<spritedef_t> sprites; extern TArray<spritedef_t> sprites;
extern TArray<spriteframe_t> SpriteFrames; extern TArray<spriteframe_t> SpriteFrames;
@ -63,6 +64,238 @@ EXTERN_CVAR(Bool, r_debug_disable_vis_filter)
EXTERN_CVAR(Float, transsouls) EXTERN_CVAR(Float, transsouls)
//==========================================================================
//
//
//
//==========================================================================
void GLSprite::DrawSprite(HWDrawInfo *di, FRenderState &state, bool translucent)
{
bool additivefog = false;
bool foglayer = false;
int rel = fullbright ? 0 : getExtraLight();
auto &vp = di->Viewpoint;
if (translucent)
{
// The translucent pass requires special setup for the various modes.
// for special render styles brightmaps would not look good - especially for subtractive.
if (RenderStyle.BlendOp != STYLEOP_Add)
{
state.EnableBrightmap(false);
}
// Optionally use STYLE_ColorBlend in place of STYLE_Add for fullbright items.
if (RenderStyle == LegacyRenderStyles[STYLE_Add] && trans > 1.f - FLT_EPSILON &&
gl_usecolorblending && !di->isFullbrightScene() && actor &&
fullbright && gltexture && !gltexture->tex->GetTranslucency())
{
RenderStyle = LegacyRenderStyles[STYLE_ColorBlend];
}
state.SetRenderStyle(RenderStyle);
state.SetTextureMode(RenderStyle);
if (hw_styleflags == STYLEHW_NoAlphaTest)
{
state.AlphaFunc(Alpha_GEqual, 0.f);
}
else
{
state.AlphaFunc(Alpha_GEqual, gl_mask_sprite_threshold);
}
if (RenderStyle.BlendOp == STYLEOP_Shadow)
{
float fuzzalpha = 0.44f;
float minalpha = 0.1f;
// fog + fuzz don't work well without some fiddling with the alpha value!
if (!Colormap.FadeColor.isBlack())
{
float dist = Dist2(vp.Pos.X, vp.Pos.Y, x, y);
int fogd = hw_GetFogDensity(lightlevel, Colormap.FadeColor, Colormap.FogDensity, Colormap.BlendFactor);
// this value was determined by trial and error and is scale dependent!
float factor = 0.05f + exp(-fogd * dist / 62500.f);
fuzzalpha *= factor;
minalpha *= factor;
}
state.AlphaFunc(Alpha_GEqual, gl_mask_sprite_threshold);
state.SetColor(0.2f, 0.2f, 0.2f, fuzzalpha, Colormap.Desaturation);
additivefog = true;
lightlist = nullptr; // the fuzz effect does not use the sector's light level so splitting is not needed.
}
else if (RenderStyle.BlendOp == STYLEOP_Add && RenderStyle.DestAlpha == STYLEALPHA_One)
{
additivefog = true;
}
}
else if (modelframe == nullptr)
{
// This still needs to set the texture mode. As blend mode it will always use GL_ONE/GL_ZERO
state.SetTextureMode(RenderStyle);
state.SetDepthBias(-1, -128);
}
if (RenderStyle.BlendOp != STYLEOP_Shadow)
{
if (level.HasDynamicLights && !di->isFullbrightScene() && !fullbright)
{
if (dynlightindex == -1) // only set if we got no light buffer index. This covers all cases where sprite lighting is used.
{
float out[3];
di->GetDynSpriteLight(gl_light_sprites ? actor : nullptr, gl_light_particles ? particle : nullptr, out);
state.SetDynLight(out[0], out[1], out[2]);
}
}
sector_t *cursec = actor ? actor->Sector : particle ? particle->subsector->sector : nullptr;
if (cursec != nullptr)
{
const PalEntry finalcol = fullbright
? ThingColor
: ThingColor.Modulate(cursec->SpecialColors[sector_t::sprites]);
state.SetObjectColor(finalcol);
}
state.SetColor(lightlevel, rel, di->isFullbrightScene(), Colormap, trans);
}
if (Colormap.FadeColor.isBlack()) foglevel = lightlevel;
if (RenderStyle.Flags & STYLEF_FadeToBlack)
{
Colormap.FadeColor = 0;
additivefog = true;
}
if (RenderStyle.BlendOp == STYLEOP_RevSub || RenderStyle.BlendOp == STYLEOP_Sub)
{
if (!modelframe)
{
// non-black fog with subtractive style needs special treatment
if (!Colormap.FadeColor.isBlack())
{
foglayer = true;
// Due to the two-layer approach we need to force an alpha test that lets everything pass
state.AlphaFunc(Alpha_Greater, 0);
}
}
else RenderStyle.BlendOp = STYLEOP_Fuzz; // subtractive with models is not going to work.
}
if (!foglayer) state.SetFog(foglevel, rel, di->isFullbrightScene(), &Colormap, additivefog);
else
{
state.EnableFog(false);
state.SetFog(0, 0);
}
if (gltexture) state.SetMaterial(gltexture, CLAMP_XY, translation, OverrideShader);
else if (!modelframe) state.EnableTexture(false);
//SetColor(lightlevel, rel, Colormap, trans);
unsigned int iter = lightlist ? lightlist->Size() : 1;
bool clipping = false;
if (lightlist || topclip != LARGE_VALUE || bottomclip != -LARGE_VALUE)
{
clipping = true;
state.EnableSplit(true);
}
secplane_t bottomp = { { 0, 0, -1. }, bottomclip };
secplane_t topp = { { 0, 0, -1. }, topclip };
for (unsigned i = 0; i < iter; i++)
{
if (lightlist)
{
// set up the light slice
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 != nullptr ? hw_ClampLight(*(*lightlist)[i].p_lightlevel) : lightlevel;
int thisll = actor == nullptr ? thislight : (uint8_t)actor->Sector->CheckSpriteGlow(thislight, actor->InterpolatedPosition(vp.TicFrac));
FColormap thiscm;
thiscm.CopyFog(Colormap);
thiscm.CopyFrom3DLight(&(*lightlist)[i]);
if (level.flags3 & LEVEL3_NOCOLOREDSPRITELIGHTING)
{
thiscm.Decolorize();
}
state.SetColor(thisll, rel, di->isFullbrightScene(), thiscm, trans);
if (!foglayer)
{
state.SetFog(thislight, rel, di->isFullbrightScene(), &thiscm, additivefog);
}
state.SetSplitPlanes(*topplane, *lowplane);
}
else if (clipping)
{
state.SetSplitPlanes(topp, bottomp);
}
if (!modelframe)
{
state.SetNormal(0, 0, 0);
if (screen->BuffersArePersistent())
{
CreateVertices(di);
}
if (polyoffset)
{
state.SetDepthBias(-1, -128);
}
di->Draw(DT_TriangleStrip, state, vertexindex, 4);
if (foglayer)
{
// If we get here we know that we have colored fog and no fixed colormap.
state.SetFog(foglevel, rel, false, &Colormap, additivefog);
state.SetTextureMode(TM_FOGLAYER);
state.SetRenderStyle(STYLE_Translucent);
di->Draw(DT_TriangleStrip, state, vertexindex, 4);
state.SetTextureMode(TM_NORMAL);
}
}
else
{
di->DrawModel(this, state);
}
}
if (clipping)
{
state.EnableSplit(false);
}
if (translucent)
{
state.EnableBrightmap(true);
state.SetRenderStyle(STYLE_Translucent);
state.SetTextureMode(TM_NORMAL);
if (actor != nullptr && (actor->renderflags & RF_SPRITETYPEMASK) == RF_FLATSPRITE)
{
state.ClearDepthBias();
}
}
else if (modelframe == nullptr)
{
state.ClearDepthBias();
}
state.SetObjectColor(0xffffffff);
state.EnableTexture(true);
state.SetDynLight(0, 0, 0);
}
//========================================================================== //==========================================================================
// //
// //