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

Add Material Support to Globe #5919

Merged
merged 35 commits into from
Nov 25, 2017
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
24ff46b
Added material support to the globe
jasonbeverage Oct 20, 2017
4e3ae37
Removed SlopeMaterial shader in favor of the SlopeRampMaterial which …
jasonbeverage Oct 20, 2017
6c2d17c
Got rid of multiple enableLighting calls
jasonbeverage Oct 20, 2017
ce71917
Unsetting uniformMap if there is no material
jasonbeverage Oct 20, 2017
a2152cc
Updated CHANGES.md
jasonbeverage Oct 20, 2017
5139bad
Updated CHANGES.md with PR reference
jasonbeverage Oct 20, 2017
29d4ae2
Fix eslint warning
jasonbeverage Oct 20, 2017
11325f2
Merge remote-tracking branch 'upstream/master' into globematerials
jasonbeverage Oct 20, 2017
9b7f7d9
Merge branch 'master' into globematerials
jasonbeverage Nov 1, 2017
60c0121
Style tweaks
lilleyse Nov 3, 2017
46d1a17
Merge branch 'master' into globematerials
lilleyse Nov 3, 2017
3ba02db
Merge branch 'master' into globematerials
lilleyse Nov 3, 2017
cbcaea1
Setting initial time in Globe Materials demo to make lighting look de…
jasonbeverage Nov 13, 2017
cff763d
Using defined to check for material in Globe
jasonbeverage Nov 13, 2017
5c619a9
Using defined to check for uniformMap
jasonbeverage Nov 13, 2017
7493d7c
Wrapping slope and height and globe shaders with APPLY_MATERIAL ifdef.
jasonbeverage Nov 13, 2017
5e4aab6
Renamed minHeight/maxHeight => minimumHeight/maximumHeight in Elevati…
jasonbeverage Nov 13, 2017
c045a6c
Added lineThickness uniform to ElevationContourMaterial
jasonbeverage Nov 13, 2017
8f4a8a1
fancy sandcastle demo
Nov 17, 2017
e8f9b04
Removed trailing whitespace to fix travis
jasonbeverage Nov 21, 2017
8ca9ac9
Changed link in CHANGES.md to Globe Material sandcastle demo
jasonbeverage Nov 25, 2017
0697c45
Changed dirtyShaders to makeShadersDirty and made it a file level fun…
jasonbeverage Nov 25, 2017
83dedf0
Remove comment
jasonbeverage Nov 25, 2017
a5fd43f
Formatting
jasonbeverage Nov 25, 2017
e469dd7
Renamed lineThickness to width for ElevationContourMaterial
jasonbeverage Nov 25, 2017
560caa5
Clarification of height in materialInput
jasonbeverage Nov 25, 2017
cc77f3a
Commenting slope in materialInput
jasonbeverage Nov 25, 2017
8c30e90
Not normalizing v_normalMC in GlobeVS.glsl
jasonbeverage Nov 25, 2017
5bd104f
Not reading varying values in GlobeVS
jasonbeverage Nov 25, 2017
a71d73a
Changed default viewpoint of GlobeMaterials to the Himalayas
jasonbeverage Nov 25, 2017
b42d079
Added unit tests for rendering a globe with materials
jasonbeverage Nov 25, 2017
0264ab1
Added sets material test for Globe
jasonbeverage Nov 25, 2017
8eb3bd4
Tweak CHANGES.md
pjcozzi Nov 25, 2017
217ce3a
Whitespace
pjcozzi Nov 25, 2017
fc88b02
Default Globe Material Sandcastle example to elevation shading
pjcozzi Nov 25, 2017
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
285 changes: 285 additions & 0 deletions Apps/Sandcastle/gallery/Globe Materials.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,285 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no">
<meta name="description" content="Apply materials to the globe.">
<meta name="cesium-sandcastle-labels" content="Showcases">
<title>Cesium Demo</title>
<script type="text/javascript" src="../Sandcastle-header.js"></script>
<script type="text/javascript" src="../../../ThirdParty/requirejs-2.1.20/require.js"></script>
<script type="text/javascript">
if(typeof require === "function") {
require.config({
baseUrl : '../../../Source',
waitSeconds : 120
});
}
</script>
</head>
<body class="sandcastle-loading" data-sandcastle-bucket="bucket-requirejs.html">
<style>
@import url(../templates/bucket.css);
.demo-container {
background-color: #303336;
border-radius: 5px;
padding: 5px;
margin: 5px 3px;
}
.demo-container input {
vertical-align: middle;
margin-top: 0;
}
</style>
<div id="cesiumContainer" class="fullSize"></div>
<div id="loadingOverlay"><h1>Loading...</h1></div>
<div id="toolbar">
<div id="zoomButtons"></div>
<div class="demo-container">
<label><input type="radio" name="shadingMaterials" value="none" data-bind="checked: selectedShading"> No shading</label>
<label><input type="radio" name="shadingMaterials" value="elevation" data-bind="checked: selectedShading"> Elevation</label>
<label><input type="radio" name="shadingMaterials" value="slope" data-bind="checked: selectedShading"> Slope</label>
</div>
<div class="demo-container">
<div>
<label><input type="checkbox" data-bind="checked: enableContour">Enable Contour Lines</label>
</div>
<div>
Spacing <input style="width: 136px" type="range" min="1.0" max="500.0" step="1.0" data-bind="value: contourSpacing, valueUpdate: 'input', enable: enableContour"> <span data-bind="text: contourSpacing"></span>m
</div>
<div>
Line Width <input style="width: 125px" type="range" min="1.0" max="10.0" step="1.0" data-bind="value: contourWidth, valueUpdate: 'input', enable: enableContour"> <span data-bind="text: contourWidth"></span>px
</div>
<div>
<button type="button" data-bind="click: changeColor, enable: enableContour">Change color</button>
</div>
</div>
</div>
<script id="cesium_sandcastle_script">
function startup(Cesium) {
'use strict';
//Sandcastle_Begin
var viewer = new Cesium.Viewer('cesiumContainer');
viewer.terrainProvider = new Cesium.CesiumTerrainProvider({
url : 'https://assets.agi.com/stk-terrain/v1/tilesets/world/tiles',
requestWaterMask : true,
requestVertexNormals : true
});
viewer.scene.globe.enableLighting = true;

function getElevationContourMaterial() {
// Creates a composite material with both elevation shading and contour lines
return new Cesium.Material({
fabric: {
type: 'ElevationColorContour',
materials: {
contourMaterial: {
type: 'ElevationContour'
},
elevationRampMaterial: {
type: 'ElevationRamp'
}
},
components: {
diffuse: 'contourMaterial.alpha == 0.0 ? elevationRampMaterial.diffuse : contourMaterial.diffuse',
alpha: 'max(contourMaterial.alpha, elevationRampMaterial.alpha)'
}
},
translucent: false
});
}

function getSlopeContourMaterial() {
// Creates a composite material with both slope shading and contour lines
return new Cesium.Material({
fabric: {
type: 'SlopeColorContour',
materials: {
contourMaterial: {
type: 'ElevationContour'
},
slopeRampMaterial: {
type: 'SlopeRamp'
}
},
components: {
diffuse: 'contourMaterial.alpha == 0.0 ? slopeRampMaterial.diffuse : contourMaterial.diffuse',
alpha: 'max(contourMaterial.alpha, slopeRampMaterial.alpha)'
}
},
translucent: false
});
}

var elevationRamp = [0.0, 0.045, 0.1, 0.15, 0.37, 0.54, 1.0];
var slopeRamp = [0.0, 0.29, 0.5, Math.sqrt(2)/2, 0.87, 0.91, 1.0];
function getColorRamp(selectedShading) {
var ramp = document.createElement('canvas');
ramp.width = 100;
ramp.height = 1;
var ctx = ramp.getContext('2d');

var values = selectedShading === 'elevation' ? elevationRamp : slopeRamp;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@hpinkos can the color ramp be tweaked to be a bit less subtle for the default view?

image

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or change the default view.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I changed the default view to be of the Himalayas


var grd = ctx.createLinearGradient(0, 0, 100, 0);
grd.addColorStop(values[0], '#000000'); //black
grd.addColorStop(values[1], '#2747E0'); //blue
grd.addColorStop(values[2], '#D33B7D'); //pink
grd.addColorStop(values[3], '#D33038'); //red
grd.addColorStop(values[4], '#FF9742'); //orange
grd.addColorStop(values[5], '#ffd700'); //yellow
grd.addColorStop(values[6], '#ffffff'); //white

ctx.fillStyle = grd;
ctx.fillRect(0, 0, 100, 1);

return ramp;
}

var minHeight = -414.0; // approximate dead sea elevation
var maxHeight = 8777.0; // approximate everest elevation
var contourColor = Cesium.Color.RED.clone();
var contourUniforms = {};
var shadingUniforms = {};

// The viewModel tracks the state of our mini application.
var viewModel = {
enableContour: false,
contourSpacing: 150.0,
contourWidth: 2.0,
selectedShading: 'elevation',
changeColor: function() {
contourUniforms.color = Cesium.Color.fromRandom({alpha: 1.0}, contourColor);
}
};

// Convert the viewModel members into knockout observables.
Cesium.knockout.track(viewModel);

// Bind the viewModel to the DOM elements of the UI that call for it.
var toolbar = document.getElementById('toolbar');
Cesium.knockout.applyBindings(viewModel, toolbar);

function updateMaterial() {
var hasContour = viewModel.enableContour;
var selectedShading = viewModel.selectedShading;
var globe = viewer.scene.globe;
var material;
if (hasContour) {
if (selectedShading === 'elevation') {
material = getElevationContourMaterial();
shadingUniforms = material.materials.elevationRampMaterial.uniforms;
shadingUniforms.minHeight = minHeight;
shadingUniforms.maxHeight = maxHeight;
contourUniforms = material.materials.contourMaterial.uniforms;
} else if (selectedShading === 'slope') {
material = getSlopeContourMaterial();
shadingUniforms = material.materials.slopeRampMaterial.uniforms;
contourUniforms = material.materials.contourMaterial.uniforms;
} else {
material = Cesium.Material.fromType('ElevationContour');
contourUniforms = material.uniforms;
}
contourUniforms.width = viewModel.contourWidth;
contourUniforms.spacing = viewModel.contourSpacing;
contourUniforms.color = contourColor;
} else if (selectedShading === 'elevation') {
material = Cesium.Material.fromType('ElevationRamp');
shadingUniforms = material.uniforms;
shadingUniforms.minHeight = minHeight;
shadingUniforms.maxHeight = maxHeight;
} else if (selectedShading === 'slope') {
material = Cesium.Material.fromType('SlopeRamp');
shadingUniforms = material.uniforms;
}
if (selectedShading !== 'none') {
shadingUniforms.image = getColorRamp(selectedShading);
}

globe.material = material;
}

updateMaterial();

Cesium.knockout.getObservable(viewModel, 'enableContour').subscribe(function(newValue) {
updateMaterial();
});

Cesium.knockout.getObservable(viewModel, 'contourWidth').subscribe(function(newValue) {
contourUniforms.width = parseFloat(newValue);
});

Cesium.knockout.getObservable(viewModel, 'contourSpacing').subscribe(function(newValue) {
contourUniforms.spacing = parseFloat(newValue);
});

Cesium.knockout.getObservable(viewModel, 'selectedShading').subscribe(function(value) {
updateMaterial();
});

Sandcastle.addToolbarMenu([{
text : 'Himalayas',
onselect : function() {
viewer.camera.setView({
destination: new Cesium.Cartesian3(322100.7492728492, 5917960.047024654, 3077602.646977297),
orientation: {
heading: 5.988151498702285,
pitch: -1.5614542839414822,
roll: 0
}
});
viewer.clockViewModel.currentTime = Cesium.JulianDate.fromIso8601('2017-09-22T04:00:00Z');
}
}, {
text : 'Half Dome',
onselect : function() {
viewer.camera.setView({
destination: new Cesium.Cartesian3(-2495709.521843174, -4391600.804712465, 3884463.7192916023),
orientation: {
heading: 1.7183056487769202,
pitch: -0.06460370548034144,
roll: 0.0079181631783527
}
});
viewer.clockViewModel.currentTime = Cesium.JulianDate.fromIso8601('2017-09-22T18:00:00Z');
}
}, {
text : 'Vancouver',
onselect : function() {
viewer.camera.setView({
destination: new Cesium.Cartesian3(-2301222.367751603, -3485269.915771613, 4812080.961755785),
orientation: {
heading: 0.11355958593902571,
pitch: -0.260011078090858,
roll: 0.00039019018274721873
}
});
viewer.clockViewModel.currentTime = Cesium.JulianDate.fromIso8601('2017-09-22T18:00:00Z');
}
}, {
text : 'Mount Everest',
onselect : function() {
viewer.camera.setView({
destination: new Cesium.Cartesian3(282157.6960889096, 5638892.465594703, 2978736.186473513),
orientation: {
heading: 4.747266966349747,
pitch: -0.2206998858596192,
roll: 6.280340554587955
}
});
viewer.clockViewModel.currentTime = Cesium.JulianDate.fromIso8601('2017-09-22T04:00:00Z');
}
}], 'zoomButtons');

//Sandcastle_End
Sandcastle.finishedLoading();
}
if (typeof Cesium !== "undefined") {
startup(Cesium);
} else if (typeof require === "function") {
require(["Cesium"], startup);
}
</script>
</body>
</html>
Binary file added Apps/Sandcastle/gallery/Globe Materials.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ Change Log

### 1.40 - 2017-12-01

* Added `Globe.material` to apply materials to the globe/terrain for shading such as height- or slope-based color ramps. See the new [Sandcastle example](https://cesiumjs.org/Cesium/Apps/Sandcastle/?src=Globe%20Materials.html&label=Showcases). [#5919](https://github.com/AnalyticalGraphicsInc/cesium/pull/5919/files)
* Added ability to support touch event in Imagery Layers Split demo application. [#5948](https://github.com/AnalyticalGraphicsInc/cesium/pull/5948)

### 1.39 - 2017-11-01
Expand Down
60 changes: 52 additions & 8 deletions Source/Scene/Globe.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ define([
'./GlobeSurfaceShaderSet',
'./GlobeSurfaceTileProvider',
'./ImageryLayerCollection',
'./Material',
'./QuadtreePrimitive',
'./SceneMode',
'./ShadowMode'
Expand Down Expand Up @@ -53,6 +54,7 @@ define([
GlobeSurfaceShaderSet,
GlobeSurfaceTileProvider,
ImageryLayerCollection,
Material,
QuadtreePrimitive,
SceneMode,
ShadowMode) {
Expand All @@ -79,14 +81,7 @@ define([
this._imageryLayerCollection = imageryLayerCollection;

this._surfaceShaderSet = new GlobeSurfaceShaderSet();

this._surfaceShaderSet.baseVertexShaderSource = new ShaderSource({
sources : [GroundAtmosphere, GlobeVS]
});

this._surfaceShaderSet.baseFragmentShaderSource = new ShaderSource({
sources : [GlobeFS]
});
this._material = undefined;

this._surface = new QuadtreePrimitive({
tileProvider : new GlobeSurfaceTileProvider({
Expand All @@ -99,6 +94,8 @@ define([
this._terrainProvider = terrainProvider;
this._terrainProviderChanged = new Event();

makeShadersDirty(this);

/**
* Determines if the globe will be shown.
*
Expand Down Expand Up @@ -276,9 +273,52 @@ define([
get: function() {
return this._surface.tileLoadProgressEvent;
}
},

/**
* Gets or sets the material appearance of the Globe. This can be one of several built-in {@link Material} objects or a custom material, scripted with
* {@link https://github.com/AnalyticalGraphicsInc/cesium/wiki/Fabric|Fabric}.
* @memberof Globe.prototype
* @type {Material}
*/
material: {
get: function() {
return this._material;
},
set: function(material) {
if (this._material !== material) {
this._material = material;
makeShadersDirty(this);
}
}
}
});

function makeShadersDirty(globe) {
var defines = [];

var fragmentSources = [];
if (defined(globe._material)) {
fragmentSources.push(globe._material.shaderSource);
defines.push('APPLY_MATERIAL');
globe._surface._tileProvider.uniformMap = globe._material._uniforms;
} else {
globe._surface._tileProvider.uniformMap = undefined;
}
fragmentSources.push(GlobeFS);

globe._surfaceShaderSet.baseVertexShaderSource = new ShaderSource({
sources : [GroundAtmosphere, GlobeVS],
defines : defines
});

globe._surfaceShaderSet.baseFragmentShaderSource = new ShaderSource({
sources : fragmentSources,
defines : defines
});
globe._surfaceShaderSet.material = globe._material;
}

function createComparePickTileFunction(rayOrigin) {
return function(a, b) {
var aDist = BoundingSphere.distanceSquaredTo(a.pickBoundingSphere, rayOrigin);
Expand Down Expand Up @@ -525,6 +565,10 @@ define([
return;
}

if (defined(this._material)) {
this._material.update(frameState.context);
}

var surface = this._surface;
var pass = frameState.passes;

Expand Down
Loading