DarkPlaces lighting #2 - Lighting model
Author: VorteXSource: http://omnicide.razorwind.ru/wiki/
Lighting visualized. Blue is shadow volumes, bright orange is zones being processed for dynamic realtime lighting.
Darkplaces uses a variation of Phong shading as a default lighting model. It is based on per-pixel lighting - a technique of computing lighting equations for each pixel independently. Renderer contains lots of tricks to allow shading to be fast and flexible. Default model is used on both GL2.0 rendering paths and pre-shader rendering paths (GL1.4), although not all lighting features are possible on pre-shader fixed rendering pipeline.
Lighting are breaked into the passes:
- Static lighting (lightmap or lightgrid or vertex lighting)
- Dynamic light 1
- Dynamic light 2
- ...
- Dynamic light X
- Photon Mapping (optional)
- Fog (optional)
Data used for each light pass:
- Vertex normal : values between vertices of pixel's triangle are interpolated using Gouraud shading
- (http://en.wikipedia.org/wiki/Gouraud_shading)
- Color Map : base texture (best way to use diffuse texture)
- Normal Map : texture storing additional surface curvature (optionally, alpha storing height)
- Gloss Map : texture used for specular reflection. Contains gloss color (RGB) and optional exponent
- multiplier (alpha)
- Glow Map : texture's local luminance texture, RGB additive blended texture that entirely ignores
- shading
- Light Vector : vector of light direction (either calculated for realtime light or got from deluxemap
- lightmap component)
- Eye Vector : being computed for each pixel, this vector is used for specular calculation.
This gallery illustrates how lighting features changes the quality:
Attenuation-only 'flat' lighting |
|
+ Shadows |
|
+ Shading |
|
+ Specular |
|
+ Photonmapping |
Attenuation
Dynamic lights in Darkplaces engine are omnidirectional, using linear falloff.
? Spotlights and projected dynamic lights could be simulated with cubemap filters.
Static lights can have a variety of options for controlling attenuation (this options is only used in Q3map2 LIGHT stage):
- target and radius : simulating spot lights with cone falloff
- _sun flag - infinite distance lights, constant direction
- _deviance and _samples - non-point lights
Shading
Shading is done by using dotproduct of light vector and pixel normal. Some ambient lighting could be added for a more smooth result.
? Important: Lightmaps by default dont have shading since they lack light direction data. In order to make lightmaps use the whole shading cycle, the map compiler tool should be configured to make deluxemaps (second lightmap set which stores per-pixel light directions).
Rough shading algorithm explanation:
// Surface's vertex normals are always supplied, texture normalmap is forced to default RGB '0.5 0.5 1' (same as surface normal) if not found
PixelNormal = Surface.VertexNormal + Texture.NormalMap;
// LightSource are only defined for dynamic lights
// LightmapGlobal.AmbientLight is r_ambient cvar
// Material.AmbientLight is set by dprtlightambient material keyword and only applicable to dynamic lights
AmbientLight = LightSource.AmbientLight + LightmapGlobal.AmbientLight + Material.AmbientLight;
if (LightSource)
DiffuseLight = LightSource.DiffuseLight;
else
DiffuseLight = 1; // Static lighting
Shading = dotproduct(PixelNormal, LightVector) * DiffuseLight + AmbientLight;
? r_shadow_usenormalmap : Enables use of normalmap texture for lighting. Setting this to to will make only vertex normals to be used.
? r_shadow_bumpscale_basetexture : Forces normalmap to be automatically calculated from color texture by using it as bumpmap, value controls magnitude. Requires r_restart.
? r_shadow_bumpscale_bumpmap : Normalmap can be supplied as _bump texture, in this case engine converts it to normalmap on load, value is magnitude. Requires r_restart.
? r_glsl_deluxemapping : Use full shading on lightmapped surfaces. A value of 2 forces deluxemap shading even if the surface has no one.
? r_ambient : Amount of ambient light to be added to all surfaces. Makes the level brighter.
Specular
Specular (or gloss) is the mirror-like reflection of light from a surface, in which light from a single incoming direction (a ray) is reflected into a single outgoing direction. Many well-known surfaces (metal, plastic, wood) are recognized by the specularity they have.
Specular offers two parameters to mess with:
- Specular multiplier: intensity of specular effect, this could be very high or very low. It is a multiplier to gloss texture.
- Specular exponent: how 'sharp' gloss is, high values are used to make texture to be plastic-like, while lower ones are suitable for matte surfaces. Basically it's just a modifier to gloss texture's alpha channel (which is forced to 1 if not supplied).
Gloss may be forced (see r_shadow_gloss 2 below), in this case texture, if missing its own gloss map, gets a white image for gloss map and parameters from a cvars.
Rough specular algorithm explanation:
// Global.GlossIntensity is controlled by r_shadow_glossintensity or r_shadow_glossintensity2 if gloss is forced
// Material.GlossIntensityMod is set by dpglossintensitymod material keyword
SpecularColor = Texture.GlossMap * Global.GlossIntensity * Material.GlossIntensityMod;
// Global.GlossExponent is controlled by r_shadow_glossexponent or r_shadow_glossexponent2 if gloss is forced
// Material.GlossExponentModis set by dpglossexponentmod material keyword
if (Texture.GlossMap.Alpha)
SpecularExponent = Texture.GlossMap.Alpha * Global.GlossExponent * Material.GlossExponentMod;
else
SpecularExponent = Global.GlossExponent * Material.GlossExponentMod;
// this is rough specular calculation
// optionally, engine can use real reflection map to get specular normal (see r_shadow_glossexact below)
SpecularNormal = PixelNormal + EyeVector;
Specular = SpecularColor * power(dotproduct(PixelNormal, SpecularNormal), SpecularExponent)
? Important: Forced gloss (gloss 2) which is used if texture's gloss map is missed, are only used on outside map to simulate wet surfaces effect.
? r_shadow_glossintensity : Global intensity for specular calculations, default is 1.
? r_shadow_gloss2intensity : Global intensity for specular calculations applied for forced-gloss surfaces, default is 1.
? r_shadow_glossexponent : Global gloss exponent used as a base in shader calculations.
? r_shadow_gloss2exponent : Same one used for forced-gloss surfaces.
? r_shadow_glossexact : Use real reflection math for gloss calculation. This is slower and a little more correct.
Shadows
Shadows are the most valuable part of realtime lighting. They are increasing scene depth so it looks more realistic.
? Important: Shadows are quite complex render task, many lights casting many shadows may decrease rendering speed significantly. Map designer should plan his map with this limitation in mind - there should be no situation of many lights being seen from a certain point, or the user will experience a game slowdown.
Darkplaces supports two realtime shadowing techniques: stencil shadow volumes and shadow mapping.
Stencil shadow volumes Stencil shadow volumes is a base shadow rendering method in Darkplaces. This technique is well known for its shadows not having penumbra. Many other restrictions (high fill rate hit, bad scalability) make this method to be used only on a few games (such as Doom 3).
? r_shadow_polygonfactor : how much to enlarge shadow volume polygons when rendering (should be 0!)
? r_shadow_polygonoffset : how much to push shadow volumes into the distance when rendering, to reduce chances of zfighting artifacts (should not be less than 0)
? r_shadow_frontsidecasting : whether to cast shadows from illuminated triangles (front side of model) or unlit triangles (back side of model)
? r_showshadows : Show areas covered by shadow volumes. Useful for finding out why some areas of the map render slowly (bright blue = lots of passes, slow). Only matters if using shadow volumes.
Shadow mapping
In 2010 darkplaces got shadow mapping implemented by Eihrul.
Shadowmapping have a number of advantages over shadow volume rendering and is considered to replaceit:
- Penumbra
- Fast to render (especially on complex area maps)
- Takes less CPU time (as construction of shadow volumes is not required)
- Distance-based LOD (far lights rendered with lower shadowmap resolution)
? r_shadow_shadowmapping : Enables shadow mapping
? r_shadow_shadowmapping_bias : Shadowmap bias parameter (this is multiplied by nearclip * 1024 / lodsize)
? r_shadow_shadowmapping_bordersize : Shadowmap size bias for filtering
? r_shadow_shadowmapping_depthbits : Requested minimum shadowmap texture depth bits, could be 16 or 24
? r_shadow_shadowmapping_filterquality : Shadowmap filter modes: -1 = auto-select, 0 = no filtering, 1 = bilinear, 2 = bilinear 2x2 blur (fast), 3 = 3x3 blur (moderate), 4 = 4x4 blur (slow)
? r_shadow_shadowmapping_maxsize : Shadowmap size limit
? r_shadow_shadowmapping_minsize : Shadowmap size limit
? r_shadow_shadowmapping_nearclip : Shadowmap near clip in world units. Increasing this will make shadow rendering to be more precise (as more bits goes to middle range), at the cost of the small non-shadowed zone around light.
? r_shadow_shadowmapping_polygonfactor : Slope-dependent shadow mapping bias.
? r_shadow_shadowmapping_polygonoffset : Constant shadow mapping bias.
? r_shadow_shadowmapping_precision : Makes shadowmaps have a maximum resolution of this number of pixels per light source radius unit such that, for example, at precision 0.5 a light with radius 200 will have a maximum resolution of 100 pixels.
? r_shadow_shadowmapping_useshadowsampler : whether to use sampler2DShadow if available.
? r_shadow_shadowmapping_vsdct : enables use of virtual shadow depth cube texture
? r_usedepthtextures : Use depth texture instead of depth renderbuffer where possible, uses less video memory but may render slower (or faster) depending on hardwaree.
Bug: r_usedepthtextures causing strong precision drop, which leads to splotches around shadow edges
Other light models
Darkplaces includes other lighting models which are used eventually:
Fake light A developer-only mode which is forced on non-lit maps (ones which were compiled and didn't get LIGHT phase). This is infinite realtime light that is cast from eye position.
Sun light A similar to fake light technique to render sun lighting on outdoor surfaces, Used for sunset and sun dawn effects on outdoor maps. Cel shading Altered shading for default lighting model.
? r_celshading : Enable cel shading (alternate diffuse math) Lightmap Lightmap with no deluxemap applied (just an old lightmap with no per-pixel lighting effects) Fullbright No lighting applied (all textures at their full brightness) ? r_fullbright : makes map very bright and renders faster
? r_fullbright_directed : render 'fake' lighting instead of real lightmaps
Special effects
This chapter contains references of various special effects hardcoded in light renderer. These special effects, applied or combined, will help to create a wide range of things, such as: switchable lights, projective lights, sunlight simulation, flickering lights and more.
CoronasCoronas aimed to simulate glow around dynamic lights, which looks good on small and medium size lights. Coronas are customized per-light (size and brightness) and also can be placed without lights.
? r_coronas : Brightness of corona effects. 0 disables coronas.
? r_coronas_occlusionquery : Fades coronas according to visibility. Bad performance (synchronous rendering), even worse on multi-GPU.
? r_coronas_occlusionquerysize : Size of lightsource for corona occlusion checksum. Usial value is 0.1
Cubemap filtering
A technique for modeling non-uniform light distribution according to direction, for example a lantern may use a cubemap to describe the light emission pattern of the cage around the lantern (as well as soot buildup discoloring the light in certain areas), often also used for softened grate shadows and light shining through a stained glass window (done crudely by texturing the lighting with a cubemap), another good example would be a discolight.
Any dynamic lightsource can have a cubemap attached.
Planar shadows
Simplified global shadows which are cast from entities, not from lights (so planar shadows are just filters, they dont do any lighting math). Planar shadows are either stencil or shadowmapped if shadowmapping is on.
Tip: Planar shadows are used to simulate sunlight in outdoor locations.
? r_shadows : Enable planar shadows cast using lightgrid-stored light direction. When set to 2 always cast the shadows in the certain direction (see below). Shadowmapping only supports r_shadows 2.
? r_shadows_castfrombmodel : Enables shadows cast from bmodels.
? r_shadows_darken : How many shadowed areas will be darkened.
? r_shadows_drawafterrtlighting : Hack to draw fake shadows AFTER realtime lightning is drawn. May be useful for simulating sunlight on large outdoor maps with only one big noshadow rtlight. The price is the less realistic appearance of dynamic light shadows.
? r_shadows_focus : Offset the shadowed area focus (used for shadowed area bounds).
? r_shadows_shadowmapscale : Increases shadowmap quality (multiply global shadowmap precision). Needs shadowmapping ON.
? r_shadows_throwdirection : r_shadows 2 throwing direction. Default is '0 0 -1' (down).
? r_shadows_throwdistance : How far to cast shadows from models. This sets shadowed area bounds for shadowmapping.
Customized ModelLight
Lightgrid sampling (diffuse, ambient and light vector components) can be overridden by Client-side QuakeC. Allows various lighting effects on models (strobing, using different positions for sampling etc.)
Fog
Fog is global. Optionally, height plane and height texture can be defined which will make fog to fade with height.
- density - how much fog to add per distance, this is virtual value. 1 means very strong fog.
- red - red component of fog color
- green - green component of fog color
- blue - blue component of fog color
- alpha - fog effect opacity (default is 1)
- mindist - distance to start applying fog at
- maxdist - maximal distance apply fog at
- top - origin of height plane at worldspace (game units)
- height - fog height fade in game units
- fadetexture - horizontal texture that resembles fading, left pixel if top bright, right is top dark. Can be used for non-linear fading.
Fog are set by console commands:
? fog <density> <red> <green> <blue> [<alpha> <mindist> <maxdist> <top> <height>] : Sets the global fog
? fog_heighttexture <density> <red> <green> <blue> <alpha> <mindist> <maxdist> <top> <height> <fadetexture> : Sets the global fog with customized fade texture
Tags: DarkPlaces, quake, tutorial, mapping