Second Life Lighting System - ApertureViewer/Aperture-Viewer GitHub Wiki
Analysis of the Second Life Lighting System (via Aperture Viewer Codebase)
This document provides a technical analysis of the core lighting system used in Second Life, based on a review of the Aperture Viewer v1.0.0 codebase. It is understood that, at the time of this analysis, the fundamental deferred shading pipeline, light source handling, and shadow mapping logic within the reviewed Aperture code largely reflect the implementation inherited from its upstream source (Firestorm Viewer, derived from the official Second Life Viewer). While Aperture may have specific shader modifications (e.g., potentially related to SSAO integration or PostFX), the core lighting and shadow rendering architecture described here is believed to be representative of the standard system used across current viewers, not a lighting system uniquely implemented by Aperture Viewer itself.
(Analysis based on review of relevant C++ files like pipeline.cpp
, llprimitive.cpp
, llvovolume.cpp
, llgl.cpp
, shader files, etc., from the Aperture v1.0.0 source.)
1. Overall Architecture: Deferred Shading
The core of the lighting system relies on a Deferred Shading pipeline. This approach separates geometry rendering from lighting calculations for efficiency, especially with many light sources.
- G-Buffer Generation (
renderGeomDeferred
): Opaque and alpha-masked objects are rendered first. Their surface properties (Albedo/BaseColor, Normal, Specular/ORM, Emissive, Material Flags) are written into multiple render targets (mRT->deferredScreen
). Shaders responsible includediffuseF.glsl
,pbropaqueF.glsl
,materialF.glsl
,avatarF.glsl
, etc. - Lighting Calculation (
renderDeferredLighting
): This pass reads the G-Buffer data for each pixel. It calculates and accumulates the lighting contribution from global sources (Sun/Moon) and selected local lights (Point/Spot) into a lighting buffer (mRT->screen
, possibly viamRT->deferredLight
). It integrates Ambient Occlusion (SSAO) and atmospheric effects. Key shaders:sunLightF.glsl
,pointLightF.glsl
,multiPointLightF.glsl
,spotLightF.glsl
,multiSpotLightF.glsl
,softenLightF.glsl
. - Shadow Mapping (
generateSunShadow
,renderShadow
): Runs separately to generate depth maps from the perspective of shadow-casting lights (Sun/Moon cascades and up to two Spotlights) intomRT->shadow[]
andmSpotShadow[]
. Uses simplified shaders (shadowF.glsl
, etc.). - Forward Rendering (
renderGeomPostDeferred
): Handles objects unsuitable for deferred shading (alpha-blended transparency, water, UI, debug visuals). These are rendered after the deferred lighting pass and typically perform their own lighting calculations (sampling environment probes and potentially a limited set of dynamic lights passed via uniforms). - Post-Processing (
renderFinalize
): Applies final screen-space effects like Glow, Depth of Field, Tonemapping, Anti-Aliasing, Sharpening, etc., to the composed image.
2. Light Source Types & Representation
- Sun/Moon: A single primary directional light. Its color and direction are global, managed by
LLEnvironment
/LLSettingsSky
and passed as uniforms (e.g.,sun_dir
,sunlight_color
). Its contribution is significantly affected by atmospherics. - Ambient Light: A non-directional base illumination level (
ambient_color
), also from environment settings. - Local Point Lights: Omni-directional lights originating from a point. Represented by
LLVOVolume
objects where light parameters are enabled. Key properties (radius, color, falloff) are stored in parameter blocks (LLLightParams
defined inllprimitive.h
). - Local Spot Lights: Directional lights emitting from a point within a cone. Also represented by
LLVOVolume
. Distinguished from point lights viaLLVOVolume::isLightSpotlight()
. Additional parameters (direction derived from object rotation, cutoff angle, focus, projective texture ID) are stored in parameter blocks (LLLightImageParams
defined inllprimitive.h
). - Emissive Surfaces: Objects whose materials inherently glow. Handled via the emissive channel in the G-Buffer, written by shaders like
pbropaqueF.glsl
.
3. Local Light Management: Selection & Limits
- Parameter Storage: All local light properties are stored within the
LLVOVolume
object using the parameter block system defined inllprimitive.h
/.cpp
. This system manages different data types associated with objects (e.g.,PARAMS_LIGHT
,PARAMS_LIGHT_IMAGE
). Adding new light parameters (like for Square Lights) involves modifying these structures and their pack/unpack logic. - Initial Candidate Selection (
pipeline.cpp::calcNearbyLights
):- Identifies potential lights from the global list (
mLights
). - Filters based on distance to camera relative to light radius (
calc_light_dist
), intensity (getLightIntensity
), selection status (isSelected
), whether the light is moving (LLDrawable::ACTIVE
state), and thesRenderAttachedLights
setting. - Adds qualifying lights to a sorted set (
mNearbyLights
).
- Identifies potential lights from the global list (
- Processing Limit: The number of lights from
mNearbyLights
actually processed for rendering illumination is limited by theRenderLocalLightCount
setting. Lights exceeding this count (farthest first) are faded out usingLight::fade
. Based on the provided code, no other factors (like GPU load or scene complexity) dynamically adjust this limit or further cull lights from this list before rendering. - Shadow Limit: There is a hardcoded limit of TWO spotlights that can cast dynamic shadows simultaneously. This is evident from the array sizes (
mSpotShadow[2]
,mTargetShadowSpotLight[2]
) and iteration limits (loops 0 to 1) ingenerateSunShadow
and related logic.
4. Light Rendering Process
- Deferred Point Lights:
- Rendered by drawing bounding volumes (cubes).
- Shaders (
pointLightF.glsl
,multiPointLightF.glsl
) read G-Buffer data (position, normal, material props). - Calculate attenuation based on distance, radius, and falloff uniforms.
- Compute lighting using appropriate model (legacy Blinn-Phong or PBR).
- Result is additively blended.
- Deferred Spot Lights:
- Similar process to point lights but confined to a cone.
- Use a projection matrix (
proj_mat
) and sample a projective texture (projectionMap
) for shape and color modulation. - Apply angular attenuation based on spot direction and cutoff.
- Sample one of the two spot shadow maps (
shadowMap4
/shadowMap5
) if designated (proj_shadow_idx
).
- Forward-Lit Transparency: Objects in the
renderGeomPostDeferred
pass typically use simpler lighting models within their fragment shaders, sampling environment probes and potentially a few lights passed as standard uniforms (likely sourced fromLLLightState
/setupHWLights
).
5. Shadow System
- Sun/Moon Shadows: Uses Cascaded Shadow Maps (CSM).
generateSunShadow
splits the view frustum based onmSunClipPlanes
(up to 4 cascades) and renders depth from the light's view intomRT->shadow[]
.sunLightF.glsl
samples the appropriate cascade usingsampleDirectionalShadow
andpcfShadow
based on pixel depth. - Spotlight Shadows: Limited to two casters.
setupSpotLight
selects the two highest-priority spotlights (based onupdateSpotLightPriority
which uses screen size) and assigns them shadow map slots (mSpotShadow[0..1]
).spotLightF.glsl
/multiSpotLightF.glsl
sample these usingsampleSpotShadow
andpcfSpotShadow
. A fading mechanism (mSpotLightFade
) smooths transitions between shadow casters. - Technique: Percentage-Closer Filtering (PCF) is used for soft shadow edges. Depth bias (
shadow_bias
,spot_shadow_bias
) and slope-scale bias (implied by offset logic, e.g.,shadow_offset
) are applied to reduce self-shadowing artifacts.
6. PBR Integration
- PBR materials (
GBUFFER_FLAG_HAS_PBR
) have a distinct path in lighting shaders. - Utilizes data from ORM texture (Occlusion, Roughness, Metallic) sampled from
specularMap
. - Relies heavily on Image-Based Lighting from Reflection Probes (
reflectionProbes
,irradianceProbes
) sampled viasampleReflectionProbes
and processed with functions likepbrIbl
. - Direct lighting uses PBR functions like
pbrPunctual
which incorporate roughness, metallic, and Fresnel terms.
7. Key Code References
- Main Pipeline Logic:
pipeline.cpp
,pipeline.h
- Light Object Parameters:
llprimitive.h
,llprimitive.cpp
,llvovolume.h
,llvovolume.cpp
- Low-Level GL State:
llgl.h
,llgl.cpp
(definesLLLightState
) - Shader Management:
llshadermgr.h
,llshadermgr.cpp
,llviewershadermgr.h
,llviewershadermgr.cpp
- Lighting Shaders:
deferred/sunLightF.glsl
,deferred/pointLightF.glsl
,deferred/multiPointLightF.glsl
,deferred/spotLightF.glsl
,deferred/multiSpotLightF.glsl
,deferred/softenLightF.glsl
,deferred/deferredUtil.glsl
- Shadow Shaders:
deferred/shadowF.glsl
,deferred/shadowUtil.glsl
8. Summary of Capabilities and Confirmed Limitations
- Capabilities:
- Robust deferred shading pipeline.
- Handles numerous local lights simultaneously, limited primarily by performance (
RenderLocalLightCount
) rather than fixed slots. - Full PBR material support integrated with IBL (Reflection Probes).
- Cascaded Shadow Maps for Sun/Moon.
- PCF filtering for soft shadows.
- Sophisticated atmospheric effects.
- Confirmed Limitations (Based only on provided code):
- Strict limit of TWO dynamic shadow-casting spotlights.
- No built-in support for Area Light types (only Point and Spot sources are modeled).
- Local light selection criteria are confined to distance, radius, intensity, selection status, active state, attachment status, and the count limit, with screen area used only for prioritizing the two spotlight shadow slots.
This analysis is based solely on the specific code files reviewed from the Aperture Viewer project and represents the system's implementation therein.