Skip to content

Commit

Permalink
Most of the shadows tests
Browse files Browse the repository at this point in the history
  • Loading branch information
lilleyse committed May 25, 2016
1 parent a5d4ec3 commit 36e5fcf
Show file tree
Hide file tree
Showing 8 changed files with 2,123 additions and 44 deletions.
11 changes: 9 additions & 2 deletions Source/Scene/FrameState.js
Expand Up @@ -183,15 +183,22 @@ define([
farPlane : undefined,

/**
* The size of the bounding volume that is closest to the camera. Used to estimate cascade splits.
* The size of the bounding volume that is closest to the camera. This is used to place more shadow detail near the object.
* @type {Number}
*/
closestObjectSize : undefined,

/**
* The time when a shadow map was last dirty
* @type {Number}
*/
lastDirtyTime : 0,

/**
* Whether the shadows maps are out of view this frame
* @type {Boolean}
*/
lastDirtyTime : 0
outOfView : true
};
}

Expand Down
57 changes: 32 additions & 25 deletions Source/Scene/Scene.js
Expand Up @@ -1067,7 +1067,8 @@ define([
var context = scene._context;

var shadowsDirty = false;
if (shadowMaps.length > 0 && (command.receiveShadows || command.castShadows)) {
var shadowsVisible = !frameState.shadowHints.outOfView;
if (shadowsVisible && (command.receiveShadows || command.castShadows)) {
// Update derived commands when any shadow maps become dirty
var lastDirtyTime = frameState.shadowHints.lastDirtyTime;
if (command._lastDirtyTime !== lastDirtyTime) {
Expand All @@ -1076,19 +1077,19 @@ define([
shadowsDirty = true;
}
}

if (command._dirty) {
command._dirty = false;

var derivedCommands = command.derivedCommands;

if (shadowMaps.length > 0 && (command.receiveShadows || command.castShadows)) {
if (shadowsVisible && (command.receiveShadows || command.castShadows)) {
derivedCommands.shadows = ShadowMap.createDerivedCommands(shadowMaps, command, shadowsDirty, context, derivedCommands.shadows);
}

var oit = scene._oit;
if (command.pass === Pass.TRANSLUCENT && defined(oit) && oit.isSupported()) {
if (shadowMaps.length > 0 && command.receiveShadows) {
if (shadowsVisible && command.receiveShadows) {
derivedCommands.oit = oit.createDerivedCommands(command.derivedCommands.shadows.receiveCommand, context, derivedCommands.oit);
} else {
derivedCommands.oit = oit.createDerivedCommands(command, context, derivedCommands.oit);
Expand Down Expand Up @@ -1292,7 +1293,7 @@ define([
if (updateShadowHints && command.receiveShadows && (distances.start < ShadowMap.MAXIMUM_DISTANCE) &&
!((pass === Pass.GLOBE) && (distances.start < -100.0) && (distances.stop > 100.0))) {

// Get the smallest bounding volume the camera is near. This is used to improve cascaded shadow splits.
// Get the smallest bounding volume the camera is near. This is used to place more shadow detail near the object.
var size = distances.stop - distances.start;
if ((pass !== Pass.GLOBE) && (distances.start < 100.0)) {
shadowClosestObjectSize = Math.min(shadowClosestObjectSize, size);
Expand Down Expand Up @@ -1425,7 +1426,7 @@ define([

if (scene.debugShowCommands || scene.debugShowFrustums) {
executeDebugCommand(command, scene, passState);
} else if (!scene.frameState.passes.pick && scene.frameState.shadowMaps.length > 0 && command.receiveShadows) {
} else if (!scene.frameState.passes.pick && !scene.frameState.shadowHints.outOfView && command.receiveShadows) {
command.derivedCommands.shadows.receiveCommand.execute(context, passState);
} else {
command.execute(context, passState);
Expand Down Expand Up @@ -1817,7 +1818,7 @@ define([
var shadowMaps = frameState.shadowMaps;
var shadowMapLength = shadowMaps.length;

if (shadowMapLength === 0 || scene.frameState.passes.picking) {
if (shadowMapLength === 0 || scene.frameState.passes.pick) {
return;
}

Expand Down Expand Up @@ -2060,10 +2061,12 @@ define([
var shadowMaps = frameState.shadowMaps;
var length = shadowMaps.length;

frameState.shadowHints.outOfView = true;

if (length === 0 || frameState.passes.pick) {
return;
}

for (var i = 0; i < length; ++i) {
var shadowMap = shadowMaps[i];
shadowMap.update(frameState);
Expand All @@ -2073,26 +2076,30 @@ define([
shadowMap.dirty = false;
}

if (!shadowMap.outOfView && defined(globe) && globe.castShadows) {
var sceneCamera = frameState.camera;
var sceneCullingVolume = frameState.cullingVolume;
var sceneCommandList = frameState.commandList;
if (!shadowMap.outOfView) {
frameState.shadowHints.outOfView = false;

if (defined(globe) && globe.castShadows) {
var sceneCamera = frameState.camera;
var sceneCullingVolume = frameState.cullingVolume;
var sceneCommandList = frameState.commandList;

// Update frame state to render from the light camera
frameState.camera = shadowMap.shadowMapCamera;
frameState.cullingVolume = shadowMap.shadowMapCullingVolume;
frameState.commandList = shadowMap.commandList;
// Update frame state to render from the light camera
frameState.camera = shadowMap.shadowMapCamera;
frameState.cullingVolume = shadowMap.shadowMapCullingVolume;
frameState.commandList = shadowMap.commandList;

frameState.commandList.length = 0;
frameState.commandList.length = 0;

// Update the globe again to Collect terrain commands from the light's POV.
// Primitives do not need to be updated twice because they typically aren't culled by the scene camera.
globe.update(frameState);
// Update the globe again to collect terrain commands from the light's POV.
// Primitives do not need to be updated twice because they typically aren't culled by the scene camera.
globe.update(frameState);

// Revert back to original frame state
frameState.camera = sceneCamera;
frameState.cullingVolume = sceneCullingVolume;
frameState.commandList = sceneCommandList;
// Revert back to original frame state
frameState.camera = sceneCamera;
frameState.cullingVolume = sceneCullingVolume;
frameState.commandList = sceneCommandList;
}
}
}
}
Expand Down Expand Up @@ -2777,4 +2784,4 @@ define([
};

return Scene;
});
});
46 changes: 29 additions & 17 deletions Source/Scene/ShadowMap.js
Expand Up @@ -153,7 +153,7 @@ define([

this._enabled = defaultValue(options.enabled, true);
this._softShadows = defaultValue(options.softShadows, false);
this._dirty = false;
this._dirty = true;

/**
* Determines the darkness of the shadows.
Expand Down Expand Up @@ -239,7 +239,6 @@ define([
this._isSpotLight = false;
if (this._cascadesEnabled) {
// Cascaded shadows are always orthographic. The frustum dimensions are calculated on the fly.
this._lightCamera.frustum = new OrthographicFrustum();
this._shadowMapCamera.frustum = new OrthographicFrustum();
} else if (defined(this._lightCamera.frustum.fov)) {
// If the light camera uses a perspective frustum, then the light source is a spot light
Expand Down Expand Up @@ -270,7 +269,7 @@ define([
this.debugShow = false;
this.debugFreezeFrame = false;
this._debugFreezeFrame = false;
this.debugCascadeColors = false;
this._debugCascadeColors = false;
this._debugLightFrustum = undefined;
this._debugCameraFrustum = undefined;
this._debugCascadeFrustums = new Array(this._numberOfCascades);
Expand Down Expand Up @@ -533,6 +532,23 @@ define([
get : function() {
return this._pointLightRadius;
}
},

/**
* Debug option for visualizing the cascades by color.
*
* @memberof ShadowMap.prototype
* @type {Boolean}
* @default false
*/
debugCascadeColors : {
get : function() {
return this._debugCascadeColors;
},
set : function(value) {
this._dirty = this._debugCascadeColors !== value;
this._debugCascadeColors = value;
}
}
});

Expand Down Expand Up @@ -699,6 +715,7 @@ define([
}

function resize(shadowMap, size) {
shadowMap._size = size;
var passes = shadowMap._passes;
var numberOfPasses = passes.length;
var textureSize = shadowMap._textureSize;
Expand Down Expand Up @@ -962,7 +979,7 @@ define([
return debugFrustum;
}

var debugCascadeColors = [Color.RED, Color.GREEN, Color.BLUE, Color.MAGENTA];
var debugOutlineColors = [Color.RED, Color.GREEN, Color.BLUE, Color.MAGENTA];
var scratchScale = new Cartesian3();

function applyDebugSettings(shadowMap, frameState) {
Expand Down Expand Up @@ -995,7 +1012,7 @@ define([
if (enterFreezeFrame) {
// Recreate debug frustum when entering freeze frame mode
shadowMap._debugCascadeFrustums[i] = shadowMap._debugCascadeFrustums[i] && shadowMap._debugCascadeFrustums[i].destroy();
shadowMap._debugCascadeFrustums[i] = createDebugFrustum(shadowMap._passes[i].camera, debugCascadeColors[i]);
shadowMap._debugCascadeFrustums[i] = createDebugFrustum(shadowMap._passes[i].camera, debugOutlineColors[i]);
}
shadowMap._debugCascadeFrustums[i].update(frameState);
}
Expand Down Expand Up @@ -1365,18 +1382,6 @@ define([
var sceneCamera = shadowMap._sceneCamera; // Clone of camera, with clamped near and far planes
var shadowMapCamera = shadowMap._shadowMapCamera; // Camera representing the shadow volume, initially cloned from lightCamera

if (defined(sceneCamera)) {
// Skip check on the first frame
checkVisibility(shadowMap, frameState);
}

// Clear the shadow texture when a cascaded shadow map goes out of view (e.g. when the sun dips below the horizon).
// This prevents objects that still read from the shadow map from reading old values.
if (shadowMap._cascadesEnabled && !shadowMap._outOfViewPrevious && shadowMap._outOfView) {
clearFramebuffer(shadowMap, frameState.context);
}
shadowMap._outOfViewPrevious = shadowMap._outOfView;

// Clone light camera into the shadow map camera
if (shadowMap._cascadesEnabled) {
Cartesian3.clone(lightCamera.directionWC, shadowMapCamera.directionWC);
Expand Down Expand Up @@ -1413,6 +1418,13 @@ define([
shadowMap._sceneCamera.frustum.near = near;
shadowMap._sceneCamera.frustum.far = far;
shadowMap._distance = far - near;

checkVisibility(shadowMap, frameState);

if (!shadowMap._outOfViewPrevious && shadowMap._outOfView) {
shadowMap._needsUpdate = true;
}
shadowMap._outOfViewPrevious = shadowMap._outOfView;
}

/**
Expand Down

0 comments on commit 36e5fcf

Please sign in to comment.