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

Billboard transparency #4886

Merged
merged 17 commits into from
Jan 26, 2017
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
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
7 changes: 7 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ Change Log
==========

### 1.30 - 2017-02-01

* Deprecated
* The properties `url` and `key` will be removed from `GeocoderViewModel` in 1.31. These properties will be available on geocoder services that support them, like `BingMapsGeocoderService`.
* The function `createBinormalAndBitangent` of `GeometryPipeline` will be removed in 1.31. Use the function `createTangentAndBitangent` instead. [#4856](https://github.com/AnalyticalGraphicsInc/cesium/pull/4856)
Expand All @@ -26,8 +27,10 @@ Change Log
* Added `Rectangle.fromRadians`.
* `TerrainProvider` now optionally exposes an `availability` property that can be used to query the terrain level that is available at a location or in a rectangle. Currently only `CesiumTerrainProvider` exposes this property.
* Added `sampleTerrainMostDetailed` to sample the height of an array of positions using the best available terrain data at each point. This requires a `TerrainProvider` with the `availability` property.
* Transparent parts of billboards, labels, and points no longer overwrite parts of the scene behind them. [#4886](https://github.com/AnalyticalGraphicsInc/cesium/pull/4886)
Copy link
Contributor

Choose a reason for hiding this comment

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

Update this.


### 1.29 - 2017-01-02

* Improved 3D Models
* Added the ability to blend a `Model` with a color/translucency. Added `color`, `colorBlendMode`, and `colorBlendAmount` properties to `Model`, `ModelGraphics`, and CZML. Also 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)
Expand Down Expand Up @@ -63,6 +66,7 @@ Change Log
* Fixed `Cartographic.fromCartesian` when the cartesian is not on the ellipsoid surface. [#4611](https://github.com/AnalyticalGraphicsInc/cesium/issues/4611)

### 1.27 - 2016-11-01

* Deprecated
* Individual heading, pitch, and roll options to `Transforms.headingPitchRollToFixedFrame` and `Transforms.headingPitchRollQuaternion` have been deprecated and will be removed in 1.30. Pass the new `HeadingPitchRoll` object instead. [#4498](https://github.com/AnalyticalGraphicsInc/cesium/pull/4498)
* Breaking changes
Expand Down Expand Up @@ -201,9 +205,11 @@ Change Log
* Added `packArray` and `unpackArray` functions to `Cartesian2`, `Cartesian3`, and `Cartesian4`.

### 1.22.2 - 2016-06-14

* This is an npm only release to fix the improperly published 1.22.1. There were no code changes.

### 1.22.1 - 2016-06-13

* Fixed default Bing Key and added a watermark to notify users that they need to sign up for their own key.

### 1.22 - 2016-06-01
Expand Down Expand Up @@ -322,6 +328,7 @@ Change Log
* Fixed hole that appeared in the top of in dynamic ellipsoids

### 1.18 - 2016-02-01

* Breaking changes
* Removed support for `CESIUM_binary_glTF`. Use `KHR_binary_glTF` instead, which is the default for the online [COLLADA-to-glTF converter](http://cesiumjs.org/convertmodel.html).
* Deprecated
Expand Down
37 changes: 28 additions & 9 deletions Source/Scene/BillboardCollection.js
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,7 @@ define([
this._sp = undefined;
this._rs = undefined;
this._vaf = undefined;
this._spTranslucent = undefined;
this._spPick = undefined;

this._billboards = [];
Expand Down Expand Up @@ -1482,11 +1483,27 @@ define([
vs.defines.push('DISTANCE_DISPLAY_CONDITION');
}

fs = new ShaderSource({
Copy link
Contributor

Choose a reason for hiding this comment

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

Here and in the point cloud, shouldn't the render state be different for each pass? Opaque writes depth; translucent does not.

defines : ['OPAQUE'],
sources : [BillboardCollectionFS]
});
this._sp = ShaderProgram.replaceCache({
context : context,
shaderProgram : this._sp,
vertexShaderSource : vs,
fragmentShaderSource : BillboardCollectionFS,
fragmentShaderSource : fs,
attributeLocations : attributeLocations
});

fs = new ShaderSource({
defines : ['TRANSLUCENT'],
sources : [BillboardCollectionFS]
});
this._spTranslucent = ShaderProgram.replaceCache({
context : context,
shaderProgram : this._spTranslucent,
vertexShaderSource : vs,
fragmentShaderSource : fs,
attributeLocations : attributeLocations
});

Expand All @@ -1502,21 +1519,22 @@ define([
vaLength = va.length;

colorList.length = vaLength;
for (j = 0; j < vaLength; ++j) {
for (j = 0; j < vaLength * 2; ++j) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Minor, but extract * 2 from the loop.

command = colorList[j];
if (!defined(command)) {
command = colorList[j] = new DrawCommand({
pass : Pass.OPAQUE,
owner : this
});
command = colorList[j] = new DrawCommand();
}

command.pass = (j % 2 === 0) ? Pass.OPAQUE : Pass.TRANSLUCENT;
command.owner = this;

var index = Math.floor(j / 2.0);
command.boundingVolume = boundingVolume;
command.modelMatrix = modelMatrix;
command.count = va[j].indicesCount;
command.shaderProgram = this._sp;
command.count = va[index].indicesCount;
command.shaderProgram = (j % 2 === 0) ? this._sp : this._spTranslucent;
command.uniformMap = this._uniforms;
command.vertexArray = va[j].va;
command.vertexArray = va[index].va;
command.renderState = this._rs;
command.debugShowBoundingVolume = this.debugShowBoundingVolume;

Expand Down Expand Up @@ -1658,6 +1676,7 @@ define([

this._textureAtlas = this._destroyTextureAtlas && this._textureAtlas && this._textureAtlas.destroy();
this._sp = this._sp && this._sp.destroy();
this._spTranslucent = this._spTranslucent && this._spTranslucent.destroy();
this._spPick = this._spPick && this._spPick.destroy();
this._vaf = this._vaf && this._vaf.destroy();
destroyBillboards(this._billboards);
Expand Down
37 changes: 28 additions & 9 deletions Source/Scene/PointPrimitiveCollection.js
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ define([
this._sp = undefined;
this._rs = undefined;
this._vaf = undefined;
this._spTranslucent = undefined;
this._spPick = undefined;

this._pointPrimitives = [];
Expand Down Expand Up @@ -875,11 +876,27 @@ define([
vs.defines.push('DISTANCE_DISPLAY_CONDITION');
}

fs = new ShaderSource({
defines : ['OPAQUE'],
sources : [PointPrimitiveCollectionFS]
});
this._sp = ShaderProgram.replaceCache({
context : context,
shaderProgram : this._sp,
vertexShaderSource : vs,
fragmentShaderSource : PointPrimitiveCollectionFS,
fragmentShaderSource : fs,
attributeLocations : attributeLocations
});

fs = new ShaderSource({
defines : ['TRANSLUCENT'],
sources : [PointPrimitiveCollectionFS]
});
this._spTranslucent = ShaderProgram.replaceCache({
context : context,
shaderProgram : this._spTranslucent,
vertexShaderSource : vs,
fragmentShaderSource : fs,
attributeLocations : attributeLocations
});

Expand All @@ -892,21 +909,22 @@ define([
vaLength = va.length;

colorList.length = vaLength;
for (j = 0; j < vaLength; ++j) {
for (j = 0; j < vaLength * 2; ++j) {
command = colorList[j];
if (!defined(command)) {
command = colorList[j] = new DrawCommand({
primitiveType : PrimitiveType.POINTS,
pass : Pass.OPAQUE,
owner : this
});
command = colorList[j] = new DrawCommand();
}

command.primitiveType = PrimitiveType.POINTS;
command.pass = (j % 2 === 0) ? Pass.OPAQUE : Pass.TRANSLUCENT;
Copy link
Contributor

Choose a reason for hiding this comment

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

Let's make a public enum with the following properties:

  • OPAQUE
  • TRANSLUCENT
  • OPAQUE_AND_TRANSLUCENT

Billboard, label, and point collections can expose this property (get/set ideally) and default to OPAQUE_AND_TRANSLUCENT. Make sure the reference doc clearly defines the performance vs. visual quality tradeoffs.

command.owner = this;

var index = Math.floor(j / 2.0);
command.boundingVolume = boundingVolume;
command.modelMatrix = modelMatrix;
command.shaderProgram = this._sp;
command.shaderProgram = (j % 2 === 0) ? this._sp : this._spTranslucent;
command.uniformMap = this._uniforms;
command.vertexArray = va[j].va;
command.vertexArray = va[index].va;
command.renderState = this._rs;
command.debugShowBoundingVolume = this.debugShowBoundingVolume;

Expand Down Expand Up @@ -1015,6 +1033,7 @@ define([
*/
PointPrimitiveCollection.prototype.destroy = function() {
this._sp = this._sp && this._sp.destroy();
this._spTranslucent = this._spTranslucent && this._spTranslucent.destroy();
this._spPick = this._spPick && this._spPick.destroy();
this._vaf = this._vaf && this._vaf.destroy();
destroyPointPrimitives(this._pointPrimitives);
Expand Down
21 changes: 18 additions & 3 deletions Source/Shaders/BillboardCollectionFS.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,28 @@ void main()
#else
vec4 vertexColor = v_color;
#endif

vec4 color = texture2D(u_atlas, v_textureCoordinates) * vertexColor;
if (color.a == 0.0)

#ifdef RENDER_FOR_PICK
Copy link
Contributor

Choose a reason for hiding this comment

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

Can you add a comment here and to the point shader that explains this? For example: fully transparent parts are not pickable, and the billboard/point is rendered twice: the opaque pass discards translucent fragments, and the translucent pass discards opaque ones.

if (color.a < 0.005) // matches 0/255 and 1/255
{
discard;
}
#else
#ifdef OPAQUE
if (color.a < 0.995) // matches < 254/255
{
discard;
}

#else
if (color.a >= 0.995) // matches 254/255 and 255/255
{
discard;
}
#endif
#endif

#ifdef RENDER_FOR_PICK
gl_FragColor = v_pickColor;
#else
Expand Down
17 changes: 16 additions & 1 deletion Source/Shaders/PointPrimitiveCollectionFS.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,25 @@ void main()

vec4 color = mix(v_outlineColor, v_color, innerAlpha);
color.a *= wholeAlpha;
if (color.a < 0.005)

#ifdef RENDER_FOR_PICK
if (color.a < 0.005) // matches 0/255 and 1/255
{
discard;
}
#else
#ifdef OPAQUE
if (color.a < 0.995) // matches < 254/255
{
discard;
}
#else
if (color.a >= 0.995) // matches 254/255 and 255/255
{
discard;
}
#endif
#endif

#ifdef RENDER_FOR_PICK
gl_FragColor = v_pickColor;
Expand Down