Skip to content

Commit

Permalink
Refactor|Renderer|LightGrid: Reimplemented LightGrid
Browse files Browse the repository at this point in the history
Separated IPointLightSource from ILightSource so that the latter can
be used as the base for non-point light sources.

LightGrid::IBlockLightSource (based on ILightSource) is the (abstract)
base for illumination sources. SectorCluster is one such source.

LightGrid light source grid CoverageData is now managed internally.

LightGrid (re)initialization was revised to separate light source
coverage determination from logical grid initialization. New sources
can now be created dynamically without needing to rebuild the logical
grid.

LightGrid no longer observes Sector light color/intensity changes.
Instead, IBlockLightSources are obliged to notify the LightGrid when
their lighting properties change for scheduling of block updates.

Revised LightGrid internal representation to clean up the "null block"
optimization.

Separated the light grid debug visual into rend_main.cpp for now.

The map renderer now obtains the effective lighting properties from
SectorCluster directly (using the same method as IBlockLightSource).

Experimenting with sector light color & intensity as Vector4f.
  • Loading branch information
danij-deng committed Apr 28, 2014
1 parent 357d170 commit 7b82ef6
Show file tree
Hide file tree
Showing 24 changed files with 1,207 additions and 1,087 deletions.
2 changes: 1 addition & 1 deletion doomsday/client/include/render/cameralensfx.h
Expand Up @@ -52,6 +52,6 @@ void LensFx_EndFrame();
/**
* Marks a light potentially visible in the current frame.
*/
void LensFx_MarkLightVisible(ILightSource const &lightSource);
void LensFx_MarkLightVisible(IPointLightSource const &lightSource);

#endif // DENG_CLIENT_CAMERALENSFX_H
2 changes: 1 addition & 1 deletion doomsday/client/include/render/fx/lensflares.h
Expand Up @@ -33,7 +33,7 @@ class LensFlares : public ConsoleEffect
LensFlares(int console);

void clearLights();
void markLightPotentiallyVisibleForCurrentFrame(ILightSource const *lightSource);
void markLightPotentiallyVisibleForCurrentFrame(IPointLightSource const *lightSource);

void glInit();
void glDeinit();
Expand Down
45 changes: 29 additions & 16 deletions doomsday/client/include/render/ilightsource.h
@@ -1,4 +1,4 @@
/** @file ilightsource.h Interface for a light source.
/** @file ilightsource.h Interface for a point light source.
*
* @authors Copyright (c) 2013 Jaakko Keränen <jaakko.keranen@iki.fi>
*
Expand Down Expand Up @@ -34,8 +34,6 @@
class ILightSource
{
public:
typedef de::Vector3d Origin;

/**
* Unique identifier of the source. This can be used to uniquely identify a
* source of light across multiple frames.
Expand All @@ -52,17 +50,6 @@ class ILightSource

virtual LightId lightSourceId() const = 0;

/**
* Returns the position of the light source, in map units.
*/
virtual Origin lightSourceOrigin() const = 0;

/**
* Returns the radius of the emitter itself, in map units. A radius of
* zero would mean that the light emitter is an infinitely small point.
*/
virtual de::dfloat lightSourceRadius() const = 0;

/**
* Returns the color of the emitted light. The intensity of the light must
* not be factored into the color values, but is instead returned separately
Expand All @@ -73,10 +60,36 @@ class ILightSource
/**
* Returns the intensity of the light.
*
* @param viewPoint World point from where the light is being observed.
* Intensity may vary based on direction.
* @param viewPoint World point from where the light is being observed if
* the intensity may vary depending on the relative direction
* and/or position of the viewer.
*/
virtual de::dfloat lightSourceIntensity(de::Vector3d const &viewPoint) const = 0;
};

This comment has been minimized.

Copy link
@skyjake

skyjake Apr 28, 2014

Owner

I just realized this interface is missing a lightDirection() method. While some light can be directionless (direction = 0,0,0), in most cases we'll need a direction for lighting objects, etc.

This comment has been minimized.

Copy link
@danij-deng

danij-deng Apr 28, 2014

Author Collaborator

I would think that is looking at this from the wrong perspective. A pure "point" light source is inherently directionless. The "direction" of light is only ever inferred from other objects occluding or otherwise warping the emitted light. In this case I would say the "direction" you speak of is viewer-relative rather than source relative and should therefore not exist here as a lightDirection() method. (It might make sense in IPointLightSource, though).


/**
* Interface for a point light source.
*
* @ingroup render
*/
class IPointLightSource : public ILightSource
{
public:
typedef de::Vector3d Origin;

public:
virtual ~IPointLightSource() {}

/**
* Returns the position of the light source, in map units.
*/
virtual Origin lightSourceOrigin() const = 0;

/**
* Returns the radius of the emitter itself, in map units. A radius of
* zero would mean that the light emitter is an infinitely small point.
*/
virtual de::dfloat lightSourceRadius() const = 0;
};

#endif // DENG_CLIENT_ILIGHTSOURCE_H
153 changes: 109 additions & 44 deletions doomsday/client/include/render/lightgrid.h
@@ -1,7 +1,7 @@
/** @file render/lightgrid.h Light Grid (Smoothed ambient sector lighting).
/** @file lightgrid.h Light Grid (Smoothed ambient sector lighting).
*
* @authors Copyright © 2003-2013 Jaakko Keränen <jaakko.keranen@iki.fi>
* @authors Copyright © 2006-2013 Daniel Swanson <danij@dengine.net>
* @authors Copyright © 2006-2014 Daniel Swanson <danij@dengine.net>
*
* @par License
* GPL: http://www.gnu.org/licenses/gpl.html
Expand All @@ -17,103 +17,168 @@
* http://www.gnu.org/licenses</small>
*/

#ifndef DENG_RENDER_LIGHT_GRID_H
#define DENG_RENDER_LIGHT_GRID_H

#include "dd_types.h"
#ifndef DENG_CLIENT_LIGHTGRID_H
#define DENG_CLIENT_LIGHTGRID_H

#include <de/libdeng2.h>
#include <de/Error>
#include <de/Vector>

class Sector;
#include "render/ilightsource.h"

namespace de {

class Map;

/**
* Simple global illumination method utilizing a 2D grid of light levels, achieving
* smoothed ambient sector lighting.
* Simple global illumination method utilizing a 2D grid of block light sources,
* achieving smoothed ambient lighting for sectors.
*
* @ingroup render
*/
class LightGrid
{
public:
/**
* Linear reference to a block in the grid (X + Y * Grid Width).
*/
typedef int Index;

/**
* Two dimensioned reference to a block in the grid [X, Y].
*/
typedef Vector2i Ref;

/**
* Linear reference to a block in the grid (X + Y * Grid Width).
* Base class for a block illumination source.
*
* Derived classes are obliged to call @ref LightGrid::blockLightSourceChanged()
* whenever the properties of the light source change, so that any necessary
* updates can be scheduled.
*/
typedef int Index;
class IBlockLightSource : public ILightSource
{
public:
virtual ~IBlockLightSource() {}

/**
* Determines the Z-axis bias scale factor for the illumination source.
*/
virtual int blockLightSourceZBias() = 0;
};

public:
/**
* Construct and initialize a new LightGrid for the specifed map. SectorClusters
* must be built for this.
* Construct and initialize an empty LightGrid.
*/
LightGrid(Vector2d const &origin, Vector2d const &dimensions);

/**
* To be called when physical dimensions of the grid or the logical block size
* changes to resize the light grid. Note that resizing inherently means clearing
* of primary illumination sources, so they'll need to be initialized again.
*
* @note Initialization may take some time depending on the complexity of the map
* (world dimensions, number of sectors) and should therefore be done "off-line".
* @param newOrigin Origin of the grid in map space.
* @param newDimensions Dimensions of the grid in map space units.
*/
LightGrid(Map &map);
void resizeAndClear(Vector2d const &newOrigin, Vector2d const &newDimensions);

/**
* Register the console comands and variables of this module.
* Determine the smoothed ambient lighting properties for the given @a point
* in the map coordinate space.
*
* @param point 3D point.
*
* @return Evaluated color at the specified point.
* - [x, y, z] = RGB color with premultiplied luminance factor
* - [w] = luminance factor (i.e., light level)
*/
static void consoleRegister();
Vector4f evaluate(Vector3d const &point);

/**
* Update the grid by finding the strongest light source in each grid block.
* Should be called periodically to update/refresh the grid contents (e.g., when
* beginning a new render frame).
* Convenient method of determining the smoothed ambient lighting properties
* for the given @a point in the map coordinate space and returns the intensity
* factor directly.
*
* @param point 3D point.
*
* @return Evaluated light intensity at the specified point.
*
* @see evaluate
*/
void update();
inline float evaluateIntensity(Vector3d const &point) {
return evaluate(point).w;
}

/**
* To be called when an engine variable which affects the lightgrid changes.
* @todo Only needed because of the sky light color. -ds
*/
void markAllForUpdate();
void scheduleFullUpdate();

/**
* Returns the dimensions of the light grid in blocks. For informational purposes.
* Update the grid. Should be called periodically to update/refresh the grid
* contents (e.g., when beginning a new render frame).
*/
Vector2i const &dimensions() const;
void updateIfNeeded();

/**
* Returns the size of grid block in map coordinate space units. For informational
* purposes.
* Change the primary light source for the specified grid @a block. Whenever
* a primary source is changed the necessary grid updates are scheduled.
*
* @param index Linear index of the block to change.
* @param newSource New primary light source to set. Use @c 0 to clear.
*/
coord_t blockSize() const;
void setPrimarySource(Index block, IBlockLightSource *newSource);

/**
* Determine the ambient light color for a point in the map coordinate space.
*
* @param point 3D point.
*
* @return Evaluated color at the specified point.
* Lookup the primary illumination source for the specified @a block. For debug.
*/
Vector3f evaluate(Vector3d const &point);
IBlockLightSource *primarySource(Index block) const;

/**
* Determine the ambient light level for a point in the map coordinate space.
*
* @param point 3D point.
*
* @return Evaluated light level at the specified point.
* IBlockLightSources are obliged to call this whenever the attributes of the
* the light source have changed to schedule any necessary grid updates.
*/
float evaluateLightLevel(Vector3d const &point);
void primarySourceLightChanged(IBlockLightSource *changedSource);

/**
* Draw the light grid debug visual.
* Register the console comands and variables of this module.
*/
void drawDebugVisual();
static void consoleRegister();

public: // Utilities -----------------------------------------------------------

/// Returns the linear grid index for the given two-dimensioned grid reference.
inline Index toIndex(int x, int y) { return y * dimensions().x + x; }

/// @copydoc toIndex()
inline Index toIndex(Ref const &gref) { return toIndex(gref.x, gref.y); }

/// Returns the two-dimensioned grid reference for the given map space @a point.
Ref toRef(Vector3d const &point);

/// Returns the size of a grid block in map space units.
int blockSize() const;

/// Returns the origin of the grid in map space.
Vector2d const &origin() const;

/// Returns the dimensions of the grid in blocks.
Vector2i const &dimensions() const;

/// Returns the total number of non-null blocks in the grid.
int numBlocks() const;

/// Returns the total number of bytes used for non-null blocks in the grid.
size_t blockStorageSize() const;

/// Returns the "raw" color for the specified @a block. For debug.
Vector3f const &rawColorRef(Index block) const;

private:
DENG2_PRIVATE(d)
};

} // namespace de

#endif // DENG_RENDER_LIGHT_GRID_H
#endif // DENG_CLIENT_LIGHTGRID_H
15 changes: 13 additions & 2 deletions doomsday/client/include/render/rend_main.h
Expand Up @@ -36,6 +36,7 @@ class SectorCluster;

namespace de {
class Map;
class LightGrid;
}

// Multiplicative blending for dynamic lights?
Expand Down Expand Up @@ -197,9 +198,19 @@ void Rend_UpdateLightModMatrix();
void Rend_DrawLightModMatrix();

/**
* Sector light color may be affected by the sky light color.
* Draws the light grid debug visual.
*/
de::Vector3f const &Rend_SectorLightColor(SectorCluster const &cluster);
void Rend_LightGridVisual(de::LightGrid &lg);

/**
* Determines whether the sky light color tinting is enabled.
*/
bool Rend_SkyLightIsEnabled();

/**
* Returns the effective sky light color.
*/
de::Vector3f Rend_SkyLightColor();

/**
* Blend the given light value with the luminous object's color, applying any
Expand Down

0 comments on commit 7b82ef6

Please sign in to comment.