- removed texture based dynamic lighting. For GL 3.x the shader approach is always better.

- fixed: sky fog was not unset.
This commit is contained in:
Christoph Oelckers 2014-07-15 20:49:21 +02:00
parent fb6b4238ed
commit b8bcbe819b
17 changed files with 129 additions and 657 deletions

View file

@ -521,14 +521,12 @@ void ADynamicLight::CollectWithinRadius(subsector_t *subSec, float radius)
{
if (!subSec) return;
bool additive = (flags4&MF4_ADDITIVE) || gl_lights_additive;
subSec->validcount = ::validcount;
touching_subsectors = AddLightNode(&subSec->lighthead[additive], subSec, this, touching_subsectors);
touching_subsectors = AddLightNode(&subSec->lighthead, subSec, this, touching_subsectors);
if (subSec->sector->validcount != ::validcount)
{
touching_sector = AddLightNode(&subSec->render_sector->lighthead[additive], subSec->sector, this, touching_sector);
touching_sector = AddLightNode(&subSec->render_sector->lighthead, subSec->sector, this, touching_sector);
subSec->sector->validcount = ::validcount;
}
@ -542,7 +540,7 @@ void ADynamicLight::CollectWithinRadius(subsector_t *subSec, float radius)
if (DMulScale32 (y-seg->v1->y, seg->v2->x-seg->v1->x, seg->v1->x-x, seg->v2->y-seg->v1->y) <=0)
{
seg->linedef->validcount=validcount;
touching_sides = AddLightNode(&seg->sidedef->lighthead[additive], seg->sidedef, this, touching_sides);
touching_sides = AddLightNode(&seg->sidedef->lighthead, seg->sidedef, this, touching_sides);
}
}
@ -755,22 +753,15 @@ CCMD(listsublights)
{
subsector_t *sub = &subsectors[i];
int lights = 0;
int addlights = 0;
FLightNode * node = sub->lighthead[0];
FLightNode * node = sub->lighthead;
while (node != NULL)
{
lights++;
node = node->nextLight;
}
node = sub->lighthead[1];
while (node != NULL)
{
addlights++;
node = node->nextLight;
}
Printf(PRINT_LOG, "Subsector %d - %d lights, %d additive lights\n", i, lights, addlights);
Printf(PRINT_LOG, "Subsector %d - %d lights\n", i, lights);
}
}

View file

@ -184,8 +184,6 @@ struct FDynLightData
bool gl_GetLight(Plane & p, ADynamicLight * light, bool checkside, bool forceadditive, FDynLightData &data);
bool gl_SetupLight(Plane & p, ADynamicLight * light, Vector & nearPt, Vector & up, Vector & right, float & scale, int desaturation, bool checkside=true, bool forceadditive=true);
bool gl_SetupLightTexture();
void gl_UploadLights(FDynLightData &data);

View file

@ -68,17 +68,6 @@ CUSTOM_CVAR (Bool, gl_lights, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_NOIN
else gl_DeleteAllAttachedLights();
}
CUSTOM_CVAR (Bool, gl_dynlight_shader, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_NOINITCALL)
{
if (self)
{
if (gl.maxuniforms < 1024 && !(gl.flags & RFL_SHADER_STORAGE_BUFFER))
{
self = false;
}
}
}
CVAR (Bool, gl_attachedlights, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG);
CVAR (Bool, gl_lights_checkside, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG);
CVAR (Float, gl_lights_intensity, 1.0f, CVAR_ARCHIVE | CVAR_GLOBALCONFIG);
@ -155,75 +144,6 @@ bool gl_GetLight(Plane & p, ADynamicLight * light, bool checkside, bool forceadd
}
//==========================================================================
//
// Sets up the parameters to render one dynamic light onto one plane
//
//==========================================================================
bool gl_SetupLight(Plane & p, ADynamicLight * light, Vector & nearPt, Vector & up, Vector & right,
float & scale, int desaturation, bool checkside, bool forceadditive)
{
Vector fn, pos;
float x = FIXED2FLOAT(light->x);
float y = FIXED2FLOAT(light->y);
float z = FIXED2FLOAT(light->z);
float dist = fabsf(p.DistToPoint(x, z, y));
float radius = (light->GetRadius() * gl_lights_size);
if (radius <= 0.f) return false;
if (dist > radius) return false;
if (checkside && gl_lights_checkside && p.PointOnSide(x, z, y))
{
return false;
}
if (light->owned && light->target != NULL && !light->target->IsVisibleToPlayer())
{
return false;
}
scale = 1.0f / ((2.f * radius) - dist);
// project light position onto plane (find closest point on plane)
pos.Set(x,z,y);
fn=p.Normal();
fn.GetRightUp(right, up);
#ifdef _MSC_VER
nearPt = pos + fn * dist;
#else
Vector tmpVec = fn * dist;
nearPt = pos + tmpVec;
#endif
float cs = 1.0f - (dist / radius);
if (gl_lights_additive || light->flags4&MF4_ADDITIVE || forceadditive) cs*=0.2f; // otherwise the light gets too strong.
float r = light->GetRed() / 255.0f * cs * gl_lights_intensity;
float g = light->GetGreen() / 255.0f * cs * gl_lights_intensity;
float b = light->GetBlue() / 255.0f * cs * gl_lights_intensity;
if (light->IsSubtractive())
{
Vector v;
gl_RenderState.BlendEquation(GL_FUNC_REVERSE_SUBTRACT);
v.Set(r, g, b);
r = v.Length() - r;
g = v.Length() - g;
b = v.Length() - b;
}
else
{
gl_RenderState.BlendEquation(GL_FUNC_ADD);
}
gl_RenderState.SetColor(r, g, b, 1.f, desaturation);
return true;
}
//==========================================================================
//
//
@ -257,31 +177,3 @@ void gl_UploadLights(FDynLightData &data)
}
}
#endif
//==========================================================================
//
//
//
//==========================================================================
bool gl_SetupLightTexture()
{
if (GLRenderer->gllight == NULL) return false;
FMaterial * pat = FMaterial::ValidateTexture(GLRenderer->gllight);
pat->BindPatch(0);
return true;
}
//==========================================================================
//
//
//
//==========================================================================
inline fixed_t P_AproxDistance3(fixed_t dx, fixed_t dy, fixed_t dz)
{
return P_AproxDistance(P_AproxDistance(dx,dy),dz);
}

View file

@ -96,7 +96,7 @@ FGLRenderer::FGLRenderer(OpenGLFrameBuffer *fb)
mSkyVBO = NULL;
gl_spriteindex = 0;
mShaderManager = NULL;
glpart2 = glpart = gllight = mirrortexture = NULL;
glpart2 = glpart = mirrortexture = NULL;
}
void FGLRenderer::Initialize()
@ -104,7 +104,6 @@ void FGLRenderer::Initialize()
glpart2 = FTexture::CreateTexture(Wads.GetNumForFullName("glstuff/glpart2.png"), FTexture::TEX_MiscPatch);
glpart = FTexture::CreateTexture(Wads.GetNumForFullName("glstuff/glpart.png"), FTexture::TEX_MiscPatch);
mirrortexture = FTexture::CreateTexture(Wads.GetNumForFullName("glstuff/mirror.png"), FTexture::TEX_MiscPatch);
gllight = FTexture::CreateTexture(Wads.GetNumForFullName("glstuff/gllight.png"), FTexture::TEX_MiscPatch);
mVBO = new FFlatVertexBuffer;
mSkyVBO = new FSkyVertexBuffer;
@ -128,7 +127,6 @@ FGLRenderer::~FGLRenderer()
if (glpart2) delete glpart2;
if (glpart) delete glpart;
if (mirrortexture) delete mirrortexture;
if (gllight) delete gllight;
if (mFBID != 0) glDeleteFramebuffers(1, &mFBID);
}

View file

@ -62,7 +62,6 @@ public:
FTexture *glpart2;
FTexture *glpart;
FTexture *mirrortexture;
FTexture *gllight;
float mSky1Pos, mSky2Pos;

View file

@ -13,14 +13,6 @@ enum GLDrawItemType
enum DrawListType
{
// These are organized so that the various multipass rendering modes
// have to be set as few times as possible
GLDL_LIGHT,
GLDL_LIGHTBRIGHT,
GLDL_LIGHTMASKED,
GLDL_LIGHTFOG,
GLDL_LIGHTFOGMASKED,
GLDL_PLAIN,
GLDL_MASKED,
GLDL_FOG,
@ -30,25 +22,15 @@ enum DrawListType
GLDL_TRANSLUCENTBORDER,
GLDL_TYPES,
GLDL_FIRSTLIGHT = GLDL_LIGHT,
GLDL_LASTLIGHT = GLDL_LIGHTFOGMASKED,
GLDL_FIRSTNOLIGHT = GLDL_PLAIN,
GLDL_LASTNOLIGHT = GLDL_FOGMASKED,
};
enum Drawpasses
{
GLPASS_BASE, // Draws the untextured surface only
GLPASS_BASE_MASKED, // Draws an untextured surface that is masked by the texture
GLPASS_PLAIN, // Draws a texture that isn't affected by dynamic lights with sector light settings
GLPASS_LIGHT, // Draws dynamic lights
GLPASS_LIGHT_ADDITIVE, // Draws additive dynamic lights
GLPASS_TEXTURE, // Draws the texture to be modulated with the light information on the base surface
GLPASS_PLAIN, // Main pass without dynamic lights
GLPASS_ALL, // Main pass with dynamic lights
GLPASS_DECALS, // Draws a decal
GLPASS_DECALS_NOFOG,// Draws a decal without setting the fog (used for passes that need a fog layer)
GLPASS_TRANSLUCENT, // Draws translucent objects
GLPASS_ALL // Everything at once, using shaders for dynamic lights
};
//==========================================================================

View file

@ -103,22 +103,20 @@ void gl_SetPlaneTextureRotation(const GLSectorPlane * secplane, FMaterial * glte
}
//==========================================================================
//
// Flats
//
//==========================================================================
extern FDynLightData lightdata;
void GLFlat::DrawSubsectorLights(subsector_t * sub, int pass)
bool GLFlat::SetupSubsectorLights(bool lightsapplied, subsector_t * sub)
{
Plane p;
Vector nearPt, up, right, t1;
float scale;
unsigned int k;
seg_t *v;
FLightNode * node = sub->lighthead[pass==GLPASS_LIGHT_ADDITIVE];
gl_RenderState.Apply();
lightdata.Clear();
FLightNode * node = sub->lighthead;
while (node)
{
ADynamicLight * light = node->lightsource;
@ -140,72 +138,9 @@ void GLFlat::DrawSubsectorLights(subsector_t * sub, int pass)
}
p.Set(plane.plane);
if (!gl_SetupLight(p, light, nearPt, up, right, scale, Colormap.desaturation, false, foggy))
{
node=node->nextLight;
continue;
}
draw_dlightf++;
gl_RenderState.Apply();
// Render the light
FFlatVertex *ptr = GLRenderer->mVBO->GetBuffer();
for (k = 0, v = sub->firstline; k < sub->numlines; k++, v++)
{
vertex_t *vt = v->v1;
float zc = plane.plane.ZatPoint(vt->fx, vt->fy) + dz;
t1.Set(vt->fx, zc, vt->fy);
Vector nearToVert = t1 - nearPt;
ptr->Set(vt->fx, zc, vt->fy, (nearToVert.Dot(right) * scale) + 0.5f, (nearToVert.Dot(up) * scale) + 0.5f);
ptr++;
}
GLRenderer->mVBO->RenderCurrent(ptr, GL_TRIANGLE_FAN);
gl_GetLight(p, light, false, false, lightdata);
node = node->nextLight;
}
}
//==========================================================================
//
// Flats
//
//==========================================================================
extern FDynLightData lightdata;
bool GLFlat::SetupSubsectorLights(bool lightsapplied, subsector_t * sub)
{
Plane p;
lightdata.Clear();
for(int i=0;i<2;i++)
{
FLightNode * node = sub->lighthead[i];
while (node)
{
ADynamicLight * light = node->lightsource;
if (light->flags2&MF2_DORMANT)
{
node=node->nextLight;
continue;
}
iter_dlightf++;
// we must do the side check here because gl_SetupLight needs the correct plane orientation
// which we don't have for Legacy-style 3D-floors
fixed_t planeh = plane.plane.ZatPoint(light->x, light->y);
if (gl_lights_checkside && ((planeh<light->z && ceiling) || (planeh>light->z && !ceiling)))
{
node=node->nextLight;
continue;
}
p.Set(plane.plane);
gl_GetLight(p, light, false, false, lightdata);
node = node->nextLight;
}
}
int numlights[3];
@ -347,7 +282,6 @@ void GLFlat::DrawSubsectors(int pass, bool istrans)
//==========================================================================
void GLFlat::Draw(int pass)
{
int i;
int rel = getExtraLight();
#ifdef _DEBUG
@ -360,65 +294,15 @@ void GLFlat::Draw(int pass)
switch (pass)
{
case GLPASS_BASE:
gl_SetColor(lightlevel, rel, Colormap,1.0f);
if (!foggy) gl_SetFog(lightlevel, rel, &Colormap, false);
DrawSubsectors(pass, false);
break;
case GLPASS_PLAIN: // Single-pass rendering
case GLPASS_ALL:
case GLPASS_BASE_MASKED:
gl_SetColor(lightlevel, rel, Colormap,1.0f);
if (!foggy || pass != GLPASS_BASE_MASKED) gl_SetFog(lightlevel, rel, &Colormap, false);
// fall through
case GLPASS_TEXTURE:
{
gl_SetFog(lightlevel, rel, &Colormap, false);
gltexture->Bind();
gl_SetPlaneTextureRotation(&plane, gltexture);
DrawSubsectors(pass, false);
gl_RenderState.EnableTextureMatrix(false);
break;
}
case GLPASS_LIGHT:
case GLPASS_LIGHT_ADDITIVE:
if (!foggy) gl_SetFog((255+lightlevel)>>1, 0, &Colormap, false);
else gl_SetFog(lightlevel, 0, &Colormap, true);
if (sub)
{
DrawSubsectorLights(sub, pass);
}
else
{
// Draw the subsectors belonging to this sector
for (i=0; i<sector->subsectorcount; i++)
{
subsector_t * sub = sector->subsectors[i];
if (gl_drawinfo->ss_renderflags[sub-subsectors]&renderflags)
{
DrawSubsectorLights(sub, pass);
}
}
// Draw the subsectors assigned to it due to missing textures
if (!(renderflags&SSRF_RENDER3DPLANES))
{
gl_subsectorrendernode * node = (renderflags&SSRF_RENDERFLOOR)?
gl_drawinfo->GetOtherFloorPlanes(sector->sectornum) :
gl_drawinfo->GetOtherCeilingPlanes(sector->sectornum);
while (node)
{
DrawSubsectorLights(node->sub, pass);
node = node->next;
}
}
}
break;
case GLPASS_TRANSLUCENT:
if (renderstyle==STYLE_Add) gl_RenderState.BlendFunc(GL_SRC_ALPHA, GL_ONE);
@ -462,38 +346,15 @@ inline void GLFlat::PutFlat(bool fog)
}
if (renderstyle!=STYLE_Translucent || alpha < 1.f - FLT_EPSILON || fog)
{
int list = (renderflags&SSRF_RENDER3DPLANES) ? GLDL_TRANSLUCENT : GLDL_TRANSLUCENTBORDER;
gl_drawinfo->drawlists[list].AddFlat (this);
// translucent 3D floors go into the regular translucent list, translucent portals go into the translucent border list.
list = (renderflags&SSRF_RENDER3DPLANES) ? GLDL_TRANSLUCENT : GLDL_TRANSLUCENTBORDER;
}
else if (gltexture != NULL)
{
static DrawListType list_indices[2][2][2]={
{ { GLDL_PLAIN, GLDL_FOG }, { GLDL_MASKED, GLDL_FOGMASKED } },
{ { GLDL_LIGHT, GLDL_LIGHTFOG }, { GLDL_LIGHTMASKED, GLDL_LIGHTFOGMASKED } }
};
bool light = false;
bool masked = gltexture->isMasked() && ((renderflags&SSRF_RENDER3DPLANES) || stack);
if (!gl_fixedcolormap)
{
foggy = gl_CheckFog(&Colormap, lightlevel) || level.flags&LEVEL_HASFADETABLE;
if (gl_lights && !gl_dynlight_shader && GLRenderer->mLightCount) // Are lights touching this sector?
{
for(int i=0;i<sector->subsectorcount;i++) if (sector->subsectors[i]->lighthead[0] != NULL)
{
light=true;
}
}
}
else foggy = false;
list = list_indices[light][masked][foggy];
if (list == GLDL_LIGHT && gltexture->tex->gl_info.Brightmap) list = GLDL_LIGHTBRIGHT;
gl_drawinfo->drawlists[list].AddFlat (this);
list = masked ? GLDL_MASKED : GLDL_PLAIN;
}
gl_drawinfo->drawlists[list].AddFlat (this);
}
//==========================================================================

View file

@ -144,7 +144,7 @@ void GLPortal::DrawPortalStencil()
for (unsigned int i = 0; i<lines.Size(); i++)
{
lines[i].RenderWall(GLWall::RWF_NORENDER, NULL, &mPrimIndices[i * 2]);
lines[i].RenderWall(GLWall::RWF_NORENDER, &mPrimIndices[i * 2]);
}
if (cap)

View file

@ -351,120 +351,31 @@ void FGLRenderer::RenderScene(int recursion)
int pass;
if (mLightCount > 0 && gl_fixedcolormap == CM_DEFAULT && gl_lights && gl_dynlight_shader)
if (mLightCount > 0 && gl_fixedcolormap == CM_DEFAULT && gl_lights)
{
pass = GLPASS_ALL;
}
else if (gl_texture)
else
{
pass = GLPASS_PLAIN;
}
else
{
pass = GLPASS_BASE;
}
gl_RenderState.EnableTexture(gl_texture);
gl_RenderState.EnableBrightmap(gl_fixedcolormap == CM_DEFAULT);
gl_RenderState.EnableBrightmap(true);
gl_drawinfo->drawlists[GLDL_PLAIN].Sort();
gl_drawinfo->drawlists[GLDL_PLAIN].Draw(pass);
gl_drawinfo->drawlists[GLDL_FOG].Sort();
gl_drawinfo->drawlists[GLDL_FOG].Draw(pass);
gl_drawinfo->drawlists[GLDL_LIGHTFOG].Sort();
gl_drawinfo->drawlists[GLDL_LIGHTFOG].Draw(pass);
// Part 2: masked geometry. This is set up so that only pixels with alpha>0.5 will show
// Part 2: masked geometry. This is set up so that only pixels with alpha>gl_mask_threshold will show
if (!gl_texture)
{
gl_RenderState.EnableTexture(true);
gl_RenderState.SetTextureMode(TM_MASK);
}
if (pass == GLPASS_BASE) pass = GLPASS_BASE_MASKED;
gl_RenderState.AlphaFunc(GL_GEQUAL, gl_mask_threshold);
gl_drawinfo->drawlists[GLDL_MASKED].Sort();
gl_drawinfo->drawlists[GLDL_MASKED].Draw(pass);
gl_drawinfo->drawlists[GLDL_FOGMASKED].Sort();
gl_drawinfo->drawlists[GLDL_FOGMASKED].Draw(pass);
gl_drawinfo->drawlists[GLDL_LIGHTFOGMASKED].Sort();
gl_drawinfo->drawlists[GLDL_LIGHTFOGMASKED].Draw(pass);
// And now the multipass stuff
if (!gl_dynlight_shader && gl_lights)
{
// First pass: empty background with sector light only
// Part 1: solid geometry. This is set up so that there are no transparent parts
// remove any remaining texture bindings and shaders whick may get in the way.
gl_RenderState.EnableTexture(false);
gl_RenderState.EnableBrightmap(false);
gl_RenderState.Apply();
gl_drawinfo->drawlists[GLDL_LIGHT].Draw(GLPASS_BASE);
gl_RenderState.EnableTexture(true);
// Part 2: masked geometry. This is set up so that only pixels with alpha>0.5 will show
// This creates a blank surface that only fills the nontransparent parts of the texture
gl_RenderState.SetTextureMode(TM_MASK);
gl_RenderState.EnableBrightmap(true);
gl_drawinfo->drawlists[GLDL_LIGHTBRIGHT].Draw(GLPASS_BASE_MASKED);
gl_drawinfo->drawlists[GLDL_LIGHTMASKED].Draw(GLPASS_BASE_MASKED);
gl_RenderState.EnableBrightmap(false);
gl_RenderState.SetTextureMode(TM_MODULATE);
// second pass: draw lights (on fogged surfaces they are added to the textures!)
glDepthMask(false);
if (mLightCount && !gl_fixedcolormap)
{
if (gl_SetupLightTexture())
{
gl_RenderState.BlendFunc(GL_ONE, GL_ONE);
glDepthFunc(GL_EQUAL);
gl_RenderState.SetSoftLightLevel(255);
for(int i=GLDL_FIRSTLIGHT; i<=GLDL_LASTLIGHT; i++)
{
gl_drawinfo->drawlists[i].Draw(GLPASS_LIGHT);
}
gl_RenderState.BlendEquation(GL_FUNC_ADD);
}
else gl_lights=false;
}
// third pass: modulated texture
gl_RenderState.ResetColor();
gl_RenderState.BlendFunc(GL_DST_COLOR, GL_ZERO);
gl_RenderState.EnableFog(false);
glDepthFunc(GL_LEQUAL);
if (gl_texture)
{
gl_RenderState.AlphaFunc(GL_GEQUAL, 0.f);
gl_drawinfo->drawlists[GLDL_LIGHT].Sort();
gl_drawinfo->drawlists[GLDL_LIGHT].Draw(GLPASS_TEXTURE);
gl_RenderState.AlphaFunc(GL_GEQUAL, gl_mask_threshold);
gl_drawinfo->drawlists[GLDL_LIGHTBRIGHT].Sort();
gl_drawinfo->drawlists[GLDL_LIGHTBRIGHT].Draw(GLPASS_TEXTURE);
gl_drawinfo->drawlists[GLDL_LIGHTMASKED].Sort();
gl_drawinfo->drawlists[GLDL_LIGHTMASKED].Draw(GLPASS_TEXTURE);
}
// fourth pass: additive lights
gl_RenderState.EnableFog(true);
if (gl_lights && mLightCount && !gl_fixedcolormap)
{
gl_RenderState.BlendFunc(GL_ONE, GL_ONE);
glDepthFunc(GL_EQUAL);
if (gl_SetupLightTexture())
{
for(int i=0; i<GLDL_TRANSLUCENT; i++)
{
gl_drawinfo->drawlists[i].Draw(GLPASS_LIGHT_ADDITIVE);
}
gl_RenderState.BlendEquation(GL_FUNC_ADD);
}
else gl_lights=false;
}
}
gl_RenderState.BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

View file

@ -511,6 +511,7 @@ void GLSkyPortal::DrawContents()
gl_RenderState.Apply();
glDrawArrays(GL_TRIANGLES, 0, 12);
gl_RenderState.EnableTexture(true);
gl_RenderState.SetObjectColor(0xffffffff);
}
gl_RenderState.SetVertexBuffer(GLRenderer->mVBO);
}

View file

@ -112,7 +112,7 @@ CVAR(Bool, gl_nolayer, false, 0)
//==========================================================================
void GLSprite::Draw(int pass)
{
if (pass!=GLPASS_PLAIN && pass != GLPASS_ALL && pass!=GLPASS_TRANSLUCENT) return;
if (pass == GLPASS_DECALS) return;

View file

@ -71,47 +71,44 @@ void gl_SetDynSpriteLight(AActor *self, fixed_t x, fixed_t y, fixed_t z, subsect
float out[3] = { 0.0f, 0.0f, 0.0f };
// Go through both light lists
for (int i = 0; i < 2; i++)
FLightNode * node = subsec->lighthead;
while (node)
{
FLightNode * node = subsec->lighthead[i];
while (node)
light=node->lightsource;
if (!light->owned || light->target == NULL || light->target->IsVisibleToPlayer())
{
light = node->lightsource;
if (!light->owned || light->target == NULL || light->target->IsVisibleToPlayer())
if (!(light->flags2&MF2_DORMANT) &&
(!(light->flags4&MF4_DONTLIGHTSELF) || light->target != self))
{
if (!(light->flags2&MF2_DORMANT) &&
(!(light->flags4&MF4_DONTLIGHTSELF) || light->target != self))
float dist = FVector3(FIXED2FLOAT(x - light->x), FIXED2FLOAT(y - light->y), FIXED2FLOAT(z - light->z)).Length();
radius = light->GetRadius() * gl_lights_size;
if (dist < radius)
{
float dist = FVector3(FIXED2FLOAT(x - light->x), FIXED2FLOAT(y - light->y), FIXED2FLOAT(z - light->z)).Length();
radius = light->GetRadius() * gl_lights_size;
frac = 1.0f - (dist / radius);
if (dist < radius)
if (frac > 0)
{
frac = 1.0f - (dist / radius);
if (frac > 0)
lr = light->GetRed() / 255.0f * gl_lights_intensity;
lg = light->GetGreen() / 255.0f * gl_lights_intensity;
lb = light->GetBlue() / 255.0f * gl_lights_intensity;
if (light->IsSubtractive())
{
lr = light->GetRed() / 255.0f * gl_lights_intensity;
lg = light->GetGreen() / 255.0f * gl_lights_intensity;
lb = light->GetBlue() / 255.0f * gl_lights_intensity;
if (light->IsSubtractive())
{
float bright = FVector3(lr, lg, lb).Length();
FVector3 lightColor(lr, lg, lb);
lr = (bright - lr) * -1;
lg = (bright - lg) * -1;
lb = (bright - lb) * -1;
}
out[0] += lr * frac;
out[1] += lg * frac;
out[2] += lb * frac;
float bright = FVector3(lr, lg, lb).Length();
FVector3 lightColor(lr, lg, lb);
lr = (bright - lr) * -1;
lg = (bright - lg) * -1;
lb = (bright - lb) * -1;
}
out[0] += lr * frac;
out[1] += lg * frac;
out[2] += lb * frac;
}
}
}
node = node->nextLight;
}
node = node->nextLight;
}
gl_RenderState.SetDynLight(out[0], out[1], out[2]);
}

View file

@ -169,7 +169,7 @@ private:
void SetupLights();
bool PrepareLight(texcoord * tcs, ADynamicLight * light);
void RenderWall(int textured, ADynamicLight * light=NULL, unsigned int *store = NULL);
void RenderWall(int textured, unsigned int *store = NULL);
void FloodPlane(int pass);

View file

@ -114,9 +114,8 @@ void GLWall::PutWall(bool translucent)
4, //RENDERWALL_SECTORSTACK, // special
4, //RENDERWALL_PLANEMIRROR, // special
4, //RENDERWALL_MIRROR, // special
1, //RENDERWALL_MIRRORSURFACE, // needs special handling
2, //RENDERWALL_M2SNF, // depends on render and texture settings, no fog
2, //RENDERWALL_M2SFOG, // depends on render and texture settings, no fog
1, //RENDERWALL_MIRRORSURFACE, // only created here from RENDERWALL_MIRROR
2, //RENDERWALL_M2SNF, // depends on render and texture settings, no fog, used on mid texture lines with a fog boundary.
3, //RENDERWALL_COLOR, // translucent
2, //RENDERWALL_FFBLOCK // depends on render and texture settings
4, //RENDERWALL_COLORLAYER // color layer needs special handling
@ -145,47 +144,11 @@ void GLWall::PutWall(bool translucent)
}
else if (passflag[type]!=4) // non-translucent walls
{
static DrawListType list_indices[2][2][2]={
{ { GLDL_PLAIN, GLDL_FOG }, { GLDL_MASKED, GLDL_FOGMASKED } },
{ { GLDL_LIGHT, GLDL_LIGHTFOG }, { GLDL_LIGHTMASKED, GLDL_LIGHTFOGMASKED } }
};
bool masked;
bool light = false;
if (!gl_fixedcolormap)
{
if (gl_lights && !gl_dynlight_shader)
{
if (seg->sidedef == NULL)
{
light = false;
}
else if (!(seg->sidedef->Flags & WALLF_POLYOBJ))
{
light = seg->sidedef->lighthead[0] != NULL;
}
else if (sub)
{
// for polyobjects we cannot use the side's light list.
// We must use the subsector's.
light = sub->lighthead[0] != NULL;
}
}
}
else
{
flags&=~GLWF_FOGGY;
}
masked = passflag[type]==1? false : (light && type!=RENDERWALL_FFBLOCK) || (gltexture && gltexture->isMasked());
list = list_indices[light][masked][!!(flags&GLWF_FOGGY)];
if (list == GLDL_LIGHT)
{
if (gltexture->tex->gl_info.Brightmap) list = GLDL_LIGHTBRIGHT;
if (flags & GLWF_GLOW) list = GLDL_LIGHTBRIGHT;
}
masked = passflag[type]==1? false : (gltexture && gltexture->isMasked());
list = masked ? GLDL_MASKED : GLDL_PLAIN;
gl_drawinfo->drawlists[list].AddWall(this);
}
@ -1514,11 +1477,12 @@ void GLWall::Process(seg_t *seg, sector_t * frontsector, sector_t * backsector)
glseg.x2= FIXED2FLOAT(v2->x);
glseg.y2= FIXED2FLOAT(v2->y);
Colormap=frontsector->ColorMap;
flags = (!gl_isBlack(Colormap.FadeColor) || level.flags&LEVEL_HASFADETABLE)? GLWF_FOGGY : 0;
flags = 0;
int rel = 0;
int orglightlevel = gl_ClampLight(frontsector->lightlevel);
lightlevel = gl_ClampLight(seg->sidedef->GetLightLevel(!!(flags&GLWF_FOGGY), orglightlevel, false, &rel));
bool foggy = (!gl_isBlack(Colormap.FadeColor) || level.flags&LEVEL_HASFADETABLE); // fog disables fake contrast
lightlevel = gl_ClampLight(seg->sidedef->GetLightLevel(foggy, orglightlevel, false, &rel));
if (orglightlevel >= 253) // with the software renderer fake contrast won't be visible above this.
{
rellight = 0;
@ -1764,7 +1728,7 @@ void GLWall::ProcessLowerMiniseg(seg_t *seg, sector_t * frontsector, sector_t *
glseg.fracleft = 0;
glseg.fracright = 1;
flags = (!gl_isBlack(Colormap.FadeColor) || level.flags&LEVEL_HASFADETABLE)? GLWF_FOGGY : 0;
flags = 0;
// can't do fake contrast without a sidedef
lightlevel = gl_ClampLight(frontsector->lightlevel);

View file

@ -62,57 +62,6 @@
EXTERN_CVAR(Bool, gl_seamless)
//==========================================================================
//
// Sets up the texture coordinates for one light to be rendered
//
//==========================================================================
bool GLWall::PrepareLight(texcoord * tcs, ADynamicLight * light)
{
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;
Vector nearPt, up, right;
float scale;
p.Init(vtx,4);
if (!p.ValidNormal())
{
return false;
}
if (!gl_SetupLight(p, light, nearPt, up, right, scale, Colormap.desaturation, true, !!(flags&GLWF_FOGGY)))
{
return false;
}
if (tcs != NULL)
{
Vector t1;
int outcnt[4]={0,0,0,0};
for(int i=0;i<4;i++)
{
t1.Set(&vtx[i*3]);
Vector nearToVert = t1 - nearPt;
tcs[i].u = (nearToVert.Dot(right) * scale) + 0.5f;
tcs[i].v = (nearToVert.Dot(up) * scale) + 0.5f;
// quick check whether the light touches this polygon
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]++;
}
// The light doesn't touch this polygon
if (outcnt[0]==4 || outcnt[1]==4 || outcnt[2]==4 || outcnt[3]==4) return false;
}
draw_dlight++;
return true;
}
//==========================================================================
//
// Collect lights for shader
@ -132,77 +81,74 @@ void GLWall::SetupLights()
{
return;
}
for(int i=0;i<2;i++)
FLightNode *node;
if (seg->sidedef == NULL)
{
FLightNode *node;
if (seg->sidedef == NULL)
{
node = NULL;
}
else if (!(seg->sidedef->Flags & WALLF_POLYOBJ))
{
node = seg->sidedef->lighthead[i];
}
else if (sub)
{
// Polobject segs cannot be checked per sidedef so use the subsector instead.
node = sub->lighthead[i];
}
else node = 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)
// Iterate through all dynamic lights which touch this wall and render them
while (node)
{
if (!(node->lightsource->flags2&MF2_DORMANT))
{
if (!(node->lightsource->flags2&MF2_DORMANT))
iter_dlight++;
Vector fn, pos;
float x = FIXED2FLOAT(node->lightsource->x);
float y = FIXED2FLOAT(node->lightsource->y);
float z = FIXED2FLOAT(node->lightsource->z);
float dist = fabsf(p.DistToPoint(x, z, y));
float radius = (node->lightsource->GetRadius() * gl_lights_size);
float scale = 1.0f / ((2.f * radius) - dist);
if (radius > 0.f && dist < radius)
{
iter_dlight++;
Vector nearPt, up, right;
Vector fn, pos;
pos.Set(x,z,y);
fn=p.Normal();
fn.GetRightUp(right, up);
float x = FIXED2FLOAT(node->lightsource->x);
float y = FIXED2FLOAT(node->lightsource->y);
float z = FIXED2FLOAT(node->lightsource->z);
float dist = fabsf(p.DistToPoint(x, z, y));
float radius = (node->lightsource->GetRadius() * gl_lights_size);
float scale = 1.0f / ((2.f * radius) - dist);
Vector tmpVec = fn * dist;
nearPt = pos + tmpVec;
if (radius > 0.f && dist < radius)
Vector 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++)
{
Vector nearPt, up, right;
t1.Set(&vtx[i*3]);
Vector nearToVert = t1 - nearPt;
tcs[i].u = (nearToVert.Dot(right) * scale) + 0.5f;
tcs[i].v = (nearToVert.Dot(up) * scale) + 0.5f;
pos.Set(x,z,y);
fn=p.Normal();
fn.GetRightUp(right, up);
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]++;
Vector tmpVec = fn * dist;
nearPt = pos + tmpVec;
Vector 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.Set(&vtx[i*3]);
Vector nearToVert = t1 - nearPt;
tcs[i].u = (nearToVert.Dot(right) * scale) + 0.5f;
tcs[i].v = (nearToVert.Dot(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)
{
gl_GetLight(p, node->lightsource, true, false, lightdata);
}
}
if (outcnt[0]!=4 && outcnt[1]!=4 && outcnt[2]!=4 && outcnt[3]!=4)
{
gl_GetLight(p, node->lightsource, true, false, lightdata);
}
}
node = node->nextLight;
}
node = node->nextLight;
}
int numlights[3];
@ -223,29 +169,20 @@ void GLWall::SetupLights()
//
//==========================================================================
void GLWall::RenderWall(int textured, ADynamicLight * light, unsigned int *store)
void GLWall::RenderWall(int textured, unsigned int *store)
{
static texcoord tcs[4]; // making this variable static saves us a relatively costly stack integrity check.
bool split = (gl_seamless && !(textured&RWF_NOSPLIT) && seg->sidedef != NULL && !(seg->sidedef->Flags & WALLF_POLYOBJ));
if (!light)
tcs[0]=lolft;
tcs[1]=uplft;
tcs[2]=uprgt;
tcs[3]=lorgt;
if ((flags&GLWF_GLOW) && (textured & RWF_GLOW))
{
tcs[0]=lolft;
tcs[1]=uplft;
tcs[2]=uprgt;
tcs[3]=lorgt;
if ((flags&GLWF_GLOW) && (textured & RWF_GLOW))
{
gl_RenderState.SetGlowPlanes(topplane, bottomplane);
gl_RenderState.SetGlowParams(topglowcolor, bottomglowcolor);
}
gl_RenderState.SetGlowPlanes(topplane, bottomplane);
gl_RenderState.SetGlowParams(topglowcolor, bottomglowcolor);
}
else
{
if (!PrepareLight(tcs, light)) return;
}
if (!(textured & RWF_NORENDER))
{
@ -422,7 +359,6 @@ void GLWall::RenderTranslucentWall()
//==========================================================================
void GLWall::Draw(int pass)
{
FLightNode * node;
int rel;
#ifdef _DEBUG
@ -461,64 +397,6 @@ void GLWall::Draw(int pass)
gl_RenderState.EnableLight(false);
break;
case GLPASS_BASE: // Base pass for non-masked polygons (all opaque geometry)
case GLPASS_BASE_MASKED: // Base pass for masked polygons (2sided mid-textures and transparent 3D floors)
rel = rellight + getExtraLight();
gl_SetColor(lightlevel, rel, Colormap,1.0f);
if (!(flags&GLWF_FOGGY))
{
if (type!=RENDERWALL_M2SNF) gl_SetFog(lightlevel, rel, &Colormap, false);
else gl_SetFog(255, 0, NULL, false);
}
gl_RenderState.EnableGlow(!!(flags & GLWF_GLOW));
// fall through
if (pass != GLPASS_BASE)
{
gltexture->Bind(flags, 0);
}
RenderWall(RWF_TEXTURED|RWF_GLOW);
gl_RenderState.EnableGlow(false);
gl_RenderState.EnableLight(false);
break;
case GLPASS_TEXTURE: // modulated texture
gltexture->Bind(flags, 0);
RenderWall(RWF_TEXTURED);
break;
case GLPASS_LIGHT:
case GLPASS_LIGHT_ADDITIVE:
// black fog is diminishing light and should affect lights less than the rest!
if (!(flags&GLWF_FOGGY)) gl_SetFog((255+lightlevel)>>1, 0, NULL, false);
else gl_SetFog(lightlevel, 0, &Colormap, true);
if (seg->sidedef == NULL)
{
node = NULL;
}
else if (!(seg->sidedef->Flags & WALLF_POLYOBJ))
{
// Iterate through all dynamic lights which touch this wall and render them
node = seg->sidedef->lighthead[pass==GLPASS_LIGHT_ADDITIVE];
}
else if (sub)
{
// To avoid constant rechecking for polyobjects use the subsector's lightlist instead
node = sub->lighthead[pass==GLPASS_LIGHT_ADDITIVE];
}
else node = NULL;
while (node)
{
if (!(node->lightsource->flags2&MF2_DORMANT))
{
iter_dlight++;
RenderWall(RWF_TEXTURED, node->lightsource);
}
node = node->nextLight;
}
break;
case GLPASS_DECALS:
case GLPASS_DECALS_NOFOG:
if (seg->sidedef && seg->sidedef->AttachedDecals)

View file

@ -772,7 +772,7 @@ struct sector_t
int subsectorcount; // list of subsectors
subsector_t ** subsectors;
FPortal * portals[2]; // floor and ceiling portals
FLightNode * lighthead[2];
FLightNode * lighthead;
enum
{
@ -949,7 +949,7 @@ struct side_t
vertex_t *V2() const;
//For GL
FLightNode * lighthead[2]; // all blended lights that may affect this wall
FLightNode * lighthead; // all blended lights that may affect this wall
seg_t **segs; // all segs belonging to this sidedef in ascending order. Used for precise rendering
int numsegs;
@ -1082,7 +1082,7 @@ struct subsector_t
void BuildPolyBSP();
// subsector related GL data
FLightNode * lighthead[2]; // Light nodes (blended and additive)
FLightNode * lighthead; // Light nodes (blended and additive)
int validcount;
short mapsection;
char hacked; // 1: is part of a render hack

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB