Further cleanup of lighting code.

- remove thing color from lighting calculations.
- implement alpha textures and inverse sprites for infrared as texture modes. This still requires some handling for the alpha texture mode for non-shader rendering because there is no way in the fixed pipeline to do it. The inverted texture effect can be done with a texture combiner.
- fixed: ThingColor for sprites was set in the wrong place. It must be in the Process function, not in the lighting calculation.
- added functions for isolated calculation of sprites' dynlight color.
This commit is contained in:
Christoph Oelckers 2014-05-11 17:56:38 +02:00
parent 607be91c48
commit 7793bbbcc9
11 changed files with 133 additions and 72 deletions

View file

@ -160,13 +160,17 @@ void gl_GetRenderStyle(FRenderStyle style, bool drawopaque, bool allowcolorblend
int blendequation = renderops[style.BlendOp&15];
int texturemode = drawopaque? TM_OPAQUE : TM_MODULATE;
if (style.Flags & STYLEF_ColorIsFixed)
if (style.Flags & STYLEF_RedIsAlpha)
{
texturemode = TM_REDTOALPHA;
}
else if (style.Flags & STYLEF_ColorIsFixed)
{
texturemode = TM_MASK;
}
else if (style.Flags & STYLEF_InvertSource)
{
texturemode = drawopaque? TM_INVERTOPAQUE : TM_INVERT;
texturemode = TM_INVERSE;
}
if (blendequation == -1)
@ -316,14 +320,9 @@ void gl_GetLightColor(int lightlevel, int rellight, const FColormap * cm, float
// set current light color
//
//==========================================================================
void gl_SetColor(int light, int rellight, const FColormap * cm, float *red, float *green, float *blue, PalEntry ThingColor, bool weapon)
void gl_SetColor(int light, int rellight, const FColormap * cm, float *red, float *green, float *blue, bool weapon)
{
float r,g,b;
gl_GetLightColor(light, rellight, cm, &r, &g, &b, weapon);
*red = r * ThingColor.r/255.0f;
*green = g * ThingColor.g/255.0f;
*blue = b * ThingColor.b/255.0f;
gl_GetLightColor(light, rellight, cm, red, green, blue, weapon);
}
//==========================================================================
@ -331,20 +330,15 @@ void gl_SetColor(int light, int rellight, const FColormap * cm, float *red, floa
// set current light color
//
//==========================================================================
void gl_SetColor(int light, int rellight, const FColormap * cm, float alpha, PalEntry ThingColor, bool weapon)
void gl_SetColor(int light, int rellight, const FColormap * cm, float alpha, bool weapon)
{
float r,g,b;
gl_GetLightColor(light, rellight, cm, &r, &g, &b, weapon);
if (glset.lightmode != 8)
gl_RenderState.SetColor(r, g, b, alpha);
if (glset.lightmode == 8)
{
glColor4f(r * ThingColor.r/255.0f, g * ThingColor.g/255.0f, b * ThingColor.b/255.0f, alpha);
}
else
{
glColor4f(r, g, b, alpha);
if (gl_fixedcolormap)
{
glVertexAttrib1f(VATTR_LIGHTLEVEL, 1.0);

View file

@ -20,8 +20,7 @@ void gl_SetFogParams(int _fogdensity, PalEntry _outsidefogcolor, int _outsidefog
int gl_CalcLightLevel(int lightlevel, int rellight, bool weapon);
PalEntry gl_CalcLightColor(int light, PalEntry pe, int blendfactor, bool force = false);
void gl_GetLightColor(int lightlevel, int rellight, const FColormap * cm, float * pred, float * pgreen, float * pblue, bool weapon=false);
void gl_SetColor(int light, int rellight, const FColormap * cm, float alpha, PalEntry ThingColor = 0xffffff, bool weapon=false);
void gl_SetColor(int light, int rellight, const FColormap * cm, float *red, float *green, float *blue, PalEntry ThingColor=0xffffff, bool weapon=false);
void gl_SetColor(int light, int rellight, const FColormap * cm, float alpha, bool weapon=false);
float gl_GetFogDensity(int lightlevel, PalEntry fogcolor);
struct sector_t;

View file

@ -338,6 +338,7 @@ void FGLRenderer::DrawTexture(FTexture *img, DCanvas::DrawParms &parms)
else
{
// This is an alpha texture
gl_RenderState.SetTextureMode(TM_REDTOALPHA);
gltex->BindPatch(CM_SHADE, 0);
}

View file

@ -377,7 +377,7 @@ void GLWall::DrawDecal(DBaseDecal *decal)
{
if (glset.lightmode == 8)
{
gl_SetColor(light, rel, &p, a, extralight); // Korshun.
gl_SetColor(light, rel, &p, a, !!extralight); // Korshun.
}
else
{

View file

@ -169,7 +169,7 @@ void GLSprite::Draw(int pass)
}
gl_RenderState.AlphaFunc(GL_GEQUAL,minalpha*gl_mask_sprite_threshold);
glColor4f(0.2f,0.2f,0.2f,fuzzalpha);
gl_RenderState.SetColor(0.2f,0.2f,0.2f,fuzzalpha);
additivefog = true;
}
else if (RenderStyle.BlendOp == STYLEOP_Add && RenderStyle.DestAlpha == STYLEALPHA_One)
@ -181,22 +181,23 @@ void GLSprite::Draw(int pass)
{
if (actor)
{
lightlevel = gl_SetSpriteLighting(RenderStyle, actor, lightlevel, rel, &Colormap, ThingColor, trans,
lightlevel = gl_SetSpriteLighting(RenderStyle, actor, lightlevel, rel, &Colormap, 0xffffffff, trans,
fullbright || gl_fixedcolormap >= CM_FIRSTSPECIALCOLORMAP, false);
}
else if (particle)
{
if (gl_light_particles)
{
lightlevel = gl_SetSpriteLight(particle, lightlevel, rel, &Colormap, trans, ThingColor);
lightlevel = gl_SetSpriteLight(particle, lightlevel, rel, &Colormap, trans, 0xffffffff);
}
else
{
gl_SetColor(lightlevel, rel, &Colormap, trans, ThingColor);
gl_SetColor(lightlevel, rel, &Colormap, trans);
}
}
else return;
}
gl_RenderState.SetObjectColor(ThingColor);
if (gl_isBlack(Colormap.FadeColor)) foglevel=lightlevel;
@ -425,13 +426,6 @@ void GLSprite::SplitSprite(sector_t * frontsector, bool translucent)
copySprite.Colormap.LightColor.b=(255+v+v)/3;
}
if (!gl_isWhite(ThingColor))
{
copySprite.Colormap.LightColor.r=(copySprite.Colormap.LightColor.r*ThingColor.r)>>8;
copySprite.Colormap.LightColor.g=(copySprite.Colormap.LightColor.g*ThingColor.g)>>8;
copySprite.Colormap.LightColor.b=(copySprite.Colormap.LightColor.b*ThingColor.b)>>8;
}
z1=copySprite.z2=maplightbottom;
vt=copySprite.vb=copySprite.vt+
(maplightbottom-copySprite.z1)*(copySprite.vb-copySprite.vt)/(z2-copySprite.z1);
@ -471,13 +465,6 @@ void GLSprite::SetSpriteColor(sector_t *sector, fixed_t center_y)
Colormap.LightColor.g=
Colormap.LightColor.b=(255+v+v)/3;
}
if (!gl_isWhite(ThingColor))
{
Colormap.LightColor.r=(Colormap.LightColor.r*ThingColor.r)>>8;
Colormap.LightColor.g=(Colormap.LightColor.g*ThingColor.g)>>8;
Colormap.LightColor.b=(Colormap.LightColor.b*ThingColor.b)>>8;
}
return;
}
}
@ -734,6 +721,10 @@ void GLSprite::Process(AActor* thing,sector_t * sector)
lightlevel = (byte)gl_CheckSpriteGlow(rendersector, lightlevel, thingx, thingy, thingz);
ThingColor = (thing->RenderStyle.Flags & STYLEF_ColorIsFixed) ? thing->fillcolor : 0xffffff;
ThingColor.a = 255;
RenderStyle = thing->RenderStyle;
// colormap stuff is a little more complicated here...
if (gl_fixedcolormap)
{
@ -749,8 +740,7 @@ void GLSprite::Process(AActor* thing,sector_t * sector)
if (gl_enhanced_nightvision &&
(thing->IsKindOf(RUNTIME_CLASS(AInventory)) || thing->flags3&MF3_ISMONSTER || thing->flags&MF_MISSILE || thing->flags&MF_CORPSE))
{
// needs to be fixed later
//Colormap.colormap = CM_FIRSTSPECIALCOLORMAP + INVERSECOLORMAP;
RenderStyle.Flags |= STYLEF_InvertSource;
}
}
}
@ -785,8 +775,6 @@ void GLSprite::Process(AActor* thing,sector_t * sector)
translation=thing->Translation;
ThingColor=0xffffff;
RenderStyle = thing->RenderStyle;
OverrideShader = 0;
trans = FIXED2FLOAT(thing->alpha);
hw_styleflags = STYLEHW_Normal;
@ -955,8 +943,7 @@ void GLSprite::ProcessParticle (particle_t *particle, sector_t *sector)//, int s
OverrideShader = 0;
ThingColor = particle->color;
gl_ModifyColor(ThingColor.r, ThingColor.g, ThingColor.b, Colormap.colormap);
ThingColor.a=0;
ThingColor.a = 255;
modelframe=NULL;
gltexture=NULL;

View file

@ -57,6 +57,77 @@
#include "gl/textures/gl_material.h"
//==========================================================================
//
// Sets a single light value from all dynamic lights affecting the specified location
//
//==========================================================================
void gl_SetDynSpriteLight(AActor *self, fixed_t x, fixed_t y, fixed_t z, subsector_t * subsec)
{
ADynamicLight *light;
float frac, lr, lg, lb;
float radius;
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[i];
while (node)
{
light = node->lightsource;
if (!light->owned || light->target == NULL || light->target->IsVisibleToPlayer())
{
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)
{
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())
{
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;
}
}
gl_RenderState.SetDynLight(out[0], out[1], out[2]);
}
void gl_SetDynSpriteLight(AActor *thing, particle_t *particle)
{
if (thing != NULL)
{
gl_SetDynSpriteLight(thing, thing->x, thing->y, thing->z + (thing->height >> 1), thing->subsector);
}
else if (particle != NULL)
{
gl_SetDynSpriteLight(NULL, particle->x, particle->y, particle->z, particle->subsector);
}
}
//==========================================================================
//
// Gets the light for a sprite - takes dynamic lights into account
@ -294,7 +365,7 @@ int gl_SetSpriteLighting(FRenderStyle style, AActor *thing, int lightlevel, int
}
else
{
gl_SetColor(lightlevel, rellight, cm, alpha, ThingColor, weapon);
gl_SetColor(lightlevel, rellight, cm, alpha, weapon);
}
}
gl_RenderState.AlphaFunc(GL_GEQUAL,alpha*gl_mask_sprite_threshold);

View file

@ -351,6 +351,10 @@ inline float Dist2(float x1,float y1,float x2,float y2)
// Light + color
void gl_SetDynSpriteLight(AActor *self, fixed_t x, fixed_t y, fixed_t z, subsector_t *subsec);
void gl_SetDynSpriteLight(AActor *actor, particle_t *particle);
bool gl_GetSpriteLight(AActor *Self, fixed_t x, fixed_t y, fixed_t z, subsector_t * subsec, int desaturation, float * out, line_t *line = NULL, int side = 0);
int gl_SetSpriteLight(AActor * thing, int lightlevel, int rellight, FColormap * cm, float alpha, PalEntry ThingColor = 0xffffff, bool weapon=false);

View file

@ -194,8 +194,7 @@ void gl_PrintStartupLog()
void gl_SetTextureMode(int type)
{
static float white[] = {1.f,1.f,1.f,1.f};
gl.needAlphaTexture = false;
if (type == TM_MASK)
{
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
@ -222,7 +221,7 @@ void gl_SetTextureMode(int type)
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_PRIMARY_COLOR);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);
}
else if (type == TM_INVERT)
else if (type == TM_INVERSE)
{
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_MODULATE);
@ -237,22 +236,10 @@ void gl_SetTextureMode(int type)
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA, GL_SRC_ALPHA);
}
else if (type == TM_INVERTOPAQUE)
{
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_MODULATE);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_TEXTURE0);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_PRIMARY_COLOR);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_ONE_MINUS_SRC_COLOR);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_REPLACE);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_PRIMARY_COLOR);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);
}
else // if (type == TM_MODULATE)
{
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
gl.needAlphaTexture = (type == TM_REDTOALPHA);
}
}

View file

@ -16,16 +16,13 @@ enum RenderFlags
enum TexMode
{
TMF_MASKBIT = 1,
TMF_OPAQUEBIT = 2,
TMF_INVERTBIT = 4,
TM_MODULATE = 0, // (r, g, b, a)
TM_MASK = 1, // (1, 1, 1, a)
TM_OPAQUE = 2, // (r, g, b, 1)
TM_INVERSE = 3, // (1-r, 1-g, 1-b, a)
TM_REDTOALPHA = 4, // (1, 1, 1, r)
TM_MODULATE = 0,
TM_MASK = TMF_MASKBIT,
TM_OPAQUE = TMF_OPAQUEBIT,
TM_INVERT = TMF_INVERTBIT,
//TM_INVERTMASK = TMF_MASKBIT | TMF_INVERTBIT
TM_INVERTOPAQUE = TMF_INVERTBIT | TMF_OPAQUEBIT,
// 4 cannot be done natively without shaders and requires special textures.
};
struct RenderContext
@ -36,6 +33,7 @@ struct RenderContext
float glslversion;
int max_texturesize;
char * vendorstring;
bool needAlphaTexture;
int MaxLights() const
{

View file

@ -149,7 +149,17 @@ vec4 getTexel(vec2 st)
//
// Apply texture modes
//
if (texturemode == 2)
if (texturemode == 3)
{
texel *=objectcolor;
texel = vec4(1.0-texel.r, 1.0-texel.g, 1.0-texel.b, texel.a);
return texel;
}
else if (texturemode == 4)
{
texel = vec4(1.0, 1.0, 1.0, texel.r);
}
else if (texturemode == 2)
{
texel.a = 1.0;
}

View file

@ -20,7 +20,17 @@ vec4 getTexel(vec2 st)
//
// Apply texture modes
//
if (texturemode == 2)
if (texturemode == 3)
{
texel *=objectcolor;
texel = vec4(1.0-texel.r, 1.0-texel.g, 1.0-texel.b, texel.a);
return texel;
}
else if (texturemode == 4)
{
texel = vec4(1.0, 1.0, 1.0, texel.r);
}
else if (texturemode == 2)
{
texel.a = 1.0;
}