From bef62841aee3bd8ef33f2c3c7e6ad7e2fb5adac5 Mon Sep 17 00:00:00 2001 From: Sean Lilley Date: Wed, 5 Sep 2018 17:17:41 -0400 Subject: [PATCH] Improve shadow derived command creation. Split up receive from cast --- Source/Scene/Scene.js | 12 ++++++--- Source/Scene/ShadowMap.js | 46 +++++++++++++++++++-------------- Source/Scene/ShadowMapShader.js | 4 +-- Specs/Scene/ShadowMapSpec.js | 19 +++++--------- 4 files changed, 43 insertions(+), 38 deletions(-) diff --git a/Source/Scene/Scene.js b/Source/Scene/Scene.js index f93f35934cb1..8161349f7924 100644 --- a/Source/Scene/Scene.js +++ b/Source/Scene/Scene.js @@ -1450,15 +1450,13 @@ define([ var frameState = scene._frameState; var context = scene._context; var oit = scene._view.oit; - var shadowsEnabled = frameState.shadowState.shadowsEnabled; - var shadowMaps = frameState.shadowState.shadowMaps; var lightShadowMaps = frameState.shadowState.lightShadowMaps; var lightShadowsEnabled = frameState.shadowState.lightShadowsEnabled; var derivedCommands = command.derivedCommands; - if (shadowsEnabled && (command.receiveShadows || command.castShadows)) { - derivedCommands.shadows = ShadowMap.createDerivedCommands(shadowMaps, lightShadowMaps, command, shadowsDirty, context, derivedCommands.shadows); + if (lightShadowsEnabled && command.receiveShadows) { + derivedCommands.shadows = ShadowMap.createReceiveDerivedCommand(lightShadowMaps, command, shadowsDirty, context, derivedCommands.shadows); } if (defined(command.pickId)) { @@ -1513,6 +1511,12 @@ define([ if (command.dirty) { command.dirty = false; + var shadowMaps = frameState.shadowState.shadowMaps; + var shadowsEnabled = frameState.shadowState.shadowsEnabled; + if (shadowsEnabled && command.castShadows) { + derivedCommands.shadows = ShadowMap.createCastDerivedCommand(shadowMaps, command, shadowsDirty, context, derivedCommands.shadows); + } + if (hasLogDepthDerivedCommands || needsLogDepthDerivedCommands) { derivedCommands.logDepth = DerivedCommand.createLogDepthCommand(command, context, derivedCommands.logDepth); updateDerivedCommands(this, derivedCommands.logDepth.command, shadowsDirty); diff --git a/Source/Scene/ShadowMap.js b/Source/Scene/ShadowMap.js index 98d875e1e8fa..d8fa87a3a23c 100644 --- a/Source/Scene/ShadowMap.js +++ b/Source/Scene/ShadowMap.js @@ -1528,7 +1528,7 @@ define([ return result; } - ShadowMap.createDerivedCommands = function(shadowMaps, lightShadowMaps, command, shadowsDirty, context, result) { + ShadowMap.createReceiveDerivedCommand = function(lightShadowMaps, command, shadowsDirty, context, result) { if (!defined(result)) { result = {}; } @@ -1544,24 +1544,6 @@ define([ hasTerrainNormal = command.owner.data.pickTerrain.mesh.encoding.hasVertexNormals; } - if (command.castShadows) { - var castCommands = result.castCommands; - if (!defined(castCommands)) { - castCommands = result.castCommands = []; - } - - var oldShaderId = result.castShaderProgramId; - - var shadowMapLength = shadowMaps.length; - castCommands.length = shadowMapLength; - - for (var i = 0; i < shadowMapLength; ++i) { - castCommands[i] = createCastDerivedCommand(shadowMaps[i], shadowsDirty, command, context, oldShaderId, castCommands[i]); - } - - result.castShaderProgramId = command.shaderProgram.id; - } - if (command.receiveShadows && lightShadowMapsEnabled) { // Only generate a receiveCommand if there is a shadow map originating from a light source. var receiveShader; @@ -1606,6 +1588,32 @@ define([ return result; }; + ShadowMap.createCastDerivedCommand = function(shadowMaps, command, shadowsDirty, context, result) { + if (!defined(result)) { + result = {}; + } + + if (command.castShadows) { + var castCommands = result.castCommands; + if (!defined(castCommands)) { + castCommands = result.castCommands = []; + } + + var oldShaderId = result.castShaderProgramId; + + var shadowMapLength = shadowMaps.length; + castCommands.length = shadowMapLength; + + for (var i = 0; i < shadowMapLength; ++i) { + castCommands[i] = createCastDerivedCommand(shadowMaps[i], shadowsDirty, command, context, oldShaderId, castCommands[i]); + } + + result.castShaderProgramId = command.shaderProgram.id; + } + + return result; + }; + /** * @private */ diff --git a/Source/Scene/ShadowMapShader.js b/Source/Scene/ShadowMapShader.js index 6b04939e652f..74bb6cc01c34 100644 --- a/Source/Scene/ShadowMapShader.js +++ b/Source/Scene/ShadowMapShader.js @@ -20,7 +20,7 @@ define([ var defines = vs.defines.slice(0); var sources = vs.sources.slice(0); - vs.defines.push('SHADOW_MAP'); + defines.push('SHADOW_MAP'); if (isTerrain) { defines.push('GENERATE_POSITION'); @@ -132,7 +132,7 @@ define([ var defines = vs.defines.slice(0); var sources = vs.sources.slice(0); - vs.defines.push('SHADOW_MAP'); + defines.push('SHADOW_MAP'); if (isTerrain) { if (hasTerrainNormal) { diff --git a/Specs/Scene/ShadowMapSpec.js b/Specs/Scene/ShadowMapSpec.js index 06ea1505f331..d8609a591018 100644 --- a/Specs/Scene/ShadowMapSpec.js +++ b/Specs/Scene/ShadowMapSpec.js @@ -1071,7 +1071,8 @@ defineSuite([ }); it('model updates derived commands when the shadow map is dirty', function() { - var spy = spyOn(ShadowMap, 'createDerivedCommands').and.callThrough(); + var spy1 = spyOn(ShadowMap, 'createReceiveDerivedCommand').and.callThrough(); + var spy2 = spyOn(ShadowMap, 'createCastDerivedCommand').and.callThrough(); box.show = true; floor.show = true; @@ -1117,18 +1118,10 @@ defineSuite([ scene.render(); } - var callCount; - if (!scene.logarithmicDepthBuffer) { - // Expect derived commands to be updated twice for both the floor and box, - // once on the first frame and again when the shadow map is dirty - callCount = 4; - } else { - // Same as without log z, but doubled. The derived cast commands do not write log z, but - // the derived receive commands do. - callCount = 8; - } - - expect(spy.calls.count()).toEqual(callCount); + // Expect derived commands to be updated twice for both the floor and box, + // once on the first frame and again when the shadow map is dirty + expect(spy1.calls.count()).toEqual(4); + expect(spy2.calls.count()).toEqual(4); box.show = false; floor.show = false;