Skip to content

Commit

Permalink
add simple color-to-alpha for imagery
Browse files Browse the repository at this point in the history
  • Loading branch information
likangning93 committed Apr 9, 2019
1 parent 4dc689b commit 1363dee
Show file tree
Hide file tree
Showing 8 changed files with 201 additions and 4 deletions.
87 changes: 87 additions & 0 deletions Apps/Sandcastle/gallery/Imagery Color To Alpha.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
<!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 simple color-to-alpha on imagery layers.">
<meta name="cesium-sandcastle-labels" content="Beginner, Tutorials">
<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);
#toolbar {
background: rgba(42, 42, 42, 0.8);
padding: 4px;
border-radius: 4px;
}
</style>
<div id="cesiumContainer" class="fullSize"></div>
<div id="loadingOverlay"><h1>Loading...</h1></div>
<div id="toolbar">
<table><tbody>
<tr>
<td>Threshold</td>
<td>
<input type="range" min="0.0" max="1.0" step="0.01" data-bind="value: threshold, valueUpdate: 'input'">
</td>
</tr>
</tbody></table>
</div>
<script id="cesium_sandcastle_script">
function startup(Cesium) {
'use strict';
//Sandcastle_Begin
var viewer = new Cesium.Viewer('cesiumContainer');

var layers = viewer.scene.imageryLayers;

// Set oceans on Bing base layer to transparent
var baseLayer = layers.get(0);
baseLayer.colorToAlpha = new Cesium.Color(0.0, 0.016, 0.059);
baseLayer.colorToAlphaThreshold = 0.2;

// Add a bump layer with adjustable threshold
var singleTileLayer = layers.addImageryProvider(new Cesium.SingleTileImageryProvider({
url : '../images/earthbump1k.jpg',
rectangle : Cesium.Rectangle.fromDegrees(-180.0, -90.0, 180.0, 90.0)
}));

singleTileLayer.colorToAlpha = new Cesium.Color(0.0, 0.0, 0.0, 1.0);
singleTileLayer.colorToAlphaThreshold = 0.1;

var viewModel = {
threshold : singleTileLayer.colorToAlphaThreshold
};

Cesium.knockout.track(viewModel);

var toolbar = document.getElementById('toolbar');
Cesium.knockout.applyBindings(viewModel, toolbar);

Cesium.knockout.getObservable(viewModel, 'threshold').subscribe(
function(newValue) {
singleTileLayer.colorToAlphaThreshold = parseFloat(viewModel.threshold);
}
);//Sandcastle_End
Sandcastle.finishedLoading();
}
if (typeof Cesium !== 'undefined') {
startup(Cesium);
} else if (typeof require === 'function') {
require(['Cesium'], startup);
}
</script>
</body>
</html>
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 @@ -5,6 +5,7 @@ Change Log

##### Additions :tada:
* Added support for the `KHR_texture_transform` glTF extension. [#7549](https://github.com/AnalyticalGraphicsInc/cesium/pull/7549)
* Added support for color-to-alpha with a threshold on imagery layers. [#7727](https://github.com/AnalyticalGraphicsInc/cesium/pull/7727)

##### Fixes :wrench:
* Fixed an error where `clampToHeightMostDetailed` or `sampleHeightMostDetailed` would crash if entities were created when the promise resolved. [#7690](https://github.com/AnalyticalGraphicsInc/cesium/pull/7690)
Expand Down
10 changes: 8 additions & 2 deletions Source/Scene/GlobeSurfaceShaderSet.js
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ define([
var hasImageryLayerCutout = options.hasImageryLayerCutout;
var colorCorrect = options.colorCorrect;
var highlightFillTile = options.highlightFillTile;
var colorToAlpha = options.colorToAlpha;

var quantization = 0;
var quantizationDefine = '';
Expand Down Expand Up @@ -147,7 +148,8 @@ define([
(cartographicLimitRectangleFlag << 20) |
(imageryCutoutFlag << 21) |
(colorCorrect << 22) |
(highlightFillTile << 23);
(highlightFillTile << 23) |
(colorToAlpha << 24);

var currentClippingShaderState = 0;
if (defined(clippingPlanes) && clippingPlanes.length > 0) {
Expand Down Expand Up @@ -207,6 +209,9 @@ define([
if (showOceanWaves) {
fs.defines.push('SHOW_OCEAN_WAVES');
}
if (colorToAlpha) {
fs.defines.push('APPLY_COLOR_TO_ALPHA');
}

if (enableLighting) {
if (hasVertexNormals) {
Expand Down Expand Up @@ -283,7 +288,8 @@ define([
' + (applyHue ? 'u_dayTextureHue[' + i + ']' : '0.0') + ',\n\
' + (applySaturation ? 'u_dayTextureSaturation[' + i + ']' : '0.0') + ',\n\
' + (applyGamma ? 'u_dayTextureOneOverGamma[' + i + ']' : '0.0') + ',\n\
' + (applySplit ? 'u_dayTextureSplit[' + i + ']' : '0.0') + '\n\
' + (applySplit ? 'u_dayTextureSplit[' + i + ']' : '0.0') + ',\n\
' + (colorToAlpha ? 'u_colorsToAlpha[' + i + ']' : 'vec4(0.0)') + '\n\
);\n';
if (hasImageryLayerCutout) {
computeDayColor += '\
Expand Down
25 changes: 24 additions & 1 deletion Source/Scene/GlobeSurfaceTileProvider.js
Original file line number Diff line number Diff line change
Expand Up @@ -1318,6 +1318,9 @@ define([
u_hsbShift : function() {
return this.properties.hsbShift;
},
u_colorsToAlpha : function() {
return this.properties.colorsToAlpha;
},

// make a separate object so that changes to the properties are seen on
// derived commands that combine another uniform map with this one.
Expand Down Expand Up @@ -1348,6 +1351,7 @@ define([
dayTextureSplit : [],
dayTextureCutoutRectangles : [],
dayIntensity : 0.0,
colorsToAlpha : [],

southAndNorthLatitude : new Cartesian2(),
southMercatorYAndOneOverHeight : new Cartesian2(),
Expand Down Expand Up @@ -1525,7 +1529,8 @@ define([
clippingPlanes : undefined,
clippedByBoundaries : undefined,
hasImageryLayerCutout : undefined,
colorCorrect : undefined
colorCorrect : undefined,
colorToAlpha : undefined
};

function addDrawCommandsForTile(tileProvider, tile, frameState) {
Expand Down Expand Up @@ -1782,6 +1787,7 @@ define([
var applyAlpha = false;
var applySplit = false;
var applyCutout = false;
var applyColorToAlpha = false;

while (numberOfDayTextures < maxTextures && imageryIndex < imageryLen) {
var tileImagery = tileImageryCollection[imageryIndex];
Expand Down Expand Up @@ -1860,6 +1866,22 @@ define([
dayTextureCutoutRectangle.w = (cutoutRectangle.north - cartographicTileRectangle.south) * inverseTileHeight;
}

// Update color to alpha
var colorToAlpha = uniformMapProperties.colorsToAlpha[numberOfDayTextures];
if (!defined(colorToAlpha)) {
colorToAlpha = uniformMapProperties.colorsToAlpha[numberOfDayTextures] = new Cartesian4();
}

applyColorToAlpha = defined(imageryLayer.colorToAlpha) && imageryLayer.colorToAlphaThreshold > 0.0;

if (applyColorToAlpha) {
var color = imageryLayer.colorToAlpha;
colorToAlpha.x = color.red;
colorToAlpha.y = color.green;
colorToAlpha.z = color.blue;
colorToAlpha.w = imageryLayer.colorToAlphaThreshold;
}

if (defined(imagery.credits)) {
var credits = imagery.credits;
for (var creditIndex = 0, creditLength = credits.length; creditIndex < creditLength; ++creditIndex) {
Expand Down Expand Up @@ -1906,6 +1928,7 @@ define([
surfaceShaderSetOptions.hasImageryLayerCutout = applyCutout;
surfaceShaderSetOptions.colorCorrect = colorCorrect;
surfaceShaderSetOptions.highlightFillTile = highlightFillTile;
surfaceShaderSetOptions.colorToAlpha = applyColorToAlpha;

command.shaderProgram = tileProvider._surfaceShaderSet.getShaderProgram(surfaceShaderSetOptions);
command.castShadows = castShadows;
Expand Down
24 changes: 24 additions & 0 deletions Source/Scene/ImageryLayer.js
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,8 @@ define([
* @param {Number} [options.maximumTerrainLevel] The maximum terrain level-of-detail at which to show this imagery layer,
* or undefined to show it at all levels. Level zero is the least-detailed level.
* @param {Rectangle} [options.cutoutRectangle] Cartographic rectangle for cutting out a portion of this ImageryLayer.
* @param {Color} [options.colorToAlpha] Color to be used as alpha.
* @param {Number} [options.colorToAlphaThreshold=0.004] Threshold for color-to-alpha.
*/
function ImageryLayer(imageryProvider, options) {
this._imageryProvider = imageryProvider;
Expand Down Expand Up @@ -287,6 +289,20 @@ define([
* @type {Rectangle}
*/
this.cutoutRectangle = options.cutoutRectangle;

/**
* Color value that should be set to transparent.
*
* @type {Color}
*/
this.colorToAlpha = options.colorToAlpha;

/**
* Normalized (0-1) threshold for color-to-alpha.
*
* @type {Number}
*/
this.colorToAlphaThreshold = defaultValue(options.colorToAlphaThreshold, ImageryLayer.DEFAULT_APPLY_COLOR_TO_ALPHA_THRESHOLD);
}

defineProperties(ImageryLayer.prototype, {
Expand Down Expand Up @@ -377,6 +393,14 @@ define([
*/
ImageryLayer.DEFAULT_MAGNIFICATION_FILTER = TextureMagnificationFilter.LINEAR;

/**
* This value is used as the default threshold for color-to-alpha if one is not provided
* during construction or by the imagery provider.
* @type {Number}
* @default 0.004
*/
ImageryLayer.DEFAULT_APPLY_COLOR_TO_ALPHA_THRESHOLD = 0.004;

/**
* Gets a value indicating whether this layer is the base layer in the
* {@link ImageryLayerCollection}. The base layer is the one that underlies all
Expand Down
13 changes: 12 additions & 1 deletion Source/Shaders/GlobeFS.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,10 @@ uniform float u_dayTextureOneOverGamma[TEXTURE_UNITS];
uniform vec4 u_dayTextureCutoutRectangles[TEXTURE_UNITS];
#endif

#ifdef APPLY_COLOR_TO_ALPHA
uniform vec4 u_colorsToAlpha[TEXTURE_UNITS];
#endif

uniform vec4 u_dayTextureTexCoordsRectangle[TEXTURE_UNITS];
#endif

Expand Down Expand Up @@ -115,7 +119,8 @@ vec4 sampleAndBlend(
float textureHue,
float textureSaturation,
float textureOneOverGamma,
float split)
float split,
vec4 colorToAlpha)
{
// This crazy step stuff sets the alpha to 0.0 if this following condition is true:
// tileTextureCoordinates.s < textureCoordinateRectangle.s ||
Expand All @@ -137,6 +142,12 @@ vec4 sampleAndBlend(
vec3 color = value.rgb;
float alpha = value.a;

#ifdef APPLY_COLOR_TO_ALPHA
vec3 colorDiff = abs(color.rgb - colorToAlpha.rgb);
colorDiff.r = max(max(colorDiff.r, colorDiff.g), colorDiff.b);
alpha = czm_branchFreeTernary(colorDiff.r < colorToAlpha.a, 0.0, alpha);
#endif

#if !defined(APPLY_GAMMA)
vec4 tempColor = czm_gammaCorrect(vec4(color, alpha));
color = tempColor.rgb;
Expand Down
45 changes: 45 additions & 0 deletions Specs/Scene/GlobeSurfaceTileProviderSpec.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
defineSuite([
'Scene/GlobeSurfaceTileProvider',
'Core/Cartesian3',
'Core/Cartesian4',
'Core/CesiumTerrainProvider',
'Core/Color',
'Core/Credit',
Expand Down Expand Up @@ -31,6 +32,7 @@ defineSuite([
], function(
GlobeSurfaceTileProvider,
Cartesian3,
Cartesian4,
CesiumTerrainProvider,
Color,
Credit,
Expand Down Expand Up @@ -590,6 +592,49 @@ defineSuite([
});
});

it('renders imagery with color-to-alpha', function() {
expect(scene).toRender([0, 0, 0, 255]);

var layer = scene.imageryLayers.addImageryProvider(new SingleTileImageryProvider({
url : 'Data/Images/Red16x16.png'
}));

switchViewMode(SceneMode.SCENE3D, new GeographicProjection(Ellipsoid.WGS84));

var layerColor;
return updateUntilDone(scene.globe).then(function() {
expect(scene).toRenderAndCall(function(rgba) {
layerColor = rgba;
// Expect the layer color to be mostly red
expect(layerColor[0]).toBeGreaterThan(layerColor[1]);
expect(layerColor[0]).toBeGreaterThan(layerColor[2]);
});

layer.colorToAlpha = new Color(1.0, 0.0, 0.0);
layer.colorToAlphaThreshold = 0.1;

return updateUntilDone(scene.globe);
})
.then(function() {
var commandList = scene.frameState.commandList;

for (var i = 0; i < commandList.length; ++i) {
var command = commandList[i];

var uniforms = command.uniformMap;
if (!defined(uniforms) || !defined(uniforms.u_dayTextureAlpha)) {
continue;
}

expect(uniforms.u_colorsToAlpha()).toEqual([new Cartesian4(1.0, 0.0, 0.0, 0.1)]);
}

expect(scene).toRenderAndCall(function(rgba) {
expect(rgba).not.toEqual(layerColor);
});
});
});

it('skips layer with uniform alpha value of zero', function() {
var layer = scene.imageryLayers.addImageryProvider(new SingleTileImageryProvider({
url : 'Data/Images/Red16x16.png'
Expand Down

0 comments on commit 1363dee

Please sign in to comment.