Skip to content

Commit

Permalink
Begun splitting up RL_VertexColors(). Also, extended the torch lighti…
Browse files Browse the repository at this point in the history
…ng to allow for an RGB color to be specified and added a multiplicative blending mode (implemented for jDoom64's BFG explosion effect).
  • Loading branch information
danij committed Mar 23, 2008
1 parent 20463f6 commit 3f29d68
Show file tree
Hide file tree
Showing 6 changed files with 141 additions and 96 deletions.
4 changes: 4 additions & 0 deletions doomsday/engine/api/dd_share.h
Expand Up @@ -314,6 +314,10 @@ extern "C" {
DD_GRAVITY,
DD_PSPRITE_OFFSET_X, // 10x
DD_PSPRITE_OFFSET_Y, // 10x
DD_TORCH_RED,
DD_TORCH_GREEN,
DD_TORCH_BLUE,
DD_TORCH_ADDITIVE
};

// Bounding box coordinates.
Expand Down
4 changes: 3 additions & 1 deletion doomsday/engine/portable/include/rend_list.h
Expand Up @@ -43,8 +43,10 @@ extern int renderWireframe;
extern int useMultiTexLights;
extern int useMultiTexDetails;

extern float rend_light_wall_angle;
extern float rendLightWallAngle;
extern float detailFactor, detailScale;
extern int torchAdditive;
extern float torchColor[];

void RL_Register(void);
void RL_Init(void);
Expand Down
27 changes: 27 additions & 0 deletions doomsday/engine/portable/src/dd_main.c
Expand Up @@ -1079,6 +1079,17 @@ void* DD_GetVariable(int ddvalue)
case DD_GRAVITY:
return &mapGravity;

case DD_TORCH_RED:
return &torchColor[CR];

case DD_TORCH_GREEN:
return &torchColor[CG];

case DD_TORCH_BLUE:
return &torchColor[CB];

case DD_TORCH_ADDITIVE:
return &torchAdditive;
#ifdef WIN32
case DD_WINDOW_HANDLE:
return Sys_GetWindowHandle(windowIDX);
Expand Down Expand Up @@ -1176,6 +1187,22 @@ void DD_SetVariable(int ddvalue, void *parm)
pspOffset[VY] = *(float*) parm;
return;

case DD_TORCH_RED:
torchColor[CR] = MINMAX_OF(0, *((float*) parm), 1);
return;

case DD_TORCH_GREEN:
torchColor[CG] = MINMAX_OF(0, *((float*) parm), 1);
return;

case DD_TORCH_BLUE:
torchColor[CB] = MINMAX_OF(0, *((float*) parm), 1);
return;

case DD_TORCH_ADDITIVE:
torchAdditive = (*(int*) parm)? true : false;
break;

default:
break;
}
Expand Down
3 changes: 0 additions & 3 deletions doomsday/engine/portable/src/rend_bias.c
Expand Up @@ -840,9 +840,6 @@ void SB_RendPoly(struct rendpoly_s *poly, float sectorLightLevel,
uint i;
boolean forced;

if(!useBias)
return;

// Apply sectorlight bias. Note: Distance darkening is not used
// with bias lights.
if(sectorLightLevel > biasMin && biasMax > biasMin)
Expand Down
148 changes: 79 additions & 69 deletions doomsday/engine/portable/src/rend_list.c
Expand Up @@ -230,14 +230,17 @@ int useMultiTexLights = true;
int useMultiTexDetails = true;

// Intensity of angle-based wall lighting.
float rend_light_wall_angle = 1;
float rendLightWallAngle = 1;

// Rendering parameters for detail textures.
float detailFactor = .5f;

//float detailMaxDist = 256;
float detailScale = 4;

float torchColor[3] = {1, 1, 1};
int torchAdditive = true;

// PRIVATE DATA DEFINITIONS ------------------------------------------------

/**
Expand Down Expand Up @@ -366,6 +369,30 @@ static void addMaskedPoly(rendpoly_t *poly)
}
}

static float wallAngleLightlevelOffset(const rendpoly_t *poly)
{
if(!poly->isWall || !(rendLightWallAngle > 0))
return 0;

// Do a lighting adjustment based on orientation.
return (1.0f / 255.0f) *
((poly->vertices[2].pos[VY] -
poly->vertices[0].pos[VY]) / poly->wall->length * 18 *
rendLightWallAngle);
}

static float distAttenuateLightLevel(float distToViewer, float lightLevel)
{
float real, minimum;

real = lightLevel - (distToViewer - 32) / maxLightDist * (1 - lightLevel);
minimum = lightLevel * lightLevel + (lightLevel - .63f) / 2;
if(real < minimum)
real = minimum; // Clamp it.

return real;
}

/**
* Color distance attenuation, extraLight, fixedcolormap.
* "Torchlight" is white, regardless of the original RGB.
Expand All @@ -375,96 +402,79 @@ static void addMaskedPoly(rendpoly_t *poly)
* calculated if needed, depending on the properties of
* the rendpoly to be lit, for each vertex seperately.
*/
void RL_VertexColors(rendpoly_t *poly, float lightlevel,
float distanceOverride, const float *rgb, float alpha)
void RL_VertexColors(rendpoly_t *poly, float lightLevel,
float distanceOverride, const float sufColor[3],
float alpha)
{
int i, num;
float light, real, minimum;
float dist;
rendpoly_vertex_t *vtx;
boolean usewhite;
int i, num;
float lightVal, dist = distanceOverride;
float rgb[3];
rendpoly_vertex_t *vtx;

// Check for special case exceptions.
if(poly->flags & (RPF_SKY_MASK|RPF_LIGHT|RPF_SHADOW))
{
return; // Don't need per-vertex lighting.
}

if(poly->isWall && rend_light_wall_angle && !useBias) // A quad?
{
// Do a lighting adjustment based on orientation.
lightlevel += (1.0f / 255.0f) *
((poly->vertices[2].pos[VY] -
poly->vertices[0].pos[VY]) / poly->wall->length * 18 *
rend_light_wall_angle);
if(lightlevel < 0)
lightlevel = 0;
if(lightlevel > 1)
lightlevel = 1;
}

if(lightlevel < 0)
light = 1; // Full bright.
else
light = lightlevel;
lightLevel += wallAngleLightlevelOffset(poly);
lightLevel = MINMAX_OF(0, lightLevel, 1);

num = poly->numVertices;
for(i = 0, vtx = poly->vertices; i < num; ++i, vtx++)
{
usewhite = false;

if(distanceOverride > 0)
dist = distanceOverride;
// If this is a glowing surface, boost the light level up.
if(poly->flags & RPF_GLOW)
{
vtx->color.rgba[CR] = vtx->color.rgba[CG] =
vtx->color.rgba[CB] = 255;
}
else
dist = Rend_PointDist2D(vtx->pos);
{
if(!(distanceOverride > 0))
dist = Rend_PointDist2D(vtx->pos);

real = light - (dist - 32) / maxLightDist * (1 - light);
minimum = light * light + (light - .63f) / 2;
if(real < minimum)
real = minimum; // Clamp it.
// Apply distance attenuation.
lightVal = distAttenuateLightLevel(dist, lightLevel);

// Add extra light.
real += extraLight / 16.0f;
// Add extra light.
lightVal += extraLight / 16.0f;

// Check for torch.
if(viewPlayer->fixedColorMap)
{
// Colormap 1 is the brightest. I'm guessing 16 would be
// the darkest.
int ll = 16 - viewPlayer->fixedColorMap;
float d = (1024 - dist) / 512.0f;
float newmin = d * ll / 15.0f;
// Mix with the surface color.
rgb[CR] = lightVal * sufColor[CR];
rgb[CG] = lightVal * sufColor[CG];
rgb[CB] = lightVal * sufColor[CB];

if(real < newmin)
// Check for torch.
if(viewPlayer->fixedColorMap && dist < 1024)
{
real = newmin;
usewhite = true; // \fixme Do some linear blending.
}
}

// If this is a glowing surface, boost the light up.
if(poly->flags & RPF_GLOW)
real = 1;
// Colormap 1 is the brightest. I'm guessing 16 would be
// the darkest.
int ll = 16 - viewPlayer->fixedColorMap;
float d = (1024 - dist) / 1024.0f * ll / 15.0f;

// Clamp the final light.
if(real < 0)
real = 0;
if(real > 1)
real = 1;
if(torchAdditive)
{
rgb[CR] += d * torchColor[CR];
rgb[CG] += d * torchColor[CG];
rgb[CB] += d * torchColor[CB];
}
else
{
rgb[CR] += d * ((rgb[CR] * torchColor[CR]) - rgb[CR]);
rgb[CG] += d * ((rgb[CG] * torchColor[CG]) - rgb[CG]);
rgb[CB] += d * ((rgb[CB] * torchColor[CB]) - rgb[CB]);
}
}

if(usewhite)
{
vtx->color.rgba[0] = vtx->color.rgba[1] = vtx->color.rgba[2] =
(DGLubyte) (0xff * real);
}
else
{
vtx->color.rgba[0] = (DGLubyte) (255 * rgb[0] * real);
vtx->color.rgba[1] = (DGLubyte) (255 * rgb[1] * real);
vtx->color.rgba[2] = (DGLubyte) (255 * rgb[2] * real);
// Set final color.
vtx->color.rgba[CR] = (DGLubyte) (255 * MINMAX_OF(0, rgb[CR], 1));
vtx->color.rgba[CG] = (DGLubyte) (255 * MINMAX_OF(0, rgb[CG], 1));
vtx->color.rgba[CB] = (DGLubyte) (255 * MINMAX_OF(0, rgb[CB], 1));
}

vtx->color.rgba[3] = (DGLubyte) (255 * alpha);
// Set final alpha.
vtx->color.rgba[CA] = (DGLubyte) (255 * MINMAX_OF(0, alpha, 1));
}
}

Expand Down
51 changes: 28 additions & 23 deletions doomsday/engine/portable/src/rend_main.c
Expand Up @@ -168,7 +168,7 @@ void Rend_Register(void)
Rend_CalcLightRangeModMatrix);
C_VAR_INT2("rend-light-sky", &rendSkyLight, 0, 0, 1,
LG_MarkAllForUpdate);
C_VAR_FLOAT("rend-light-wall-angle", &rend_light_wall_angle, CVF_NO_MAX,
C_VAR_FLOAT("rend-light-wall-angle", &rendLightWallAngle, CVF_NO_MAX,
0, 0);
C_VAR_INT("rend-dev-light-modmatrix", &debugLightModMatrix,
CVF_NO_ARCHIVE, 0, 1);
Expand Down Expand Up @@ -1029,9 +1029,12 @@ static void doRenderPlane(rendpoly_t *poly, sector_t *polySector,
else
poly->lightListIdx = DL_ProcessSubSectorPlane(subsector, plane->planeID);

// Do BIAS lighting for this poly.
SB_RendPoly(poly, subsector->sector->lightLevel, plane->illumination,
&plane->tracker, plane->affected, subIndex);
if(useBias)
{
// Do BIAS lighting for this poly.
SB_RendPoly(poly, subsector->sector->lightLevel, plane->illumination,
&plane->tracker, plane->affected, subIndex);
}

// Smooth Texture Animation?
if(flags & RPF2_BLEND)
Expand Down Expand Up @@ -1285,7 +1288,6 @@ static boolean renderSegSection(seg_t *seg, segsection_t section, surface_t *sur
{
const float *topColor = NULL;
const float *bottomColor = NULL;
uint lightListIdx;
float sectorLightLevel = Rend_SectorLight(frontsec);

// Check for neighborhood division?
Expand All @@ -1294,7 +1296,8 @@ static boolean renderSegSection(seg_t *seg, segsection_t section, surface_t *sur

getColorsForSegSection(sideFlags, section, &bottomColor, &topColor);

lightListIdx =
// Dynamic lights.
quad->lightListIdx =
DL_ProcessSegSection(seg, vL_ZBottom, vL_ZTop,
(quad->flags & RPF_MASKED)? true:false);

Expand All @@ -1303,29 +1306,31 @@ static boolean renderSegSection(seg_t *seg, segsection_t section, surface_t *sur
quad->flags |= RPF_GLOW;

// Surface color/light.
RL_VertexColors(quad, sectorLightLevel, -1, topColor, alpha);

// Bottom color (if different from top)?
if(bottomColor != NULL)
if(useBias)
{
// Do BIAS lighting for this poly.
SB_RendPoly(quad, sectorLightLevel, seg->illum[section],
&seg->tracker[section], seg->affected,
GET_SEG_IDX(seg));
}
else
{
uint i;
RL_VertexColors(quad, sectorLightLevel, -1, topColor, alpha);

for(i = 0; i < 4; i += 2)
// Bottom color (if different from top)?
if(bottomColor != NULL)
{
quad->vertices[i].color.rgba[0] = (DGLubyte) (255 * bottomColor[0]);
quad->vertices[i].color.rgba[1] = (DGLubyte) (255 * bottomColor[1]);
quad->vertices[i].color.rgba[2] = (DGLubyte) (255 * bottomColor[2]);
uint i;

for(i = 0; i < 4; i += 2)
{
quad->vertices[i].color.rgba[0] = (DGLubyte) (255 * bottomColor[0]);
quad->vertices[i].color.rgba[1] = (DGLubyte) (255 * bottomColor[1]);
quad->vertices[i].color.rgba[2] = (DGLubyte) (255 * bottomColor[2]);
}
}
}

// Dynamic lights.
quad->lightListIdx = lightListIdx;

// Do BIAS lighting for this poly.
SB_RendPoly(quad, sectorLightLevel, seg->illum[section],
&seg->tracker[section], seg->affected,
GET_SEG_IDX(seg));

// Smooth Texture Animation?
if(tempflags & RPF2_BLEND)
polyTexBlend(quad, surface->material);
Expand Down

0 comments on commit 3f29d68

Please sign in to comment.