-
Notifications
You must be signed in to change notification settings - Fork 3.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Cull shadow commands #3819
Cull shadow commands #3819
Changes from 5 commits
f58ded2
7b943e8
9dbb5c3
ae48196
cc09976
b5c45ea
def5187
40a68bc
0582b1f
6babfbd
c30e606
916050d
249322a
21f79df
8648679
aba1981
465d88a
32afa8e
481b239
bd98b6b
b3c5fcf
16da6a8
6471382
8409ee6
de6192e
7436308
0d1b1f1
fee0316
282e963
b756123
833f158
9cb906f
4f1b65e
6407d78
49cb616
2cffb31
1bd1c37
f1ede3c
5677298
e59ef50
9ef9d74
ad94eb8
1b89577
524e431
6198cfb
9c6f37f
5538b42
ba3a661
df04f64
5626da7
21faca4
a28d349
1abfe29
cf89f82
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -1685,64 +1685,137 @@ define([ | |
} | ||
} | ||
|
||
function getShadowMapCommands(scene) { | ||
// TODO : temporary solution for testing | ||
var terrainCommands = []; | ||
var primitiveCommands = []; | ||
var frustumCommandsList = scene._frustumCommandsList; | ||
var numFrustums = frustumCommandsList.length; | ||
for (var i = 0; i < numFrustums; ++i) { | ||
var frustumCommands = frustumCommandsList[i]; | ||
var startPass = Pass.GLOBE; | ||
var endPass = Pass.TRANSLUCENT; | ||
for (var pass = startPass; pass <= endPass; ++pass) { | ||
var shadowCommands = (pass === Pass.GLOBE) ? terrainCommands : primitiveCommands; | ||
var commands = frustumCommands.commands[pass]; | ||
var length = frustumCommands.indices[pass]; | ||
for (var j = 0; j < length; ++j) { | ||
var command = commands[j]; | ||
if (command.castShadows) { | ||
shadowCommands.push(command); | ||
function getTerrainShadowCommands(scene, shadowMap) { | ||
var frameState = scene.frameState; | ||
|
||
var sceneCommandList = frameState.commandList; | ||
var sceneCamera = frameState.camera; | ||
var sceneCullingVolume = frameState.cullingVolume; | ||
|
||
var terrainCommands = []; // TODO : avoid allocation | ||
|
||
// Update frame state to render from the light camera | ||
frameState.commandList = terrainCommands; | ||
frameState.camera = shadowMap.shadowMapCamera; | ||
frameState.cullingVolume = shadowMap.shadowMapCullingVolume; | ||
|
||
// Collect terrain commands from the light's POV | ||
if (scene._globe && scene._globe.castShadows) { | ||
scene._globe.update(frameState); | ||
} | ||
|
||
// Revert back to original frame state | ||
frameState.commandList = sceneCommandList; | ||
frameState.camera = sceneCamera; | ||
frameState.cullingVolume = sceneCullingVolume; | ||
|
||
return terrainCommands; | ||
} | ||
|
||
// function getTerrainShadowCommands(scene, shadowMap) { | ||
// // TODO : Temporary for testing. Globe.update doesn't work with orthographic frustums currently | ||
// var terrainCommands = []; | ||
// var commandList = scene.frameState.commandList; | ||
// var length = commandList.length; | ||
// for (var i = 0; i < length; ++i) { | ||
// var command = commandList[i]; | ||
// if (command.castShadows && command.pass === Pass.GLOBE) { | ||
// terrainCommands.push(command); | ||
// } | ||
// } | ||
// | ||
// return terrainCommands; | ||
// } | ||
|
||
function insertShadowCommands(commandList, insertAll, shadowMap, shadowPassCommands) { | ||
var shadowVolume = shadowMap.shadowMapCullingVolume; | ||
var passVolumes = shadowMap.passCullingVolumes; | ||
|
||
var isPointLight = shadowMap.isPointLight; | ||
var center = shadowMap.pointLightPosition; | ||
var radius = shadowMap.pointLightRadius; | ||
|
||
var numberOfPasses = shadowMap.numberOfPasses; | ||
|
||
var length = commandList.length; | ||
for (var i = 0; i < length; ++i) { | ||
var command = commandList[i]; | ||
// Don't insert globe commands with the rest of the scene commands since they are handled separately | ||
if (command.castShadows && (insertAll || (command.pass === Pass.OPAQUE || command.pass === Pass.TRANSLUCENT))) { | ||
if (isPointLight) { | ||
if (defined(command.boundingVolume)) { | ||
var distance = command.boundingVolume.distanceSquaredTo(center); | ||
if (distance < radius * radius) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Store |
||
for (var k = 0; k < numberOfPasses; ++k) { | ||
shadowPassCommands[k].push(command); | ||
} | ||
} | ||
} | ||
} else { | ||
if (isVisible(command, shadowVolume)) { | ||
if (numberOfPasses <= 1) { | ||
shadowPassCommands[0].push(command); | ||
} else { | ||
var wasVisible = false; | ||
// Loop over cascades from largest to smallest | ||
for (var j = numberOfPasses - 1; j >= 0; --j) { | ||
var cascadeVolume = passVolumes[j]; | ||
if (isVisible(command, cascadeVolume)) { | ||
shadowPassCommands[j].push(command); | ||
wasVisible = true; | ||
} else if (wasVisible) { | ||
// If it was visible in the previous cascade but now isn't | ||
// then there is no need to check any more cascades | ||
break; | ||
} | ||
} | ||
} | ||
} | ||
} | ||
} | ||
} | ||
return [terrainCommands, primitiveCommands]; | ||
} | ||
|
||
function resetShadowCommands(passCommands) { | ||
var length = passCommands.length; | ||
for (var i = 0; i < length; ++i) { | ||
passCommands[i].length = 0; | ||
} | ||
} | ||
|
||
function executeShadowMapCommands(scene) { | ||
var context = scene.context; | ||
var uniformState = context.uniformState; | ||
var shadowMap = scene.shadowMap; | ||
var isPointLight = shadowMap.isPointLight; | ||
var renderState = isPointLight ? shadowMap.pointRenderState : shadowMap.primitiveRenderState; | ||
|
||
var commands = getShadowMapCommands(scene); | ||
var terrainCommands = commands[0]; | ||
var primitiveCommands = commands[1]; | ||
var shadowPassCommands = shadowMap.passCommands; | ||
resetShadowCommands(shadowPassCommands); | ||
|
||
var j; | ||
var command; | ||
// Insert the scene commands into the shadow map passes | ||
var sceneCommands = scene.frameState.commandList; | ||
insertShadowCommands(sceneCommands, false, shadowMap, shadowPassCommands); | ||
var terrainCommands = getTerrainShadowCommands(scene, shadowMap); | ||
insertShadowCommands(terrainCommands, true, shadowMap, shadowPassCommands); | ||
|
||
var numberOfPasses = shadowMap.numberOfPasses; | ||
|
||
// // TODO : testing only | ||
// for (var k = 0; k < numberOfPasses; ++k) { | ||
// console.log('Pass ' + k + ': ' + shadowPassCommands[k].length + ' commands.'); | ||
// } | ||
|
||
for (var i = 0; i < numberOfPasses; ++i) { | ||
uniformState.updateCamera(shadowMap.passCameras[i]); | ||
var passState = shadowMap.passStates[i]; | ||
shadowMap.updatePass(context, i); | ||
|
||
// Execute terrain commands | ||
var terrainRenderState = isPointLight ? shadowMap.pointRenderState : shadowMap.terrainRenderState; | ||
var numberOfTerrainCommands = terrainCommands.length; | ||
for (j = 0; j < numberOfTerrainCommands; ++j) { | ||
command = terrainCommands[j]; | ||
executeCommand(command, scene, context, passState, terrainRenderState, command.shadowCastProgram); | ||
} | ||
|
||
// Execute primitive commands | ||
var primitiveRenderState = isPointLight ? shadowMap.pointRenderState : shadowMap.primitiveRenderState; | ||
var numberOfPrimitiveCommands = primitiveCommands.length; | ||
for (j = 0; j < numberOfPrimitiveCommands; ++j) { | ||
command = primitiveCommands[j]; | ||
executeCommand(command, scene, context, passState, primitiveRenderState, command.shadowCastProgram); | ||
var passCommands = shadowPassCommands[i]; | ||
var numberOfCommands = passCommands.length; | ||
for (var j = 0; j < numberOfCommands; ++j) { | ||
var command = passCommands[j]; | ||
executeCommand(command, scene, context, passState, renderState, command.shadowCastProgram); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. A bit tangential, but |
||
} | ||
} | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not for this PR, but long-term, we can evaluate avoiding linear searches like this, e.g., "is opaque or translucent", by using separate lists.