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

#define out water effect code for tiles that are entirely land. #2261

Merged
merged 2 commits into from
Nov 7, 2014
Merged
Show file tree
Hide file tree
Changes from all 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
40 changes: 15 additions & 25 deletions Source/Scene/Globe.js
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,6 @@ define([
*/
this.oceanNormalMapUrl = buildModuleUrl('Assets/Textures/waterNormalsSmall.jpg');
this._oceanNormalMapUrl = undefined;
this._oceanNormalMapChanged = false;

/**
* True if primitives such as billboards, polylines, labels, etc. should be depth-tested
Expand Down Expand Up @@ -273,7 +272,6 @@ define([

this._oceanNormalMap = undefined;
this._zoomedOutOceanSpecularIntensity = 0.5;
this._hasWaterMask = false;
this._hasVertexNormals = false;
this._lightingFadeDistance = new Cartesian2(this.lightingFadeOutDistance, this.lightingFadeInDistance);

Expand Down Expand Up @@ -845,19 +843,22 @@ define([
var oceanNormalMapUrl = this.oceanNormalMapUrl;
this._oceanNormalMapUrl = oceanNormalMapUrl;

var that = this;
when(loadImage(oceanNormalMapUrl), function(image) {
if (oceanNormalMapUrl !== that.oceanNormalMapUrl) {
// url changed while we were loading
return;
}
if (defined(oceanNormalMapUrl)) {
var that = this;
when(loadImage(oceanNormalMapUrl), function(image) {
if (oceanNormalMapUrl !== that.oceanNormalMapUrl) {
// url changed while we were loading
return;
}

that._oceanNormalMap = that._oceanNormalMap && that._oceanNormalMap.destroy();
that._oceanNormalMap = context.createTexture2D({
source : image
that._oceanNormalMap = that._oceanNormalMap && that._oceanNormalMap.destroy();
that._oceanNormalMap = context.createTexture2D({
source : image
});
});
that._oceanNormalMapChanged = true;
});
} else {
this._oceanNormalMap = this._oceanNormalMap && this._oceanNormalMap.destroy();
}
}

// Initial compile or re-compile if uber-shader parameters changed
Expand All @@ -867,8 +868,6 @@ define([
if (!defined(northPoleCommand.shaderProgram) ||
!defined(southPoleCommand.shaderProgram) ||
modeChanged ||
this._oceanNormalMapChanged ||
this._hasWaterMask !== hasWaterMask ||
this._hasVertexNormals !== hasVertexNormals ||
this._enableLighting !== enableLighting) {

Expand Down Expand Up @@ -909,14 +908,6 @@ define([

var shaderDefines = [];

if (hasWaterMask) {
shaderDefines.push('SHOW_REFLECTIVE_OCEAN');

if (defined(this._oceanNormalMap)) {
shaderDefines.push('SHOW_OCEAN_WAVES');
}
}

if (enableLighting) {
if (hasVertexNormals) {
shaderDefines.push('ENABLE_VERTEX_LIGHTING');
Expand Down Expand Up @@ -951,10 +942,8 @@ define([
northPoleCommand.shaderProgram = poleShaderProgram;
southPoleCommand.shaderProgram = poleShaderProgram;

this._hasWaterMask = hasWaterMask;
this._hasVertexNormals = hasVertexNormals;
this._enableLighting = enableLighting;
this._oceanNormalMapChanged = false;
}

this._occluder.cameraPosition = frameState.camera.positionWC;
Expand Down Expand Up @@ -988,6 +977,7 @@ define([
tileProvider.lightingFadeOutDistance = this.lightingFadeOutDistance;
tileProvider.lightingFadeInDistance = this.lightingFadeInDistance;
tileProvider.zoomedOutOceanSpecularIntensity = this._zoomedOutOceanSpecularIntensity;
tileProvider.hasWaterMask = hasWaterMask;
tileProvider.oceanNormalMap = this._oceanNormalMap;

surface.update(context, frameState, commandList);
Expand Down
46 changes: 13 additions & 33 deletions Source/Scene/GlobeSurfaceShaderSet.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,44 +33,17 @@ define([
this._shaders = {};
};

function getShaderKey(textureCount, applyBrightness, applyContrast, applyHue, applySaturation, applyGamma, applyAlpha) {
var key = '';
key += textureCount;

if (applyBrightness) {
key += '_brightness';
}

if (applyContrast) {
key += '_contrast';
}

if (applyHue) {
key += '_hue';
}

if (applySaturation) {
key += '_saturation';
}

if (applyGamma) {
key += '_gamma';
}

if (applyAlpha) {
key += '_alpha';
}

return key;
function getShaderKey(textureCount, applyBrightness, applyContrast, applyHue, applySaturation, applyGamma, applyAlpha, showReflectiveOcean, showOceanWaves) {
return '' + textureCount + (+applyBrightness) + (+applyContrast) + (+applyHue) + (+applySaturation) + (+applyGamma) + (+applyAlpha) + (+showReflectiveOcean) + (+showOceanWaves);
}

GlobeSurfaceShaderSet.prototype.getShaderProgram = function(context, textureCount, applyBrightness, applyContrast, applyHue, applySaturation, applyGamma, applyAlpha) {
var key = getShaderKey(textureCount, applyBrightness, applyContrast, applyHue, applySaturation, applyGamma, applyAlpha);
GlobeSurfaceShaderSet.prototype.getShaderProgram = function(context, textureCount, applyBrightness, applyContrast, applyHue, applySaturation, applyGamma, applyAlpha, showReflectiveOcean, showOceanWaves) {
var key = getShaderKey(textureCount, applyBrightness, applyContrast, applyHue, applySaturation, applyGamma, applyAlpha, showReflectiveOcean, showOceanWaves);
var shader = this._shaders[key];
if (!defined(shader)) {
var vs = this.baseVertexShaderSource;

var vs = this.baseVertexShaderSource.clone();
var fs = this.baseFragmentShaderSource.clone();

fs.defines.push('TEXTURE_UNITS ' + textureCount);

if (applyBrightness) {
Expand All @@ -91,6 +64,13 @@ define([
if (applyAlpha) {
fs.defines.push('APPLY_ALPHA');
}
if (showReflectiveOcean) {
fs.defines.push('SHOW_REFLECTIVE_OCEAN');
vs.defines.push('SHOW_REFLECTIVE_OCEAN');
}
if (showOceanWaves) {
fs.defines.push('SHOW_OCEAN_WAVES');
}

var computeDayColor = '\
vec4 computeDayColor(vec4 initialColor, vec2 textureCoordinates)\n\
Expand Down
145 changes: 70 additions & 75 deletions Source/Scene/GlobeSurfaceTile.js
Original file line number Diff line number Diff line change
Expand Up @@ -448,20 +448,7 @@ define([

// If there's a water mask included in the terrain data, create a
// texture for it.
var waterMask = surfaceTile.terrainData.waterMask;
if (defined(waterMask)) {
if (defined(surfaceTile.waterMaskTexture)) {
--surfaceTile.waterMaskTexture.referenceCount;
if (surfaceTile.waterMaskTexture.referenceCount === 0) {
surfaceTile.waterMaskTexture.destroy();
}
}
surfaceTile.waterMaskTexture = createWaterMaskTexture(context, waterMask);
surfaceTile.waterMaskTranslationAndScale.x = 0.0;
surfaceTile.waterMaskTranslationAndScale.y = 0.0;
surfaceTile.waterMaskTranslationAndScale.z = 1.0;
surfaceTile.waterMaskTranslationAndScale.w = 1.0;
}
createWaterMaskTextureIfNeeded(context, surfaceTile);

propagateNewLoadedDataToChildren(tile);
}
Expand Down Expand Up @@ -622,7 +609,6 @@ define([
}

function isDataAvailable(tile, terrainProvider) {

if (defined(terrainProvider.getTileDataAvailable)) {
var tileDataAvailable = terrainProvider.getTileDataAvailable(tile.x, tile.y, tile.level);
if (defined(tileDataAvailable)) {
Expand All @@ -647,81 +633,90 @@ define([
return parent.data.terrainData.isChildAvailable(parent.x, parent.y, tile.x, tile.y);
}

function createWaterMaskTexture(context, waterMask) {
var result;

var waterMaskData = context.cache.tile_waterMaskData;
if (!defined(waterMaskData)) {
waterMaskData = context.cache.tile_waterMaskData = {
allWaterTexture : undefined,
allLandTexture : undefined,
sampler : undefined,
destroy : function() {
if (defined(this.allWaterTexture)) {
this.allWaterTexture.destroy();
}
if (defined(this.allLandTexture)) {
this.allLandTexture.destroy();
}
}
function getContextWaterMaskData(context) {
var data = context.cache.tile_waterMaskData;

if (!defined(data)) {
var allWaterTexture = context.createTexture2D({
pixelFormat : PixelFormat.LUMINANCE,
pixelDatatype : PixelDatatype.UNSIGNED_BYTE,
source : {
arrayBufferView : new Uint8Array([255]),
width : 1,
height : 1
}
});
allWaterTexture.referenceCount = 1;

var sampler = context.createSampler({
wrapS : TextureWrap.CLAMP_TO_EDGE,
wrapT : TextureWrap.CLAMP_TO_EDGE,
minificationFilter : TextureMinificationFilter.LINEAR,
Copy link
Contributor

Choose a reason for hiding this comment

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

I hope the driver would optimize for this 1x1 case, but I would still go with NEAREST here.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Actually, this sampler is only used for the non-1x1 tiles. The allWaterTexture doesn't specify a sampler.

Copy link
Contributor

Choose a reason for hiding this comment

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

Ah, OK.

magnificationFilter : TextureMagnificationFilter.LINEAR
});

data = {
allWaterTexture : allWaterTexture,
sampler : sampler,
destroy : function() {
this.allWaterTexture.destroy();
}
};

context.cache.tile_waterMaskData = data;
}

var waterMaskSize = Math.sqrt(waterMask.length);
if (waterMaskSize === 1 && (waterMask[0] === 0 || waterMask[0] === 255)) {
// Tile is entirely land or entirely water.
if (!defined(waterMaskData.allWaterTexture)) {
waterMaskData.allWaterTexture = context.createTexture2D({
pixelFormat : PixelFormat.LUMINANCE,
pixelDatatype : PixelDatatype.UNSIGNED_BYTE,
source : {
arrayBufferView : new Uint8Array([255]),
width : 1,
height : 1
}
});
waterMaskData.allWaterTexture.referenceCount = 1;

waterMaskData.allLandTexture = context.createTexture2D({
pixelFormat : PixelFormat.LUMINANCE,
pixelDatatype : PixelDatatype.UNSIGNED_BYTE,
source : {
arrayBufferView : new Uint8Array([0]),
width : 1,
height : 1
}
});
waterMaskData.allLandTexture.referenceCount = 1;
return data;
}

function createWaterMaskTextureIfNeeded(context, surfaceTile) {
var previousTexture = surfaceTile.waterMaskTexture;
if (defined(previousTexture)) {
--previousTexture.referenceCount;
if (previousTexture.referenceCount === 0) {
previousTexture.destroy();
}
surfaceTile.waterMaskTexture = undefined;
}

var waterMask = surfaceTile.terrainData.waterMask;
if (!defined(waterMask)) {
return;
}

var waterMaskData = getContextWaterMaskData(context);
var texture;

result = waterMask[0] === 0 ? waterMaskData.allLandTexture : waterMaskData.allWaterTexture;
var waterMaskLength = waterMask.length;
if (waterMaskLength === 1) {
// Length 1 means the tile is entirely land or entirely water.
// A value of 0 indicates entirely land, a value of 1 indicates entirely water.
if (waterMask[0] !== 0) {
texture = waterMaskData.allWaterTexture;
} else {
// Leave the texture undefined if the tile is entirely land.
return;
}
} else {
result = context.createTexture2D({
var textureSize = Math.sqrt(waterMaskLength);
texture = context.createTexture2D({
pixelFormat : PixelFormat.LUMINANCE,
pixelDatatype : PixelDatatype.UNSIGNED_BYTE,
source : {
width : waterMaskSize,
height : waterMaskSize,
width : textureSize,
height : textureSize,
arrayBufferView : waterMask
}
});

result.referenceCount = 0;

if (!defined(waterMaskData.sampler)) {
waterMaskData.sampler = context.createSampler({
wrapS : TextureWrap.CLAMP_TO_EDGE,
wrapT : TextureWrap.CLAMP_TO_EDGE,
minificationFilter : TextureMinificationFilter.LINEAR,
magnificationFilter : TextureMagnificationFilter.LINEAR
});
}

result.sampler = waterMaskData.sampler;
texture.referenceCount = 0;
texture.sampler = waterMaskData.sampler;
}

++result.referenceCount;
return result;
++texture.referenceCount;
surfaceTile.waterMaskTexture = texture;

Cartesian4.fromElements(0.0, 0.0, 1.0, 1.0, surfaceTile.waterMaskTranslationAndScale);
}

function upsampleWaterMask(tile) {
Expand Down
17 changes: 12 additions & 5 deletions Source/Scene/GlobeSurfaceTileProvider.js
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ define([

this.lightingFadeOutDistance = 6500000.0;
this.lightingFadeInDistance = 9000000.0;
this.hasWaterMask = false;
this.oceanNormalMap = undefined;
this.zoomedOutOceanSpecularIntensity = 0.5;

Expand Down Expand Up @@ -800,10 +801,16 @@ define([
var viewMatrix = frameState.camera.viewMatrix;

var maxTextures = context.maximumTextureImageUnits;
if (defined(tileProvider.oceanNormalMap)) {

var waterMaskTexture = surfaceTile.waterMaskTexture;
var showReflectiveOcean = tileProvider.hasWaterMask && defined(waterMaskTexture);
var oceanNormalMap = tileProvider.oceanNormalMap;
var showOceanWaves = showReflectiveOcean && defined(oceanNormalMap);

if (showReflectiveOcean) {
--maxTextures;
}
if (defined(surfaceTile.waterMaskTexture)) {
if (showOceanWaves) {
--maxTextures;
}

Expand Down Expand Up @@ -903,7 +910,7 @@ define([
command.debugShowBoundingVolume = (tile === tileProvider._debug.boundingSphereTile);

Cartesian4.clone(initialColor, uniformMap.initialColor);
uniformMap.oceanNormalMap = tileProvider.oceanNormalMap;
uniformMap.oceanNormalMap = oceanNormalMap;
uniformMap.lightingFadeDistance.x = tileProvider.lightingFadeOutDistance;
uniformMap.lightingFadeDistance.y = tileProvider.lightingFadeInDistance;
uniformMap.zoomedOutOceanSpecularIntensity = tileProvider.zoomedOutOceanSpecularIntensity;
Expand Down Expand Up @@ -976,10 +983,10 @@ define([
// trim texture array to the used length so we don't end up using old textures
// which might get destroyed eventually
uniformMap.dayTextures.length = numberOfDayTextures;
uniformMap.waterMask = surfaceTile.waterMaskTexture;
uniformMap.waterMask = waterMaskTexture;
Cartesian4.clone(surfaceTile.waterMaskTranslationAndScale, uniformMap.waterMaskTranslationAndScale);

command.shaderProgram = tileProvider._surfaceShaderSet.getShaderProgram(context, numberOfDayTextures, applyBrightness, applyContrast, applyHue, applySaturation, applyGamma, applyAlpha);
command.shaderProgram = tileProvider._surfaceShaderSet.getShaderProgram(context, numberOfDayTextures, applyBrightness, applyContrast, applyHue, applySaturation, applyGamma, applyAlpha, showReflectiveOcean, showOceanWaves);
command.renderState = renderState;
command.primitiveType = PrimitiveType.TRIANGLES;
command.vertexArray = surfaceTile.vertexArray;
Expand Down
Loading