Skip to content
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

Improved Terrain Shadows #3765

Merged
merged 35 commits into from
Apr 5, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
c5a8266
Add normal biasing to improve terrain shadows and add biasing options…
lilleyse Mar 24, 2016
a3c6424
Fade out shadow map
lilleyse Mar 24, 2016
a0255d2
Fix point shadow shader
lilleyse Mar 24, 2016
93961fb
Merge branch 'shadows' into shadows-terrain-aliasing
lilleyse Mar 25, 2016
2b28265
Use different bias parameters for terrain and primitives
lilleyse Mar 28, 2016
fddd9d1
Added more sample models and locations, and added point light biasing…
lilleyse Mar 28, 2016
db6026e
Merge branch 'shadows' into shadows-terrain-aliasing
lilleyse Mar 28, 2016
3e5a10e
Added support for spot lights
lilleyse Mar 30, 2016
6baeee8
Remove visibility check for now
lilleyse Mar 30, 2016
42867f2
Random point light fixes
lilleyse Mar 30, 2016
ededdf0
Support exponential shadow maps, without perfiltering
lilleyse Mar 30, 2016
d5a6a24
Remove procedural shadow receiver code to GLSL files that are
bagnell Mar 31, 2016
0558e39
Merge branch 'shadows-terrain-aliasing' into shadows-shaders
bagnell Mar 31, 2016
4c50abb
Update after merge.
bagnell Mar 31, 2016
4804dbe
Remove unused file.
bagnell Mar 31, 2016
5772061
Fix terrain casting for point shadows
lilleyse Mar 31, 2016
0d4d6bc
Merge branch 'shadows-terrain-aliasing' into shadows-shaders
bagnell Mar 31, 2016
335c3d8
Merge branch 'master' into shadows-terrain-aliasing
lilleyse Mar 31, 2016
dcabbf7
Make cube map texture coordinates to 2D texture coordinates a built-i…
bagnell Mar 31, 2016
60a2099
Factor out some code common to all light types.
bagnell Mar 31, 2016
74bfe19
Don't cast shadows when picking
lilleyse Apr 1, 2016
907d46a
Small fixes
lilleyse Apr 1, 2016
be7bade
Added city-like model
lilleyse Apr 1, 2016
0b7138e
Fix globe shadow flickering by using more precise v_positionEC
lilleyse Apr 1, 2016
995063e
Use maximum depth instead of the last cascade depth to prevent early …
lilleyse Apr 1, 2016
ed8bd4b
Merge branch 'shadows' into shadows-terrain-aliasing
lilleyse Apr 1, 2016
e93fecf
Merge branch 'shadows-terrain-aliasing' into shadows-shaders
bagnell Apr 4, 2016
f81b190
Add some unit tests for new built-in GLSL functions.
bagnell Apr 4, 2016
086b6f1
Fix defines
lilleyse Apr 4, 2016
715b615
Fix cascade colors
lilleyse Apr 5, 2016
b8b81e8
Formatting
lilleyse Apr 5, 2016
a66edd0
Remove line
lilleyse Apr 5, 2016
7ee8b1e
Merge pull request #3794 from AnalyticalGraphicsInc/shadows-shaders
lilleyse Apr 5, 2016
872887d
Add UI options for globe visible and terrain enabled
lilleyse Apr 4, 2016
40355e5
Draw debug outlines for cameras and spot lights
lilleyse Apr 5, 2016
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
270 changes: 270 additions & 0 deletions Apps/SampleData/models/ShadowTester/Shadow_Tester_2.gltf

Large diffs are not rendered by default.

270 changes: 270 additions & 0 deletions Apps/SampleData/models/ShadowTester/Shadow_Tester_3.gltf

Large diffs are not rendered by default.

268 changes: 268 additions & 0 deletions Apps/SampleData/models/ShadowTester/Shadow_Tester_4.gltf

Large diffs are not rendered by default.

261 changes: 213 additions & 48 deletions Apps/Sandcastle/gallery/development/Shadows.html

Large diffs are not rendered by default.

28 changes: 28 additions & 0 deletions Source/Renderer/AutomaticUniforms.js
Original file line number Diff line number Diff line change
Expand Up @@ -1588,6 +1588,34 @@ define([
getValue : function(uniformState) {
return uniformState.shadowMap.texelStepSize;
}
}),

/**
* An automatic GLSL uniform representing the shadow map cascade distances.
*
* @alias czm_shadowMapCascadeDistances
* @glslUniform
*/
czm_shadowMapCascadeDistances : new AutomaticUniform({
size : 1,
datatype : WebGLConstants.FLOAT_VEC4,
getValue : function(uniformState) {
return uniformState.shadowMap.cascadeDistances;
}
}),

/**
* An automatic GLSL uniform representing the shadow map distance.
*
* @alias czm_shadowMapDistance
* @glslUniform
*/
czm_shadowMapDistance : new AutomaticUniform({
size : 1,
datatype : WebGLConstants.FLOAT,
getValue : function(uniformState) {
return uniformState.shadowMap.distance;
}
})
};

Expand Down
2 changes: 1 addition & 1 deletion Source/Scene/Camera.js
Original file line number Diff line number Diff line change
Expand Up @@ -253,7 +253,7 @@ define([
function updateViewMatrix(camera) {
Matrix4.computeView(camera._direction, camera._up, camera._right, camera._position, camera._viewMatrix);
Matrix4.multiply(camera._viewMatrix, camera._actualInvTransform, camera._viewMatrix);
Matrix4.inverseTransformation(camera._viewMatrix, camera._invViewMatrix);
Matrix4.inverse(camera._viewMatrix, camera._invViewMatrix);
}

var scratchCartographic = new Cartographic();
Expand Down
2 changes: 1 addition & 1 deletion Source/Scene/Globe.js
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,7 @@ define([
* @type {Boolean}
* @default true
*/
this.castShadows = true;
this.castShadows = false;

/**
* Determines whether the globe will receive shadows when shadow mapping is enabled.
Expand Down
6 changes: 5 additions & 1 deletion Source/Scene/GlobeSurfaceShaderSet.js
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,7 @@ define([
if (receiveShadows) {
var normalVarying = hasVertexNormals ? 'v_normalEC' : undefined;
vs.sources[1] = ShadowMapShader.createShadowReceiveVertexShader(vs.sources[1], frameState);
fs.sources[0] = ShadowMapShader.createShadowReceiveFragmentShader(fs.sources[0], frameState, normalVarying, 'v_positionEC');
fs.sources[0] = ShadowMapShader.createShadowReceiveFragmentShader(fs.sources[0], frameState, normalVarying, 'v_positionEC', true, fs.defines);
}

var shader = ShaderProgram.fromCache({
Expand Down Expand Up @@ -286,9 +286,13 @@ define([
vs.sources.push(getPositionMode(sceneMode));
vs.sources.push(get2DYPositionFraction(useWebMercatorProjection));

// Output v_positionEC
vs.defines.push('ENABLE_DAYNIGHT_SHADING');

vs.sources[1] = ShadowMapShader.createShadowCastVertexShader(vs.sources[1], frameState, 'v_positionEC');
fs.sources[0] = ShadowMapShader.createShadowCastFragmentShader(fs.sources[0], frameState, true, 'v_positionEC');


shadowCastShader = this._shadowCastPrograms[flags] = ShaderProgram.fromCache({
context : frameState.context,
vertexShaderSource : vs,
Expand Down
9 changes: 9 additions & 0 deletions Source/Scene/GlobeSurfaceTileProvider.js
Original file line number Diff line number Diff line change
Expand Up @@ -503,6 +503,7 @@ define([
};

var modifiedModelViewScratch = new Matrix4();
var modifiedModelViewProjectionScratch = new Matrix4();
var tileRectangleScratch = new Cartesian4();
var rtcScratch = new Cartesian3();
var centerEyeScratch = new Cartesian3();
Expand Down Expand Up @@ -676,6 +677,14 @@ define([
Matrix4.setTranslation(viewMatrix, centerEye, modifiedModelViewScratch);
return modifiedModelViewScratch;
},
u_modifiedModelViewProjection : function() {
var viewMatrix = frameState.context.uniformState.view;
var projectionMatrix = frameState.context.uniformState.projection;
var centerEye = Matrix4.multiplyByPoint(viewMatrix, this.center3D, centerEyeScratch);
Matrix4.setTranslation(viewMatrix, centerEye, modifiedModelViewProjectionScratch);
Matrix4.multiply(projectionMatrix, modifiedModelViewProjectionScratch, modifiedModelViewProjectionScratch);
return modifiedModelViewProjectionScratch;
},
u_dayTextures : function() {
return this.dayTextures;
},
Expand Down
10 changes: 7 additions & 3 deletions Source/Scene/Model.js
Original file line number Diff line number Diff line change
Expand Up @@ -1511,18 +1511,22 @@ define([
attributeLocations : attributeLocations
});
}

// Modify draw program to receive shadows
var shadowDefines = [];
if (shadowsEnabled && model.receiveShadows) {
drawVS = ShadowMapShader.createShadowReceiveVertexShader(drawVS, frameState);
// TODO : assumes the shader has these varyings, which may not be true for some models
drawFS = ShadowMapShader.createShadowReceiveFragmentShader(drawFS, frameState, 'v_normal', 'v_positionEC');
drawFS = ShadowMapShader.createShadowReceiveFragmentShader(drawFS, frameState, 'v_normal', 'v_positionEC', false, shadowDefines);
}

model._rendererResources.programs[id] = ShaderProgram.fromCache({
context : context,
vertexShaderSource : drawVS,
fragmentShaderSource : drawFS,
fragmentShaderSource : new ShaderSource({
sources : [drawFS],
defines : shadowDefines
}),
attributeLocations : attributeLocations
});

Expand Down
8 changes: 6 additions & 2 deletions Source/Scene/Primitive.js
Original file line number Diff line number Diff line change
Expand Up @@ -1155,16 +1155,20 @@ define([
validateShaderMatching(primitive._pickSP, attributeLocations);

// Modify program to receive shadows
var shadowDefines = [];
if (shadowsEnabled && primitive._receiveShadows) {
vs = ShadowMapShader.createShadowReceiveVertexShader(vs, frameState);
fs = ShadowMapShader.createShadowReceiveFragmentShader(fs, frameState, 'v_normalEC', 'v_positionEC');
fs = ShadowMapShader.createShadowReceiveFragmentShader(fs, frameState, 'v_normalEC', 'v_positionEC', false, shadowDefines);
}

primitive._sp = ShaderProgram.replaceCache({
context : context,
shaderProgram : primitive._sp,
vertexShaderSource : vs,
fragmentShaderSource : fs,
fragmentShaderSource : new ShaderSource({
sources : [fs],
defines : shadowDefines
}),
attributeLocations : attributeLocations
});
validateShaderMatching(primitive._sp, attributeLocations);
Expand Down
40 changes: 29 additions & 11 deletions Source/Scene/Scene.js
Original file line number Diff line number Diff line change
Expand Up @@ -1687,43 +1687,62 @@ define([

function getShadowMapCommands(scene) {
// TODO : temporary solution for testing
var shadowMapCommands = [];
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) {
shadowMapCommands.push(command);
shadowCommands.push(command);
}
}
}
}
return shadowMapCommands;
return [terrainCommands, primitiveCommands];
}

function executeShadowMapCommands(scene) {
var context = scene.context;
var uniformState = context.uniformState;
var shadowMap = scene.shadowMap;
var renderState = shadowMap.renderState;
var isPointLight = shadowMap.isPointLight;

var commands = getShadowMapCommands(scene);
var numberOfCommands = commands.length;
var terrainCommands = commands[0];
var primitiveCommands = commands[1];

var j;
var command;

var numberOfPasses = shadowMap.numberOfPasses;
for (var i = 0; i < numberOfPasses; ++i) {
uniformState.updateCamera(shadowMap.passCameras[i]);
var passState = shadowMap.passStates[i];
shadowMap.updatePass(context, i);
for (var j = 0; j < numberOfCommands; ++j) {
var command = commands[j];
executeCommand(command, scene, context, passState, renderState, command.shadowCastProgram);

// 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);
}
}
}
Expand All @@ -1733,7 +1752,6 @@ define([

var viewport = passState.viewport;

var uniformState = context.uniformState;
var frameState = scene._frameState;
var camera = frameState.camera;
var mode = frameState.mode;
Expand All @@ -1744,7 +1762,7 @@ define([
updateAndClearFramebuffers(scene, passState, backgroundColor, picking);
executeComputeCommands(scene);

if (scene.shadowMap.enabled) {
if (scene.shadowMap.enabled && !picking) {
executeShadowMapCommands(scene);
}

Expand Down Expand Up @@ -1895,7 +1913,7 @@ define([
updateAndClearFramebuffers(scene, passState, backgroundColor, picking);
executeComputeCommands(scene);

if (scene.shadowMap.enabled) {
if (scene.shadowMap.enabled && !picking) {
executeShadowMapCommands(scene);
}
}
Expand Down
Loading