Skip to content

Commit

Permalink
Merge pull request #4314 from jasonbeverage/modelhighlight
Browse files Browse the repository at this point in the history
Support for model outlining
  • Loading branch information
pjcozzi authored Dec 14, 2016
2 parents 14a0710 + 7a399f2 commit 403af69
Show file tree
Hide file tree
Showing 16 changed files with 635 additions and 21 deletions.
64 changes: 56 additions & 8 deletions Apps/Sandcastle/gallery/3D Models Coloring.html
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,15 @@
padding-top: 2px;
padding-bottom: 2px;
}
#toolbar .header {
font-weight: bold;
}
</style>
<div id="cesiumContainer" class="fullSize"></div>
<div id="loadingOverlay"><h1>Loading...</h1></div>
<div id="toolbar">
<table><tbody>
<tr><td class="header">Model Color</td></tr>
<tr>
<td>Mode</td>
<td><select data-bind="options: colorBlendModes, value: colorBlendMode"></select></td>
Expand All @@ -56,6 +60,25 @@
<input type="text" size="5" data-bind="value: colorBlendAmount, enable: colorBlendAmountEnabled">
</td>
</tr>
<tr><td class="header">Model Silhouette</td></tr>
<tr>
<td>Color</td>
<td><select data-bind="options: silhouetteColors, value: silhouetteColor"></select></td>
</tr>
<tr>
<td>Alpha</td>
<td>
<input type="range" min="0.0" max="1.0" step="0.01" data-bind="value: silhouetteAlpha, valueUpdate: 'input'">
<input type="text" size="5" data-bind="value: silhouetteAlpha">
</td>
</tr>
<tr>
<td>Size</td>
<td>
<input type="range" min="0.0" max="10.0" step="0.01" data-bind="value: silhouetteSize, valueUpdate: 'input'">
<input type="text" size="5" data-bind="value: silhouetteSize">
</td>
</tr>
</tbody></table>
</div>
<script id="cesium_sandcastle_script">
Expand All @@ -74,8 +97,9 @@
return Cesium.ColorBlendMode[colorBlendMode.toUpperCase()];
}

function getColor(color) {
return Cesium.Color[color.toUpperCase()];
function getColor(colorName, alpha) {
var color = Cesium.Color[colorName.toUpperCase()];
return Cesium.Color.fromAlpha(color, parseFloat(alpha));
}

// The viewModel tracks the state of our mini application.
Expand All @@ -86,7 +110,11 @@
colorBlendMode : 'Highlight',
colorBlendModes : ['Highlight', 'Replace', 'Mix'],
colorBlendAmount : 0.5,
colorBlendAmountEnabled : false
colorBlendAmountEnabled : false,
silhouetteColor : 'Red',
silhouetteColors : ['Red', 'Green', 'Blue', 'Yellow', 'Gray'],
silhouetteAlpha : 1.0,
silhouetteSize : 2.0
};

// Convert the viewModel members into knockout observables.
Expand All @@ -98,13 +126,13 @@

Cesium.knockout.getObservable(viewModel, 'color').subscribe(
function(newValue) {
entity.model.color = Cesium.Color.fromAlpha(getColor(newValue), viewModel.alpha);
entity.model.color = getColor(newValue, viewModel.alpha);
}
);

Cesium.knockout.getObservable(viewModel, 'alpha').subscribe(
function(newValue) {
entity.model.color = Cesium.Color.fromAlpha(getColor(viewModel.color), newValue);
entity.model.color = getColor(viewModel.color, newValue);
}
);

Expand All @@ -118,7 +146,25 @@

Cesium.knockout.getObservable(viewModel, 'colorBlendAmount').subscribe(
function(newValue) {
entity.model.colorBlendAmount = newValue;
entity.model.colorBlendAmount = parseFloat(newValue);
}
);

Cesium.knockout.getObservable(viewModel, 'silhouetteColor').subscribe(
function(newValue) {
entity.model.silhouetteColor = getColor(newValue, viewModel.silhouetteAlpha);
}
);

Cesium.knockout.getObservable(viewModel, 'silhouetteAlpha').subscribe(
function(newValue) {
entity.model.silhouetteColor = getColor(viewModel.silhouetteColor, newValue);
}
);

Cesium.knockout.getObservable(viewModel, 'silhouetteSize').subscribe(
function(newValue) {
entity.model.silhouetteSize = parseFloat(newValue);
}
);

Expand All @@ -140,9 +186,11 @@
uri : url,
minimumPixelSize : 128,
maximumScale : 20000,
color : Cesium.Color.fromAlpha(getColor(viewModel.color), viewModel.alpha),
color : getColor(viewModel.color, viewModel.alpha),
colorBlendMode : getColorBlendMode(viewModel.colorBlendMode),
colorBlendAmount : viewModel.colorBlendAmount
colorBlendAmount : parseFloat(viewModel.colorBlendAmount),
silhouetteColor : getColor(viewModel.silhouetteColor, viewModel.silhouetteAlpha),
silhouetteSize : parseFloat(viewModel.silhouetteSize)
}
});
viewer.trackedEntity = entity;
Expand Down
1 change: 1 addition & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ Change Log
### 1.29 - 2017-01-02

* Added the ability to blend a `Model` with a color/translucency. Added `color`, `colorBlendMode`, and `colorBlendAmount` properties to `Model`, `ModelGraphics`, and CZML. Added `ColorBlendMode` enum. [#4547](https://github.com/AnalyticalGraphicsInc/cesium/pull/4547)
* Added the ability to render a `Model` with a silhouette. Added `silhouetteColor` and `silhouetteSize` properties to `Model`, `ModelGraphics`, and CZML. [#4314](https://github.com/AnalyticalGraphicsInc/cesium/pull/4314)
* Added new `Label` properties `showBackground`, `backgroundColor`, and `backgroundPadding` to the primitive, Entity, and CZML layers.
* Added new enum `VerticalOrigin.BASELINE`. Previously, `VerticalOrigin.BOTTOM` would sometimes align to the baseline depending on the contents of a label.
* Added support for newlines (`\n`) in Cesium `Label`s and CZML. [#2402](https://github.com/AnalyticalGraphicsInc/cesium/issues/2402)
Expand Down
2 changes: 2 additions & 0 deletions Source/DataSources/CzmlDataSource.js
Original file line number Diff line number Diff line change
Expand Up @@ -1420,6 +1420,8 @@ define([
processPacketData(Boolean, model, 'runAnimations', modelData.runAnimations, interval, sourceUri, entityCollection);
processPacketData(ShadowMode, model, 'shadows', modelData.shadows, interval, sourceUri, entityCollection);
processPacketData(HeightReference, model, 'heightReference', modelData.heightReference, interval, sourceUri, entityCollection);
processPacketData(Color, model, 'silhouetteColor', modelData.silhouetteColor, interval, sourceUri, entityCollection);
processPacketData(Number, model, 'silhouetteSize', modelData.silhouetteSize, interval, sourceUri, entityCollection);
processPacketData(Color, model, 'color', modelData.color, interval, sourceUri, entityCollection);
processPacketData(ColorBlendMode, model, 'colorBlendMode', modelData.colorBlendMode, interval, sourceUri, entityCollection);
processPacketData(Number, model, 'colorBlendAmount', modelData.colorBlendAmount, interval, sourceUri, entityCollection);
Expand Down
26 changes: 26 additions & 0 deletions Source/DataSources/ModelGraphics.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ define([
* @param {Property} [options.shadows=ShadowMode.ENABLED] An enum Property specifying whether the model casts or receives shadows from each light source.
* @param {Property} [options.heightReference=HeightReference.NONE] A Property specifying what the height is relative to.
* @param {Property} [options.distanceDisplayCondition] A Property specifying at what distance from the camera that this model will be displayed.
* @param {Property} [options.silhouetteColor=Color.RED] A Property specifying the {@link Color} of the silhouette.
* @param {Property} [options.silhouetteSize=0.0] A numeric Property specifying the size of the silhouette in pixels.
* @param {Property} [options.color=Color.WHITE] A Property specifying the {@link Color} that blends with the model's rendered color.
* @param {Property} [options.colorBlendMode=ColorBlendMode.HIGHLIGHT] An enum Property specifying how the color blends with the model.
* @param {Property} [options.colorBlendAmount=0.5] A numeric Property specifying the color strength when the <code>colorBlendMode</code> is <code>MIX</code>. A value of 0.0 results in the model's rendered color while a value of 1.0 results in a solid color, with any value in-between resulting in a mix of the two.
Expand Down Expand Up @@ -80,6 +82,10 @@ define([
this._heightReferenceSubscription = undefined;
this._distanceDisplayCondition = undefined;
this._distanceDisplayConditionSubscription = undefined;
this._silhouetteColor = undefined;
this._silhouetteColorSubscription = undefined;
this._silhouetteSize = undefined;
this._silhouetteSizeSubscription = undefined;
this._color = undefined;
this._colorSubscription = undefined;
this._colorBlendMode = undefined;
Expand Down Expand Up @@ -197,6 +203,22 @@ define([
*/
distanceDisplayCondition : createPropertyDescriptor('distanceDisplayCondition'),

/**
* Gets or sets the Property specifying the {@link Color} of the silhouette.
* @memberof ModelGraphics.prototype
* @type {Property}
* @default Color.RED
*/
silhouetteColor: createPropertyDescriptor('silhouetteColor'),

/**
* Gets or sets the numeric Property specifying the size of the silhouette in pixels.
* @memberof ModelGraphics.prototype
* @type {Property}
* @default 0.0
*/
silhouetteSize : createPropertyDescriptor('silhouetteSize'),

/**
* Gets or sets the Property specifying the {@link Color} that blends with the model's rendered color.
* @memberof ModelGraphics.prototype
Expand Down Expand Up @@ -245,6 +267,8 @@ define([
result.nodeTransformations = this.nodeTransformations;
result.heightReference = this._heightReference;
result.distanceDisplayCondition = this.distanceDisplayCondition;
result.silhouetteColor = this.silhouetteColor;
result.silhouetteSize = this.silhouetteSize;
result.color = this.color;
result.colorBlendMode = this.colorBlendMode;
result.colorBlendAmount = this.colorBlendAmount;
Expand Down Expand Up @@ -275,6 +299,8 @@ define([
this.runAnimations = defaultValue(this.runAnimations, source.runAnimations);
this.heightReference = defaultValue(this.heightReference, source.heightReference);
this.distanceDisplayCondition = defaultValue(this.distanceDisplayCondition, source.distanceDisplayCondition);
this.silhouetteColor = defaultValue(this.silhouetteColor, source.silhouetteColor);
this.silhouetteSize = defaultValue(this.silhouetteSize, source.silhouetteSize);
this.color = defaultValue(this.color, source.color);
this.colorBlendMode = defaultValue(this.colorBlendMode, source.colorBlendMode);
this.colorBlendAmount = defaultValue(this.colorBlendAmount, source.colorBlendAmount);
Expand Down
4 changes: 4 additions & 0 deletions Source/DataSources/ModelVisualizer.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ define([
var defaultIncrementallyLoadTextures = true;
var defaultShadows = ShadowMode.ENABLED;
var defaultHeightReference = HeightReference.NONE;
var defaultSilhouetteColor = Color.RED;
var defaultSilhouetteSize = 0.0;
var defaultColor = Color.WHITE;
var defaultColorBlendMode = ColorBlendMode.HIGHLIGHT;
var defaultColorBlendAmount = 0.5;
Expand Down Expand Up @@ -147,6 +149,8 @@ define([
model.shadows = Property.getValueOrDefault(modelGraphics._shadows, time, defaultShadows);
model.heightReference = Property.getValueOrDefault(modelGraphics._heightReference, time, defaultHeightReference);
model.distanceDisplayCondition = Property.getValueOrUndefined(modelGraphics._distanceDisplayCondition, time);
model.silhouetteColor = Property.getValueOrDefault(modelGraphics.silhouetteColor, time, defaultSilhouetteColor);
model.silhouetteSize = Property.getValueOrDefault(modelGraphics.silhouetteSize, time, defaultSilhouetteSize);
model.color = Property.getValueOrDefault(modelGraphics._color, time, defaultColor, color);
model.colorBlendMode = Property.getValueOrDefault(modelGraphics._colorBlendMode, time, defaultColorBlendMode);
model.colorBlendAmount = Property.getValueOrDefault(modelGraphics._colorBlendAmount, time, defaultColorBlendAmount);
Expand Down
12 changes: 12 additions & 0 deletions Source/Renderer/Context.js
Original file line number Diff line number Diff line change
Expand Up @@ -508,6 +508,18 @@ define([
}
},

/**
* <code>true</code> if the WebGL context supports stencil buffers.
* Stencil buffers are not supported by all systems.
* @memberof Context.prototype
* @type {Boolean}
*/
stencilBuffer : {
get : function() {
return this._stencilBits >= 8;
}
},

/**
* <code>true</code> if the WebGL context supports antialiasing. By default
* antialiasing is requested, but it is not supported by all systems.
Expand Down
2 changes: 1 addition & 1 deletion Source/Renderer/RenderState.js
Original file line number Diff line number Diff line change
Expand Up @@ -589,7 +589,7 @@ define([
// Section 6.8 of the WebGL spec requires the reference and masks to be the same for
// front- and back-face tests. This call prevents invalid operation errors when calling
// stencilFuncSeparate on Firefox. Perhaps they should delay validation to avoid requiring this.
gl.stencilFunc(stencilTest.frontFunction, stencilTest.reference, stencilTest.mask);
gl.stencilFunc(frontFunction, reference, mask);
gl.stencilFuncSeparate(gl.BACK, backFunction, reference, mask);
gl.stencilFuncSeparate(gl.FRONT, frontFunction, reference, mask);

Expand Down
3 changes: 3 additions & 0 deletions Source/Scene/ColorBlendMode.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ define([
MIX : 2
};

/**
* @private
*/
ColorBlendMode.getColorBlend = function(colorBlendMode, colorBlendAmount) {
if (colorBlendMode === ColorBlendMode.HIGHLIGHT) {
return 0.0;
Expand Down
2 changes: 1 addition & 1 deletion Source/Scene/GroundPrimitive.js
Original file line number Diff line number Diff line change
Expand Up @@ -396,7 +396,7 @@ define([
* @returns {Boolean} <code>true</code> if GroundPrimitives are supported; otherwise, returns <code>false</code>
*/
GroundPrimitive.isSupported = function(scene) {
return scene.context.fragmentDepth;
return scene.context.fragmentDepth && scene.context.stencilBuffer;
};

GroundPrimitive._defaultMaxTerrainHeight = 9000.0;
Expand Down
Loading

0 comments on commit 403af69

Please sign in to comment.