Skip to content

Commit

Permalink
Merge pull request #2261 from AnalyticalGraphicsInc/optimizeLandTiles
Browse files Browse the repository at this point in the history
`#define` out water effect code for tiles that are entirely land.
  • Loading branch information
kring committed Nov 7, 2014
2 parents aa1c76c + 4f80225 commit aa68e37
Show file tree
Hide file tree
Showing 5 changed files with 171 additions and 200 deletions.
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,
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

0 comments on commit aa68e37

Please sign in to comment.