Skip to content

Commit

Permalink
#define out water effect code for tiles that are entirely land.
Browse files Browse the repository at this point in the history
`SHOW_REFLECTIVE_OCEAN` and `SHOW_OCEAN_WAVES` have moved into the `GlobeSurfaceShaderSet` so they can vary on a per-tile basis, rather than being set identically for all tiles.  Tiles that are entirely land now use `undefined` for their water mask texture instead of a shared "land" texture.
  • Loading branch information
shunter committed Nov 6, 2014
1 parent 5778c9a commit 7acade9
Show file tree
Hide file tree
Showing 5 changed files with 157 additions and 183 deletions.
9 changes: 1 addition & 8 deletions Source/Scene/Globe.js
Original file line number Diff line number Diff line change
Expand Up @@ -909,14 +909,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 @@ -988,6 +980,7 @@ define([
tileProvider.lightingFadeOutDistance = this.lightingFadeOutDistance;
tileProvider.lightingFadeInDistance = this.lightingFadeInDistance;
tileProvider.zoomedOutOceanSpecularIntensity = this._zoomedOutOceanSpecularIntensity;
tileProvider.hasWaterMask = this._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 7acade9

Please sign in to comment.