Merge branch 'wallwork'

This commit is contained in:
Christoph Oelckers 2018-04-27 20:37:54 +02:00
commit 59477362d9
26 changed files with 606 additions and 602 deletions

View file

@ -813,7 +813,6 @@ set( FASTMATH_SOURCES
textures/hires/xbr/xbrz.cpp
textures/hires/xbr/xbrz_old.cpp
gl/scene/gl_bsp.cpp
gl/scene/gl_decal.cpp
gl/scene/gl_drawinfo.cpp
gl/scene/gl_flats.cpp
gl/scene/gl_sprite.cpp
@ -828,6 +827,7 @@ set( FASTMATH_SOURCES
gl_load/gl_load.c
hwrenderer/dynlights/hw_dynlightdata.cpp
hwrenderer/scene/hw_fakeflat.cpp
hwrenderer/scene/hw_decal.cpp
hwrenderer/scene/hw_clipper.cpp
hwrenderer/scene/hw_renderhacks.cpp
hwrenderer/scene/hw_walls.cpp

View file

@ -555,6 +555,7 @@ bool FDrawInfo::PutWallCompat(GLWall *wall, int passflag)
int list = list_indices[masked][foggy];
auto newwall = dldrawlists[list].NewWall();
*newwall = *wall;
if (!masked) newwall->ProcessDecals(this);
return true;
}

View file

@ -1,30 +0,0 @@
#ifndef __GL_COLORMAP
#define __GL_COLORMAP
#include "doomtype.h"
#include "v_palette.h"
#include "r_data/colormaps.h"
struct lightlist_t;
enum EColorManipulation
{
CM_SPECIAL2D = -3, // the special colormaps get passed as color pair from the 2D drawer so they need a different value here.
CM_PLAIN2D = -2, // regular 2D drawing.
CM_INVALID=-1,
CM_DEFAULT=0, // untranslated
CM_FIRSTSPECIALCOLORMAP, // first special fixed colormap
CM_FIRSTSPECIALCOLORMAPFORCED= 0x08000000, // first special fixed colormap, application forced (for 2D overlays)
CM_FOGLAYER = 0x10000000, // Sprite shaped fog layer
// These are not to be passed to the texture manager
CM_LITE = 0x20000000, // special values to handle these items without excessive hacking
CM_TORCH= 0x20000010, // These are not real color manipulations
};
#define CM_MAXCOLORMAP int(CM_FIRSTSPECIALCOLORMAP + SpecialColormaps.Size())
#define CM_MAXCOLORMAPFORCED int(CM_FIRSTSPECIALCOLORMAPFORCED + SpecialColormaps.Size())
#endif

View file

@ -1,397 +0,0 @@
//
//---------------------------------------------------------------------------
//
// Copyright(C) 2003-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_decal.cpp
** OpenGL decal rendering code
**
*/
#include "doomdata.h"
#include "gl/system/gl_system.h"
#include "a_sharedglobal.h"
#include "r_utility.h"
#include "g_levellocals.h"
#include "hwrenderer/utility/hw_cvars.h"
#include "gl/data/gl_vertexbuffer.h"
#include "gl/renderer/gl_renderer.h"
#include "gl/renderer/gl_lightdata.h"
#include "gl/renderer/gl_renderstate.h"
#include "gl/scene/gl_drawinfo.h"
#include "gl/scene/gl_scenedrawer.h"
#include "gl/renderer/gl_quaddrawer.h"
struct DecalVertex
{
float x,y,z;
float u,v;
};
//==========================================================================
//
//
//
//==========================================================================
void FDrawInfo::DrawDecal(GLWall *wall, DBaseDecal *decal)
{
auto seg = wall->seg;
line_t * line = seg->linedef;
side_t * side = seg->sidedef;
int i;
float zpos;
int light;
int rel;
float a;
bool flipx, flipy;
DecalVertex dv[4];
FTextureID decalTile;
if (decal->RenderFlags & RF_INVISIBLE) return;
if (wall->type == RENDERWALL_FFBLOCK && wall->gltexture->isMasked()) return; // No decals on 3D floors with transparent textures.
//if (decal->sprite != 0xffff)
{
decalTile = decal->PicNum;
flipx = !!(decal->RenderFlags & RF_XFLIP);
flipy = !!(decal->RenderFlags & RF_YFLIP);
}
/*
else
{
decalTile = SpriteFrames[sprites[decal->sprite].spriteframes + decal->frame].lump[0];
flipx = SpriteFrames[sprites[decal->sprite].spriteframes + decal->frame].flip & 1;
}
*/
FTexture *texture = TexMan[decalTile];
if (texture == NULL) return;
FMaterial *tex;
tex = FMaterial::ValidateTexture(texture, true);
// the sectors are only used for their texture origin coordinates
// so we don't need the fake sectors for deep water etc.
// As this is a completely split wall fragment no further splits are
// necessary for the decal.
sector_t *frontsector;
// for 3d-floor segments use the model sector as reference
if ((decal->RenderFlags&RF_CLIPMASK) == RF_CLIPMID) frontsector = decal->Sector;
else frontsector = seg->frontsector;
switch (decal->RenderFlags & RF_RELMASK)
{
default:
// No valid decal can have this type. If one is encountered anyway
// it is in some way invalid so skip it.
return;
//zpos = decal->z;
//break;
case RF_RELUPPER:
if (wall->type != RENDERWALL_TOP) return;
if (line->flags & ML_DONTPEGTOP)
{
zpos = decal->Z + frontsector->GetPlaneTexZ(sector_t::ceiling);
}
else
{
zpos = decal->Z + seg->backsector->GetPlaneTexZ(sector_t::ceiling);
}
break;
case RF_RELLOWER:
if (wall->type != RENDERWALL_BOTTOM) return;
if (line->flags & ML_DONTPEGBOTTOM)
{
zpos = decal->Z + frontsector->GetPlaneTexZ(sector_t::ceiling);
}
else
{
zpos = decal->Z + seg->backsector->GetPlaneTexZ(sector_t::floor);
}
break;
case RF_RELMID:
if (wall->type == RENDERWALL_TOP || wall->type == RENDERWALL_BOTTOM) return;
if (line->flags & ML_DONTPEGBOTTOM)
{
zpos = decal->Z + frontsector->GetPlaneTexZ(sector_t::floor);
}
else
{
zpos = decal->Z + frontsector->GetPlaneTexZ(sector_t::ceiling);
}
}
if (decal->RenderFlags & RF_FULLBRIGHT)
{
light = 255;
rel = 0;
}
else
{
light = wall->lightlevel;
rel = wall->rellight + getExtraLight();
}
FColormap p = wall->Colormap;
if (level.flags3 & LEVEL3_NOCOLOREDSPRITELIGHTING)
{
p.Decolorize();
}
a = decal->Alpha;
// now clip the decal to the actual polygon
float decalwidth = tex->TextureWidth() * decal->ScaleX;
float decalheight = tex->TextureHeight() * decal->ScaleY;
float decallefto = tex->GetLeftOffset() * decal->ScaleX;
float decaltopo = tex->GetTopOffset() * decal->ScaleY;
auto &glseg = wall->glseg;
float leftedge = glseg.fracleft * side->TexelLength;
float linelength = glseg.fracright * side->TexelLength - leftedge;
// texel index of the decal's left edge
float decalpixpos = (float)side->TexelLength * decal->LeftDistance - (flipx ? decalwidth - decallefto : decallefto) - leftedge;
float left, right;
float lefttex, righttex;
// decal is off the left edge
if (decalpixpos < 0)
{
left = 0;
lefttex = -decalpixpos;
}
else
{
left = decalpixpos;
lefttex = 0;
}
// decal is off the right edge
if (decalpixpos + decalwidth > linelength)
{
right = linelength;
righttex = right - decalpixpos;
}
else
{
right = decalpixpos + decalwidth;
righttex = decalwidth;
}
if (right <= left) return; // nothing to draw
// one texture unit on the wall as vector
float vx = (glseg.x2 - glseg.x1) / linelength;
float vy = (glseg.y2 - glseg.y1) / linelength;
dv[1].x = dv[0].x = glseg.x1 + vx * left;
dv[1].y = dv[0].y = glseg.y1 + vy * left;
dv[3].x = dv[2].x = glseg.x1 + vx * right;
dv[3].y = dv[2].y = glseg.y1 + vy * right;
zpos += (flipy ? decalheight - decaltopo : decaltopo);
dv[1].z = dv[2].z = zpos;
dv[0].z = dv[3].z = dv[1].z - decalheight;
dv[1].v = dv[2].v = tex->GetVT();
dv[1].u = dv[0].u = tex->GetU(lefttex / decal->ScaleX);
dv[3].u = dv[2].u = tex->GetU(righttex / decal->ScaleX);
dv[0].v = dv[3].v = tex->GetVB();
// now clip to the top plane
float vzt = (wall->ztop[1] - wall->ztop[0]) / linelength;
float topleft = wall->ztop[0] + vzt * left;
float topright = wall->ztop[0] + vzt * right;
// completely below the wall
if (topleft < dv[0].z && topright < dv[3].z)
return;
if (topleft < dv[1].z || topright < dv[2].z)
{
// decal has to be clipped at the top
// let texture clamping handle all extreme cases
dv[1].v = (dv[1].z - topleft) / (dv[1].z - dv[0].z)*dv[0].v;
dv[2].v = (dv[2].z - topright) / (dv[2].z - dv[3].z)*dv[3].v;
dv[1].z = topleft;
dv[2].z = topright;
}
// now clip to the bottom plane
float vzb = (wall->zbottom[1] - wall->zbottom[0]) / linelength;
float bottomleft = wall->zbottom[0] + vzb * left;
float bottomright = wall->zbottom[0] + vzb * right;
// completely above the wall
if (bottomleft > dv[1].z && bottomright > dv[2].z)
return;
if (bottomleft > dv[0].z || bottomright > dv[3].z)
{
// decal has to be clipped at the bottom
// let texture clamping handle all extreme cases
dv[0].v = (dv[1].z - bottomleft) / (dv[1].z - dv[0].z)*(dv[0].v - dv[1].v) + dv[1].v;
dv[3].v = (dv[2].z - bottomright) / (dv[2].z - dv[3].z)*(dv[3].v - dv[2].v) + dv[2].v;
dv[0].z = bottomleft;
dv[3].z = bottomright;
}
if (flipx)
{
float ur = tex->GetUR();
for (i = 0; i < 4; i++) dv[i].u = ur - dv[i].u;
}
if (flipy)
{
float vb = tex->GetVB();
for (i = 0; i < 4; i++) dv[i].v = vb - dv[i].v;
}
// calculate dynamic light effect.
if (gl_lights && GLRenderer->mLightCount && !mDrawer->FixedColormap && gl_light_sprites)
{
// Note: This should be replaced with proper shader based lighting.
double x, y;
decal->GetXY(seg->sidedef, x, y);
gl_SetDynSpriteLight(nullptr, x, y, zpos - decalheight * 0.5f, wall->sub);
}
// alpha color only has an effect when using an alpha texture.
if (decal->RenderStyle.Flags & STYLEF_RedIsAlpha)
{
gl_RenderState.SetObjectColor(decal->AlphaColor | 0xff000000);
}
gl_SetRenderStyle(decal->RenderStyle, false, false);
gl_RenderState.SetMaterial(tex, CLAMP_XY, decal->Translation, 0, !!(decal->RenderStyle.Flags & STYLEF_RedIsAlpha));
// If srcalpha is one it looks better with a higher alpha threshold
if (decal->RenderStyle.SrcAlpha == STYLEALPHA_One) gl_RenderState.AlphaFunc(GL_GEQUAL, gl_mask_sprite_threshold);
else gl_RenderState.AlphaFunc(GL_GREATER, 0.f);
mDrawer->SetColor(light, rel, p, a);
// for additively drawn decals we must temporarily set the fog color to black.
PalEntry fc = gl_RenderState.GetFogColor();
if (decal->RenderStyle.BlendOp == STYLEOP_Add && decal->RenderStyle.DestAlpha == STYLEALPHA_One)
{
gl_RenderState.SetFog(0, -1);
}
gl_RenderState.SetNormal(glseg.Normal());
FQuadDrawer qd;
for (i = 0; i < 4; i++)
{
qd.Set(i, dv[i].x, dv[i].z, dv[i].y, dv[i].u, dv[i].v);
}
if (wall->lightlist == nullptr)
{
gl_RenderState.Apply();
qd.Render(GL_TRIANGLE_FAN);
}
else
{
auto &lightlist = *wall->lightlist;
for (unsigned k = 0; k < lightlist.Size(); k++)
{
secplane_t &lowplane = k == lightlist.Size() - 1 ? wall->bottomplane : lightlist[k + 1].plane;
float low1 = lowplane.ZatPoint(dv[1].x, dv[1].y);
float low2 = lowplane.ZatPoint(dv[2].x, dv[2].y);
if (low1 < dv[1].z || low2 < dv[2].z)
{
int thisll = lightlist[k].caster != NULL ? hw_ClampLight(*lightlist[k].p_lightlevel) : wall->lightlevel;
FColormap thiscm;
thiscm.FadeColor = wall->Colormap.FadeColor;
thiscm.CopyFrom3DLight(&lightlist[k]);
mDrawer->SetColor(thisll, rel, thiscm, a);
if (level.flags3 & LEVEL3_NOCOLOREDSPRITELIGHTING) thiscm.Decolorize();
mDrawer->SetFog(thisll, rel, &thiscm, wall->RenderStyle == STYLE_Add);
gl_RenderState.SetSplitPlanes(lightlist[k].plane, lowplane);
gl_RenderState.Apply();
qd.Render(GL_TRIANGLE_FAN);
}
if (low1 <= dv[0].z && low2 <= dv[3].z) break;
}
}
rendered_decals++;
gl_RenderState.SetTextureMode(TM_MODULATE);
gl_RenderState.SetObjectColor(0xffffffff);
gl_RenderState.SetFog(fc, -1);
gl_RenderState.SetDynLight(0, 0, 0);
}
//==========================================================================
//
//
//
//==========================================================================
void FDrawInfo::DoDrawDecals(GLWall *wall)
{
if (wall->seg->sidedef && wall->seg->sidedef->AttachedDecals)
{
if (wall->lightlist != nullptr)
{
gl_RenderState.EnableSplit(true);
}
else
{
mDrawer->SetFog(wall->lightlevel, wall->rellight + getExtraLight(), &wall->Colormap, false);
}
DBaseDecal *decal = wall->seg->sidedef->AttachedDecals;
while (decal)
{
DrawDecal(wall, decal);
decal = decal->WallNext;
}
if (wall->lightlist != nullptr)
{
gl_RenderState.EnableSplit(false);
}
}
}

View file

@ -867,19 +867,6 @@ void GLDrawList::DrawFlats(int pass)
RenderFlat.Unclock();
}
//==========================================================================
//
//
//
//==========================================================================
void GLDrawList::DrawDecals()
{
for(unsigned i=0;i<drawitems.Size();i++)
{
gl_drawinfo->DoDrawDecals(walls[drawitems[i].index]);
}
}
//==========================================================================
//
// Sorting the drawitems first by texture and then by light level.
@ -952,7 +939,6 @@ GLSprite *GLDrawList::NewSprite()
return sprite;
}
//==========================================================================
//
// Try to reuse the lists as often as possible as they contain resources that
@ -1033,6 +1019,8 @@ void FDrawInfo::StartScene()
{
for (int i = 0; i < GLLDL_TYPES; i++) dldrawlists[i].Reset();
}
decals[0].Clear();
decals[1].Clear();
}
//==========================================================================
@ -1323,3 +1311,11 @@ std::pair<FFlatVertex *, unsigned int> FDrawInfo::AllocVertices(unsigned int cou
auto p = GLRenderer->mVBO->Alloc(count, &index);
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;
}

View file

@ -158,7 +158,6 @@ public:
void Draw(int pass, bool trans = false);
void DrawWalls(int pass);
void DrawFlats(int pass);
void DrawDecals();
GLDrawList * next;
} ;
@ -172,6 +171,7 @@ struct FDrawInfo : public HWDrawInfo
FDrawInfo * next;
GLDrawList drawlists[GLDL_TYPES];
TArray<GLDecal *> decals[2]; // the second slot is for mirrors which get rendered in a separate pass.
GLDrawList *dldrawlists = NULL; // only gets allocated when needed.
FDrawInfo();
@ -179,6 +179,7 @@ struct FDrawInfo : public HWDrawInfo
void AddWall(GLWall *wall) override;
void AddMirrorSurface(GLWall *w) override;
GLDecal *AddDecal(bool onmirror) override;
void AddPortal(GLWall *w, int portaltype) override;
void ProcessActorsInPortal(FLinePortalSpan *glport) override;
@ -189,10 +190,10 @@ struct FDrawInfo : public HWDrawInfo
void RenderFogBoundaryCompat(GLWall *wall);
void RenderLightsCompat(GLWall *wall, int pass);
void DrawDecal(GLWall *wall, DBaseDecal *decal);
void DoDrawDecals(GLWall *wall);
void DrawDecal(GLDecal *gldecal);
void DrawDecals();
void DrawDecalsForMirror(GLWall *wall);
void StartScene();
void SetupFloodStencil(wallseg * ws);
void ClearFloodStencil(wallseg * ws);

View file

@ -375,15 +375,7 @@ void GLSceneDrawer::RenderScene(int recursion)
glEnable(GL_POLYGON_OFFSET_FILL);
glPolygonOffset(-1.0f, -128.0f);
glDepthMask(false);
// this is the only geometry type on which decals can possibly appear
gl_drawinfo->drawlists[GLDL_PLAINWALLS].DrawDecals();
if (gl.legacyMode)
{
// also process the render lists with walls and dynamic lights
gl_drawinfo->dldrawlists[GLLDL_WALLS_PLAIN].DrawDecals();
gl_drawinfo->dldrawlists[GLLDL_WALLS_FOG].DrawDecals();
}
gl_drawinfo->DrawDecals();
gl_RenderState.SetTextureMode(TM_MODULATE);
@ -434,9 +426,10 @@ void GLSceneDrawer::RenderTranslucent()
gl_drawinfo->drawlists[GLDL_TRANSLUCENT].DrawSorted();
gl_RenderState.EnableBrightmap(false);
glDepthMask(true);
gl_RenderState.AlphaFunc(GL_GEQUAL, 0.5f);
glDepthMask(true);
RenderAll.Unclock();
}

View file

@ -9,14 +9,6 @@
#include "r_utility.h"
#include "c_cvars.h"
EXTERN_CVAR(Int, gl_weaponlight);
inline int getExtraLight()
{
return r_viewpoint.extralight * gl_weaponlight;
}
class GLSceneDrawer
{
fixed_t viewx, viewy; // since the nodes are still fixed point, keeping the view position also fixed point for node traversal is faster.

View file

@ -25,17 +25,17 @@
**
*/
#include "gl/system/gl_system.h"
#include "gl/system/gl_debug.h"
#include "gl/data/gl_vertexbuffer.h"
#include "gl/shaders/gl_shader.h"
#include "hwrenderer/textures/hw_ihwtexture.h"
#include "hwrenderer/textures/hw_material.h"
#include "r_renderer.h"
#include "gl_swscene.h"
#include "w_wad.h"
#include "d_player.h"
#include "textures/bitmap.h"
#include "swrenderer/scene/r_light.h"
#include "gl/renderer/gl_renderer.h"
// [RH] Base blending values (for e.g. underwater)
int BaseBlendR, BaseBlendG, BaseBlendB;
float BaseBlendA;

View file

@ -4,9 +4,6 @@
#include "r_defs.h"
#include "m_fixed.h"
#include "hwrenderer/scene/hw_clipper.h"
#include "gl_portal.h"
#include "gl/renderer/gl_lightdata.h"
#include "gl/renderer/gl_renderer.h"
#include "r_utility.h"
#include "c_cvars.h"
@ -18,12 +15,6 @@ class SWSceneDrawer
FSWSceneTexture *FBTexture = nullptr;
bool FBIsTruecolor = false;
void BlendView (player_t *CPlayer, float blend[4]);
bool CreateResources();
void BindFBBuffer();
public:
SWSceneDrawer();
~SWSceneDrawer();

View file

@ -11,7 +11,9 @@
#include "r_data/colormaps.h"
#include "hwrenderer/scene/hw_drawstructs.h"
#ifdef _MSC_VER
#pragma warning(disable:4244)
#endif
struct GLHorizonInfo;
struct F3DFloor;
@ -84,7 +86,7 @@ public:
void SetFrom3DFloor(F3DFloor *rover, bool top, bool underside);
void ProcessSector(sector_t * frontsector);
void Draw(int pass, bool trans);
GLFlat(const GLFlat &other)
{
memcpy(this, &other, sizeof(GLFlat));

View file

@ -44,105 +44,6 @@ EXTERN_CVAR(Bool, gl_seamless)
FDynLightData lightdata;
//==========================================================================
//
// Collect lights for shader
//
//==========================================================================
bool GLWall::SetupLights(FDynLightData &lightdata)
{
if (RenderStyle == STYLE_Add && !level.lightadditivesurfaces) return false; // no lights on additively blended surfaces.
// check for wall types which cannot have dynamic lights on them (portal types never get here so they don't need to be checked.)
switch (type)
{
case RENDERWALL_FOGBOUNDARY:
case RENDERWALL_MIRRORSURFACE:
case RENDERWALL_COLOR:
return false;
}
float vtx[]={glseg.x1,zbottom[0],glseg.y1, glseg.x1,ztop[0],glseg.y1, glseg.x2,ztop[1],glseg.y2, glseg.x2,zbottom[1],glseg.y2};
Plane p;
lightdata.Clear();
auto normal = glseg.Normal();
p.Set(normal, -normal.X * glseg.x1 - normal.Z * glseg.y1);
FLightNode *node;
if (seg->sidedef == NULL)
{
node = NULL;
}
else if (!(seg->sidedef->Flags & WALLF_POLYOBJ))
{
node = seg->sidedef->lighthead;
}
else if (sub)
{
// Polobject segs cannot be checked per sidedef so use the subsector instead.
node = sub->lighthead;
}
else node = NULL;
// Iterate through all dynamic lights which touch this wall and render them
while (node)
{
if (!(node->lightsource->flags2&MF2_DORMANT))
{
iter_dlight++;
DVector3 posrel = node->lightsource->PosRelative(seg->frontsector);
float x = posrel.X;
float y = posrel.Y;
float z = posrel.Z;
float dist = fabsf(p.DistToPoint(x, z, y));
float radius = node->lightsource->GetRadius();
float scale = 1.0f / ((2.f * radius) - dist);
FVector3 fn, pos;
if (radius > 0.f && dist < radius)
{
FVector3 nearPt, up, right;
pos = { x, z, y };
fn = p.Normal();
fn.GetRightUp(right, up);
FVector3 tmpVec = fn * dist;
nearPt = pos + tmpVec;
FVector3 t1;
int outcnt[4]={0,0,0,0};
texcoord tcs[4];
// do a quick check whether the light touches this polygon
for(int i=0;i<4;i++)
{
t1 = FVector3(&vtx[i*3]);
FVector3 nearToVert = t1 - nearPt;
tcs[i].u = ((nearToVert | right) * scale) + 0.5f;
tcs[i].v = ((nearToVert | up) * scale) + 0.5f;
if (tcs[i].u<0) outcnt[0]++;
if (tcs[i].u>1) outcnt[1]++;
if (tcs[i].v<0) outcnt[2]++;
if (tcs[i].v>1) outcnt[3]++;
}
if (outcnt[0]!=4 && outcnt[1]!=4 && outcnt[2]!=4 && outcnt[3]!=4)
{
lightdata.GetLight(seg->frontsector->PortalGroup, p, node->lightsource, true);
}
}
}
node = node->nextLight;
}
return true;
}
//==========================================================================
//
@ -153,7 +54,7 @@ bool GLWall::SetupLights(FDynLightData &lightdata)
void FDrawInfo::RenderWall(GLWall *wall, int textured)
{
assert(vertcount > 0);
assert(wall->vertcount > 0);
gl_RenderState.Apply();
gl_RenderState.ApplyLightIndex(wall->dynlightindex);
GLRenderer->mVBO->RenderArray(GL_TRIANGLE_FAN, wall->vertindex, wall->vertcount);
@ -238,13 +139,14 @@ void FDrawInfo::RenderMirrorSurface(GLWall *wall)
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.
// 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)
{
glEnable(GL_POLYGON_OFFSET_FILL);
glPolygonOffset(-1.0f, -128.0f);
glDepthMask(false);
gl_drawinfo->DoDrawDecals(wall);
gl_drawinfo->DrawDecalsForMirror(wall);
glDepthMask(true);
glPolygonOffset(0.0f, 0.0f);
glDisable(GL_POLYGON_OFFSET_FILL);
@ -461,6 +363,7 @@ void FDrawInfo::AddWall(GLWall *wall)
wall->MakeVertices(this, false);
auto newwall = drawlists[list].NewWall();
*newwall = *wall;
if (!masked) newwall->ProcessDecals(this);
}
wall->dynlightindex = -1;
}
@ -482,6 +385,7 @@ void FDrawInfo::AddMirrorSurface(GLWall *w)
tcs[GLWall::LOLFT].u = tcs[GLWall::LORGT].u = tcs[GLWall::UPLFT].u = tcs[GLWall::UPRGT].u = v.X;
tcs[GLWall::LOLFT].v = tcs[GLWall::LORGT].v = tcs[GLWall::UPLFT].v = tcs[GLWall::UPRGT].v = v.Z;
newwall->MakeVertices(this, false);
newwall->ProcessDecals(this);
}
//==========================================================================
@ -566,3 +470,137 @@ void FDrawInfo::AddPortal(GLWall *wall, int ptype)
}
wall->vertcount = 0;
}
//==========================================================================
//
//
//
//==========================================================================
void FDrawInfo::DrawDecal(GLDecal *gldecal)
{
auto wall = gldecal->wall;
auto decal = gldecal->decal;
auto tex = gldecal->gltexture;
auto &seg = wall->seg;
// calculate dynamic light effect.
if (gl_lights && GLRenderer->mLightCount && !mDrawer->FixedColormap && gl_light_sprites)
{
// Note: This should be replaced with proper shader based lighting.
double x, y;
decal->GetXY(seg->sidedef, x, y);
gl_SetDynSpriteLight(nullptr, x, y, gldecal->zcenter, wall->sub);
}
// alpha color only has an effect when using an alpha texture.
if (decal->RenderStyle.Flags & STYLEF_RedIsAlpha)
{
gl_RenderState.SetObjectColor(decal->AlphaColor | 0xff000000);
}
gl_SetRenderStyle(decal->RenderStyle, false, false);
gl_RenderState.SetMaterial(tex, CLAMP_XY, decal->Translation, 0, !!(decal->RenderStyle.Flags & STYLEF_RedIsAlpha));
// If srcalpha is one it looks better with a higher alpha threshold
if (decal->RenderStyle.SrcAlpha == STYLEALPHA_One) gl_RenderState.AlphaFunc(GL_GEQUAL, gl_mask_sprite_threshold);
else gl_RenderState.AlphaFunc(GL_GREATER, 0.f);
mDrawer->SetColor(gldecal->light, gldecal->rel, gldecal->colormap, gldecal->a);
// for additively drawn decals we must temporarily set the fog color to black.
PalEntry fc = gl_RenderState.GetFogColor();
if (decal->RenderStyle.BlendOp == STYLEOP_Add && decal->RenderStyle.DestAlpha == STYLEALPHA_One)
{
gl_RenderState.SetFog(0, -1);
}
gl_RenderState.SetNormal(wall->glseg.Normal());
if (wall->lightlist == nullptr)
{
gl_RenderState.Apply();
GLRenderer->mVBO->RenderArray(GL_TRIANGLE_FAN, gldecal->vertindex, 4);
}
else
{
auto &lightlist = *wall->lightlist;
for (unsigned k = 0; k < lightlist.Size(); k++)
{
secplane_t &lowplane = k == lightlist.Size() - 1 ? wall->bottomplane : lightlist[k + 1].plane;
DecalVertex *dv = gldecal->dv;
float low1 = lowplane.ZatPoint(dv[1].x, dv[1].y);
float low2 = lowplane.ZatPoint(dv[2].x, dv[2].y);
if (low1 < dv[1].z || low2 < dv[2].z)
{
int thisll = lightlist[k].caster != NULL ? hw_ClampLight(*lightlist[k].p_lightlevel) : wall->lightlevel;
FColormap thiscm;
thiscm.FadeColor = wall->Colormap.FadeColor;
thiscm.CopyFrom3DLight(&lightlist[k]);
mDrawer->SetColor(thisll, gldecal->rel, thiscm, gldecal->a);
if (level.flags3 & LEVEL3_NOCOLOREDSPRITELIGHTING) thiscm.Decolorize();
mDrawer->SetFog(thisll, gldecal->rel, &thiscm, wall->RenderStyle == STYLE_Add);
gl_RenderState.SetSplitPlanes(lightlist[k].plane, lowplane);
gl_RenderState.Apply();
GLRenderer->mVBO->RenderArray(GL_TRIANGLE_FAN, gldecal->vertindex, 4);
}
if (low1 <= dv[0].z && low2 <= dv[3].z) break;
}
}
rendered_decals++;
gl_RenderState.SetTextureMode(TM_MODULATE);
gl_RenderState.SetObjectColor(0xffffffff);
gl_RenderState.SetFog(fc, -1);
gl_RenderState.SetDynLight(0, 0, 0);
}
//==========================================================================
//
//
//
//==========================================================================
void FDrawInfo::DrawDecals()
{
GLWall *wall = nullptr;
for (auto gldecal : decals[0])
{
if (gldecal->wall != wall)
{
wall = gldecal->wall;
if (wall->lightlist != nullptr)
{
gl_RenderState.EnableSplit(true);
}
else
{
gl_RenderState.EnableSplit(false);
mDrawer->SetFog(wall->lightlevel, wall->rellight + getExtraLight(), &wall->Colormap, false);
}
}
DrawDecal(gldecal);
}
if (wall && wall->lightlist != nullptr) gl_RenderState.EnableSplit(false);
}
//==========================================================================
//
// This list will never get long, so this code should be ok.
//
//==========================================================================
void FDrawInfo::DrawDecalsForMirror(GLWall *wall)
{
mDrawer->SetFog(wall->lightlevel, wall->rellight + getExtraLight(), &wall->Colormap, false);
for (auto gldecal : decals[1])
{
if (gldecal->wall == wall)
{
DrawDecal(gldecal);
}
}
}

View file

@ -481,10 +481,9 @@ void OpenGLFrameBuffer::SetClearColor(int color)
//
//
//==========================================================================
bool OpenGLFrameBuffer::Begin2D(bool copy3d)
void OpenGLFrameBuffer::Begin2D(bool copy3d)
{
Super::Begin2D(copy3d);
ClearClipRect();
gl_RenderState.mViewMatrix.loadIdentity();
gl_RenderState.mProjectionMatrix.ortho(0, GetWidth(), GetHeight(), 0, -1.0f, 1.0f);
gl_RenderState.ApplyMatrices();
@ -503,7 +502,6 @@ bool OpenGLFrameBuffer::Begin2D(bool copy3d)
if (GLRenderer != NULL)
GLRenderer->Begin2D();
return true;
}
//===========================================================================

View file

@ -34,7 +34,7 @@ public:
PalEntry *GetPalette () override;
bool SetFlash(PalEntry rgb, int amount) override;
void GetFlash(PalEntry &rgb, int &amount) override;
bool Begin2D(bool copy3d) override;
void Begin2D(bool copy3d) override;
void GameRestart() override;
void InitForLevel() override;
void SetClearColor(int color) override;

View file

@ -0,0 +1,282 @@
//
//---------------------------------------------------------------------------
//
// Copyright(C) 2003-2018 Christoph Oelckers
// All rights reserved.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with this program. If not, see http://www.gnu.org/licenses/
//
//--------------------------------------------------------------------------
//
/*
** gl_decal.cpp
** OpenGL decal processing code
**
*/
#include "doomdata.h"
#include "a_sharedglobal.h"
#include "r_utility.h"
#include "g_levellocals.h"
#include "hwrenderer/textures/hw_material.h"
#include "hwrenderer/utility/hw_cvars.h"
#include "hwrenderer/scene/hw_drawstructs.h"
#include "hwrenderer/scene/hw_drawinfo.h"
#include "hwrenderer/utility/hw_lighting.h"
#include "hwrenderer/data/flatvertices.h"
void GLWall::ProcessDecal(HWDrawInfo *di, DBaseDecal *decal)
{
line_t * line = seg->linedef;
side_t * side = seg->sidedef;
int i;
float zpos;
bool flipx, flipy;
FTextureID decalTile;
if (decal->RenderFlags & RF_INVISIBLE) return;
if (type == RENDERWALL_FFBLOCK && gltexture->isMasked()) return; // No decals on 3D floors with transparent textures.
if (seg == nullptr) return;
decalTile = decal->PicNum;
flipx = !!(decal->RenderFlags & RF_XFLIP);
flipy = !!(decal->RenderFlags & RF_YFLIP);
FTexture *texture = TexMan[decalTile];
if (texture == NULL) return;
// the sectors are only used for their texture origin coordinates
// so we don't need the fake sectors for deep water etc.
// As this is a completely split wall fragment no further splits are
// necessary for the decal.
sector_t *frontsector;
// for 3d-floor segments use the model sector as reference
if ((decal->RenderFlags&RF_CLIPMASK) == RF_CLIPMID) frontsector = decal->Sector;
else frontsector = seg->frontsector;
switch (decal->RenderFlags & RF_RELMASK)
{
default:
// No valid decal can have this type. If one is encountered anyway
// it is in some way invalid so skip it.
return;
//zpos = decal->z;
//break;
case RF_RELUPPER:
if (type != RENDERWALL_TOP) return;
if (line->flags & ML_DONTPEGTOP)
{
zpos = decal->Z + frontsector->GetPlaneTexZ(sector_t::ceiling);
}
else
{
zpos = decal->Z + seg->backsector->GetPlaneTexZ(sector_t::ceiling);
}
break;
case RF_RELLOWER:
if (type != RENDERWALL_BOTTOM) return;
if (line->flags & ML_DONTPEGBOTTOM)
{
zpos = decal->Z + frontsector->GetPlaneTexZ(sector_t::ceiling);
}
else
{
zpos = decal->Z + seg->backsector->GetPlaneTexZ(sector_t::floor);
}
break;
case RF_RELMID:
if (type == RENDERWALL_TOP || type == RENDERWALL_BOTTOM) return;
if (line->flags & ML_DONTPEGBOTTOM)
{
zpos = decal->Z + frontsector->GetPlaneTexZ(sector_t::floor);
}
else
{
zpos = decal->Z + frontsector->GetPlaneTexZ(sector_t::ceiling);
}
}
GLDecal &gldecal = *di->AddDecal(type == RENDERWALL_MIRRORSURFACE);
gldecal.gltexture = FMaterial::ValidateTexture(texture, true);
gldecal.wall = this;
gldecal.decal = decal;
if (decal->RenderFlags & RF_FULLBRIGHT)
{
gldecal.light = 255;
gldecal.rel = 0;
}
else
{
gldecal.light = lightlevel;
gldecal.rel = rellight + getExtraLight();
}
gldecal.colormap = Colormap;
if (level.flags3 & LEVEL3_NOCOLOREDSPRITELIGHTING)
{
gldecal.colormap.Decolorize();
}
gldecal.a = decal->Alpha;
// now clip the decal to the actual polygon
FMaterial *tex = gldecal.gltexture;
float decalwidth = tex->TextureWidth() * decal->ScaleX;
float decalheight = tex->TextureHeight() * decal->ScaleY;
float decallefto = tex->GetLeftOffset() * decal->ScaleX;
float decaltopo = tex->GetTopOffset() * decal->ScaleY;
float leftedge = glseg.fracleft * side->TexelLength;
float linelength = glseg.fracright * side->TexelLength - leftedge;
// texel index of the decal's left edge
float decalpixpos = (float)side->TexelLength * decal->LeftDistance - (flipx ? decalwidth - decallefto : decallefto) - leftedge;
float left, right;
float lefttex, righttex;
// decal is off the left edge
if (decalpixpos < 0)
{
left = 0;
lefttex = -decalpixpos;
}
else
{
left = decalpixpos;
lefttex = 0;
}
// decal is off the right edge
if (decalpixpos + decalwidth > linelength)
{
right = linelength;
righttex = right - decalpixpos;
}
else
{
right = decalpixpos + decalwidth;
righttex = decalwidth;
}
if (right <= left) return; // nothing to draw
// one texture unit on the wall as vector
float vx = (glseg.x2 - glseg.x1) / linelength;
float vy = (glseg.y2 - glseg.y1) / linelength;
DecalVertex *dv = gldecal.dv;
dv[1].x = dv[0].x = glseg.x1 + vx * left;
dv[1].y = dv[0].y = glseg.y1 + vy * left;
dv[3].x = dv[2].x = glseg.x1 + vx * right;
dv[3].y = dv[2].y = glseg.y1 + vy * right;
zpos += (flipy ? decalheight - decaltopo : decaltopo);
dv[1].z = dv[2].z = zpos;
dv[0].z = dv[3].z = dv[1].z - decalheight;
dv[1].v = dv[2].v = tex->GetVT();
dv[1].u = dv[0].u = tex->GetU(lefttex / decal->ScaleX);
dv[3].u = dv[2].u = tex->GetU(righttex / decal->ScaleX);
dv[0].v = dv[3].v = tex->GetVB();
// now clip to the top plane
float vzt = (ztop[1] - ztop[0]) / linelength;
float topleft = ztop[0] + vzt * left;
float topright = ztop[0] + vzt * right;
// completely below the wall
if (topleft < dv[0].z && topright < dv[3].z)
return;
if (topleft < dv[1].z || topright < dv[2].z)
{
// decal has to be clipped at the top
// let texture clamping handle all extreme cases
dv[1].v = (dv[1].z - topleft) / (dv[1].z - dv[0].z)*dv[0].v;
dv[2].v = (dv[2].z - topright) / (dv[2].z - dv[3].z)*dv[3].v;
dv[1].z = topleft;
dv[2].z = topright;
}
// now clip to the bottom plane
float vzb = (zbottom[1] - zbottom[0]) / linelength;
float bottomleft = zbottom[0] + vzb * left;
float bottomright = zbottom[0] + vzb * right;
// completely above the wall
if (bottomleft > dv[1].z && bottomright > dv[2].z)
return;
if (bottomleft > dv[0].z || bottomright > dv[3].z)
{
// decal has to be clipped at the bottom
// let texture clamping handle all extreme cases
dv[0].v = (dv[1].z - bottomleft) / (dv[1].z - dv[0].z)*(dv[0].v - dv[1].v) + dv[1].v;
dv[3].v = (dv[2].z - bottomright) / (dv[2].z - dv[3].z)*(dv[3].v - dv[2].v) + dv[2].v;
dv[0].z = bottomleft;
dv[3].z = bottomright;
}
if (flipx)
{
float ur = tex->GetUR();
for (i = 0; i < 4; i++) dv[i].u = ur - dv[i].u;
}
if (flipy)
{
float vb = tex->GetVB();
for (i = 0; i < 4; i++) dv[i].v = vb - dv[i].v;
}
gldecal.zcenter = zpos - decalheight * 0.5f;
auto verts = di->AllocVertices(4);
gldecal.vertindex = verts.second;
for (i = 0; i < 4; i++)
{
verts.first[i].Set(dv[i].x, dv[i].z, dv[i].y, dv[i].u, dv[i].v);
}
}
//==========================================================================
//
//
//
//==========================================================================
void GLWall::ProcessDecals(HWDrawInfo *di)
{
if (seg->sidedef != nullptr)
{
DBaseDecal *decal = seg->sidedef->AttachedDecals;
while (decal)
{
ProcessDecal(di, decal);
decal = decal->WallNext;
}
}
}

View file

@ -6,6 +6,7 @@ struct FSectorPortalGroup;
struct FLinePortalSpan;
struct FFlatVertex;
class GLWall;
struct GLDecal;
//==========================================================================
//
@ -127,6 +128,7 @@ public:
virtual void AddWall(GLWall *w) = 0;
virtual void AddPortal(GLWall *w, int portaltype) = 0;
virtual void AddMirrorSurface(GLWall *w) = 0;
virtual GLDecal *AddDecal(bool onmirror) = 0;
virtual void ProcessActorsInPortal(FLinePortalSpan *glport) = 0;
virtual std::pair<FFlatVertex *, unsigned int> AllocVertices(unsigned int count) = 0;

View file

@ -9,7 +9,9 @@
#include "textures/textures.h"
#include "r_data/colormaps.h"
#ifdef _MSC_VER
#pragma warning(disable:4244)
#endif
struct GLHorizonInfo;
struct GLSkyInfo;
@ -234,6 +236,8 @@ public:
float fch1, float fch2, float ffh1, float ffh2,
float bch1, float bch2, float bfh1, float bfh2);
void ProcessDecal(HWDrawInfo *di, DBaseDecal *decal);
void ProcessDecals(HWDrawInfo *di);
void CreateVertices(FFlatVertex *&ptr, bool nosplit);
void SplitLeftEdge (FFlatVertex *&ptr);
@ -277,6 +281,32 @@ public:
};
struct DecalVertex
{
float x, y, z;
float u, v;
};
struct GLDecal
{
FMaterial *gltexture;
GLWall *wall;
DBaseDecal *decal;
DecalVertex dv[4];
float zcenter;
unsigned int vertindex;
int light;
int rel;
float a;
FColormap colormap;
};
inline float Dist2(float x1,float y1,float x2,float y2)
{
return sqrtf((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));

View file

@ -29,6 +29,7 @@
#include "p_maputl.h"
#include "doomdata.h"
#include "g_levellocals.h"
#include "actorinlines.h"
#include "hwrenderer/dynlights/hw_dynlightdata.h"
#include "hwrenderer/textures/hw_material.h"
#include "hwrenderer/utility/hw_cvars.h"
@ -39,6 +40,105 @@
#include "hwrenderer/scene/hw_portal.h"
//==========================================================================
//
// Collect lights for shader
//
//==========================================================================
bool GLWall::SetupLights(FDynLightData &lightdata)
{
if (RenderStyle == STYLE_Add && !level.lightadditivesurfaces) return false; // no lights on additively blended surfaces.
// check for wall types which cannot have dynamic lights on them (portal types never get here so they don't need to be checked.)
switch (type)
{
case RENDERWALL_FOGBOUNDARY:
case RENDERWALL_MIRRORSURFACE:
case RENDERWALL_COLOR:
return false;
}
float vtx[]={glseg.x1,zbottom[0],glseg.y1, glseg.x1,ztop[0],glseg.y1, glseg.x2,ztop[1],glseg.y2, glseg.x2,zbottom[1],glseg.y2};
Plane p;
lightdata.Clear();
auto normal = glseg.Normal();
p.Set(normal, -normal.X * glseg.x1 - normal.Z * glseg.y1);
FLightNode *node;
if (seg->sidedef == NULL)
{
node = NULL;
}
else if (!(seg->sidedef->Flags & WALLF_POLYOBJ))
{
node = seg->sidedef->lighthead;
}
else if (sub)
{
// Polobject segs cannot be checked per sidedef so use the subsector instead.
node = sub->lighthead;
}
else node = NULL;
// Iterate through all dynamic lights which touch this wall and render them
while (node)
{
if (!(node->lightsource->flags2&MF2_DORMANT))
{
iter_dlight++;
DVector3 posrel = node->lightsource->PosRelative(seg->frontsector);
float x = posrel.X;
float y = posrel.Y;
float z = posrel.Z;
float dist = fabsf(p.DistToPoint(x, z, y));
float radius = node->lightsource->GetRadius();
float scale = 1.0f / ((2.f * radius) - dist);
FVector3 fn, pos;
if (radius > 0.f && dist < radius)
{
FVector3 nearPt, up, right;
pos = { x, z, y };
fn = p.Normal();
fn.GetRightUp(right, up);
FVector3 tmpVec = fn * dist;
nearPt = pos + tmpVec;
FVector3 t1;
int outcnt[4]={0,0,0,0};
texcoord tcs[4];
// do a quick check whether the light touches this polygon
for(int i=0;i<4;i++)
{
t1 = FVector3(&vtx[i*3]);
FVector3 nearToVert = t1 - nearPt;
tcs[i].u = ((nearToVert | right) * scale) + 0.5f;
tcs[i].v = ((nearToVert | up) * scale) + 0.5f;
if (tcs[i].u<0) outcnt[0]++;
if (tcs[i].u>1) outcnt[1]++;
if (tcs[i].v<0) outcnt[2]++;
if (tcs[i].v>1) outcnt[3]++;
}
if (outcnt[0]!=4 && outcnt[1]!=4 && outcnt[2]!=4 && outcnt[3]!=4)
{
lightdata.GetLight(seg->frontsector->PortalGroup, p, node->lightsource, true);
}
}
}
node = node->nextLight;
}
return true;
}
const char GLWall::passflag[] = {

View file

@ -1,8 +1,10 @@
#pragma once
#include <stdint.h>
#include "tarray.h"
typedef TMap<int, bool> SpriteHits;
class FTexture;
class IHardwareTexture
{

View file

@ -1,7 +1,9 @@
#pragma once
#include "c_cvars.h"
#include "v_palette.h"
#include "templates.h"
#include "r_utility.h"
struct Colormap;
@ -15,3 +17,10 @@ inline int hw_ClampLight(int lightlevel)
return clamp(lightlevel, 0, 255);
}
EXTERN_CVAR(Int, gl_weaponlight);
inline int getExtraLight()
{
return r_viewpoint.extralight * gl_weaponlight;
}

View file

@ -229,21 +229,14 @@ void DIntermissionScreenFader::Drawer ()
if (mType == FADE_In) factor = 1.0 - factor;
int color = MAKEARGB(int(factor*255), 0,0,0);
if (screen->Begin2D(false))
screen->Begin2D(false);
screen->DrawTexture (TexMan[mBackground], 0, 0, DTA_Fullscreen, true, DTA_ColorOverlay, color, TAG_DONE);
for (unsigned i=0; i < mOverlays.Size(); i++)
{
screen->DrawTexture (TexMan[mBackground], 0, 0, DTA_Fullscreen, true, DTA_ColorOverlay, color, TAG_DONE);
for (unsigned i=0; i < mOverlays.Size(); i++)
{
if (CheckOverlay(i))
screen->DrawTexture (TexMan[mOverlays[i].mPic], mOverlays[i].x, mOverlays[i].y, DTA_320x200, true, DTA_ColorOverlay, color, TAG_DONE);
}
screen->FillBorder (NULL);
}
else
{
V_SetBlend (0,0,0,int(256*factor));
Super::Drawer();
if (CheckOverlay(i))
screen->DrawTexture (TexMan[mOverlays[i].mPic], mOverlays[i].x, mOverlays[i].y, DTA_320x200, true, DTA_ColorOverlay, color, TAG_DONE);
}
screen->FillBorder (NULL);
}
}

View file

@ -58,7 +58,8 @@ FRenderStyle LegacyRenderStyles[STYLE_Count] =
{ { STYLEOP_RevSub, STYLEALPHA_Src, STYLEALPHA_One, 0 } }, /* STYLE_Subtract*/
{ { STYLEOP_Add, STYLEALPHA_Src, STYLEALPHA_One, STYLEF_ColorIsFixed } }, /* STYLE_AddStencil */
{ { STYLEOP_Add, STYLEALPHA_Src, STYLEALPHA_One, STYLEF_RedIsAlpha | STYLEF_ColorIsFixed } }, /* STYLE_AddShaded */
{ { STYLEOP_Add, STYLEALPHA_InvDstCol, STYLEALPHA_Zero, 0 } }, /* STYLE_Multiply */
{ { STYLEOP_Add, STYLEALPHA_DstCol, STYLEALPHA_Zero, 0 } }, /* STYLE_Multiply */
{ { STYLEOP_Add, STYLEALPHA_InvDstCol, STYLEALPHA_Zero, 0 } }, /* STYLE_InverseMultiply */
};
double GetAlpha(int type, double alpha)

View file

@ -62,6 +62,7 @@ enum ERenderStyle
STYLE_AddStencil, // Fill image interior with alphacolor
STYLE_AddShaded, // Treat patch data as alpha values for alphacolor
STYLE_Multiply, // Multiply source with destination (HW renderer only.)
STYLE_InverseMultiply, // Multiply source with inverse of destination (HW renderer only.)
STYLE_Count
};

View file

@ -859,11 +859,10 @@ void DFrameBuffer::SetBlendingRect (int x1, int y1, int x2, int y2)
//
//==========================================================================
bool DFrameBuffer::Begin2D (bool copy3d)
void DFrameBuffer::Begin2D (bool copy3d)
{
isIn2D = true;
ClearClipRect();
return false;
}
//==========================================================================

View file

@ -385,7 +385,7 @@ public:
// Begin 2D drawing operations.
// Returns true if hardware-accelerated 2D has been entered, false if not.
virtual bool Begin2D(bool copy3d);
virtual void Begin2D(bool copy3d);
void End2D() { isIn2D = false; }
// Returns true if Begin2D has been called and 2D drawing is now active

View file

@ -504,7 +504,7 @@ void main()
case 4: // simple 2D (reuses a uniform for the special colormap for the color overlay.)
{
frag = frag * vColor;
frag = frag * ProcessLight(vColor);
frag.rgb = frag.rgb + uFixedColormapStart.rgb;
break;
}