cesium
Version:
CesiumJS is a JavaScript library for creating 3D globes and 2D maps in a web browser without a plugin.
405 lines (342 loc) • 16 kB
JavaScript
define([
'../Core/BoundingRectangle',
'../Core/Cartesian2',
'../Core/Cartesian4',
'../Core/Color',
'../Core/defaultValue',
'../Core/defined',
'../Core/destroyObject',
'../Core/Math',
'../Core/Matrix4',
'../Core/PixelFormat',
'../Core/Transforms',
'../Renderer/ClearCommand',
'../Renderer/Framebuffer',
'../Renderer/PassState',
'../Renderer/PixelDatatype',
'../Renderer/Renderbuffer',
'../Renderer/RenderbufferFormat',
'../Renderer/RenderState',
'../Renderer/Texture',
'../Shaders/PostProcessFilters/AdditiveBlend',
'../Shaders/PostProcessFilters/BrightPass',
'../Shaders/PostProcessFilters/GaussianBlur1D',
'../Shaders/PostProcessFilters/PassThrough'
], function(
BoundingRectangle,
Cartesian2,
Cartesian4,
Color,
defaultValue,
defined,
destroyObject,
CesiumMath,
Matrix4,
PixelFormat,
Transforms,
ClearCommand,
Framebuffer,
PassState,
PixelDatatype,
Renderbuffer,
RenderbufferFormat,
RenderState,
Texture,
AdditiveBlend,
BrightPass,
GaussianBlur1D,
PassThrough) {
'use strict';
function SunPostProcess() {
this._fbo = undefined;
this._downSampleFBO1 = undefined;
this._downSampleFBO2 = undefined;
this._clearFBO1Command = undefined;
this._clearFBO2Command = undefined;
this._downSampleCommand = undefined;
this._brightPassCommand = undefined;
this._blurXCommand = undefined;
this._blurYCommand = undefined;
this._blendCommand = undefined;
this._fullScreenCommand = undefined;
this._downSamplePassState = new PassState();
this._downSamplePassState.scissorTest = {
enable : true,
rectangle : new BoundingRectangle()
};
this._upSamplePassState = new PassState();
this._upSamplePassState.scissorTest = {
enabled : true,
rectangle : new BoundingRectangle()
};
this._uCenter = new Cartesian2();
this._uRadius = undefined;
this._blurStep = new Cartesian2();
}
SunPostProcess.prototype.clear = function(context, color) {
var clear = this._clearFBO1Command;
Color.clone(defaultValue(color, Color.BLACK), clear.color);
clear.execute(context);
clear = this._clearFBO2Command;
Color.clone(defaultValue(color, Color.BLACK), clear.color);
clear.execute(context);
};
SunPostProcess.prototype.execute = function(context, framebuffer) {
this._downSampleCommand.execute(context, this._downSamplePassState);
this._brightPassCommand.execute(context, this._downSamplePassState);
this._blurXCommand.execute(context, this._downSamplePassState);
this._blurYCommand.execute(context, this._downSamplePassState);
this._fullScreenCommand.framebuffer = framebuffer;
this._blendCommand.framebuffer = framebuffer;
this._fullScreenCommand.execute(context);
this._blendCommand.execute(context, this._upSamplePassState);
};
var viewportBoundingRectangle = new BoundingRectangle();
var downSampleViewportBoundingRectangle = new BoundingRectangle();
var sunPositionECScratch = new Cartesian4();
var sunPositionWCScratch = new Cartesian2();
var sizeScratch = new Cartesian2();
var postProcessMatrix4Scratch= new Matrix4();
SunPostProcess.prototype.update = function(passState) {
var context = passState.context;
var viewport = passState.viewport;
var width = context.drawingBufferWidth;
var height = context.drawingBufferHeight;
var that = this;
if (!defined(this._downSampleCommand)) {
this._clearFBO1Command = new ClearCommand({
color : new Color()
});
this._clearFBO2Command = new ClearCommand({
color : new Color()
});
var uniformMap = {};
this._downSampleCommand = context.createViewportQuadCommand(PassThrough, {
uniformMap : uniformMap,
owner : this
});
uniformMap = {
u_avgLuminance : function() {
// A guess at the average luminance across the entire scene
return 0.5;
},
u_threshold : function() {
return 0.25;
},
u_offset : function() {
return 0.1;
}
};
this._brightPassCommand = context.createViewportQuadCommand(BrightPass, {
uniformMap : uniformMap,
owner : this
});
var delta = 1.0;
var sigma = 2.0;
uniformMap = {
delta : function() {
return delta;
},
sigma : function() {
return sigma;
},
direction : function() {
return 0.0;
}
};
this._blurXCommand = context.createViewportQuadCommand(GaussianBlur1D, {
uniformMap : uniformMap,
owner : this
});
uniformMap = {
delta : function() {
return delta;
},
sigma : function() {
return sigma;
},
direction : function() {
return 1.0;
}
};
this._blurYCommand = context.createViewportQuadCommand(GaussianBlur1D, {
uniformMap : uniformMap,
owner : this
});
uniformMap = {
u_center : function() {
return that._uCenter;
},
u_radius : function() {
return that._uRadius;
}
};
this._blendCommand = context.createViewportQuadCommand(AdditiveBlend, {
uniformMap : uniformMap,
owner : this
});
uniformMap = {};
this._fullScreenCommand = context.createViewportQuadCommand(PassThrough, {
uniformMap : uniformMap,
owner : this
});
}
var downSampleWidth = Math.pow(2.0, Math.ceil(Math.log(width) / Math.log(2)) - 2.0);
var downSampleHeight = Math.pow(2.0, Math.ceil(Math.log(height) / Math.log(2)) - 2.0);
// The size computed above can be less than 1.0 if size < 4.0. This will probably
// never happen in practice, but does in the tests. Clamp to 1.0 to prevent WebGL
// errors in the tests.
var downSampleSize = Math.max(1.0, downSampleWidth, downSampleHeight);
var downSampleViewport = downSampleViewportBoundingRectangle;
downSampleViewport.width = downSampleSize;
downSampleViewport.height = downSampleSize;
var fbo = this._fbo;
var colorTexture = (defined(fbo) && fbo.getColorTexture(0)) || undefined;
if (!defined(colorTexture) || colorTexture.width !== width || colorTexture.height !== height) {
fbo = fbo && fbo.destroy();
this._downSampleFBO1 = this._downSampleFBO1 && this._downSampleFBO1.destroy();
this._downSampleFBO2 = this._downSampleFBO2 && this._downSampleFBO2.destroy();
this._blurStep.x = this._blurStep.y = 1.0 / downSampleSize;
var colorTextures = [new Texture({
context : context,
width : width,
height : height
})];
if (context.depthTexture) {
fbo = this._fbo = new Framebuffer({
context : context,
colorTextures :colorTextures,
depthTexture : new Texture({
context : context,
width : width,
height : height,
pixelFormat : PixelFormat.DEPTH_COMPONENT,
pixelDatatype : PixelDatatype.UNSIGNED_SHORT
})
});
} else {
fbo = this._fbo = new Framebuffer({
context : context,
colorTextures : colorTextures,
depthRenderbuffer : new Renderbuffer({
context : context,
format : RenderbufferFormat.DEPTH_COMPONENT16
})
});
}
this._downSampleFBO1 = new Framebuffer({
context : context,
colorTextures : [new Texture({
context : context,
width : downSampleSize,
height : downSampleSize
})]
});
this._downSampleFBO2 = new Framebuffer({
context : context,
colorTextures : [new Texture({
context : context,
width : downSampleSize,
height : downSampleSize
})]
});
this._clearFBO1Command.framebuffer = this._downSampleFBO1;
this._clearFBO2Command.framebuffer = this._downSampleFBO2;
this._downSampleCommand.framebuffer = this._downSampleFBO1;
this._brightPassCommand.framebuffer = this._downSampleFBO2;
this._blurXCommand.framebuffer = this._downSampleFBO1;
this._blurYCommand.framebuffer = this._downSampleFBO2;
var downSampleRenderState = RenderState.fromCache({
viewport : downSampleViewport
});
this._downSampleCommand.uniformMap.u_texture = function() {
return fbo.getColorTexture(0);
};
this._downSampleCommand.renderState = downSampleRenderState;
this._brightPassCommand.uniformMap.u_texture = function() {
return that._downSampleFBO1.getColorTexture(0);
};
this._brightPassCommand.renderState = downSampleRenderState;
this._blurXCommand.uniformMap.u_texture = function() {
return that._downSampleFBO2.getColorTexture(0);
};
this._blurXCommand.uniformMap.u_step = function() {
return that._blurStep;
};
this._blurXCommand.renderState = downSampleRenderState;
this._blurYCommand.uniformMap.u_texture = function() {
return that._downSampleFBO1.getColorTexture(0);
};
this._blurYCommand.uniformMap.u_step = function() {
return that._blurStep;
};
this._blurYCommand.renderState = downSampleRenderState;
var upSampledViewport = viewportBoundingRectangle;
upSampledViewport.width = width;
upSampledViewport.height = height;
var upSampleRenderState = RenderState.fromCache({ viewport : upSampledViewport });
this._blendCommand.uniformMap.u_texture0 = function() {
return fbo.getColorTexture(0);
};
this._blendCommand.uniformMap.u_texture1 = function() {
return that._downSampleFBO2.getColorTexture(0);
};
this._blendCommand.renderState = upSampleRenderState;
this._fullScreenCommand.uniformMap.u_texture = function() {
return fbo.getColorTexture(0);
};
this._fullScreenCommand.renderState = upSampleRenderState;
}
var us = context.uniformState;
var sunPosition = us.sunPositionWC;
var viewMatrix = us.view;
var viewProjectionMatrix = us.viewProjection;
var projectionMatrix = us.projection;
// create up sampled render state
var viewportTransformation = Matrix4.computeViewportTransformation(viewport, 0.0, 1.0, postProcessMatrix4Scratch);
var sunPositionEC = Matrix4.multiplyByPoint(viewMatrix, sunPosition, sunPositionECScratch);
var sunPositionWC = Transforms.pointToGLWindowCoordinates(viewProjectionMatrix, viewportTransformation, sunPosition, sunPositionWCScratch);
sunPositionEC.x += CesiumMath.SOLAR_RADIUS;
var limbWC = Transforms.pointToGLWindowCoordinates(projectionMatrix, viewportTransformation, sunPositionEC, sunPositionEC);
var sunSize = Cartesian2.magnitude(Cartesian2.subtract(limbWC, sunPositionWC, limbWC)) * 30.0 * 2.0;
var size = sizeScratch;
size.x = sunSize;
size.y = sunSize;
var scissorRectangle = this._upSamplePassState.scissorTest.rectangle;
scissorRectangle.x = Math.max(sunPositionWC.x - size.x * 0.5, 0.0);
scissorRectangle.y = Math.max(sunPositionWC.y - size.y * 0.5, 0.0);
scissorRectangle.width = Math.min(size.x, width);
scissorRectangle.height = Math.min(size.y, height);
this._uCenter = Cartesian2.clone(sunPositionWC, this._uCenter);
this._uRadius = Math.max(size.x, size.y) * 0.15;
// create down sampled render state
viewportTransformation = Matrix4.computeViewportTransformation(downSampleViewport, 0.0, 1.0, postProcessMatrix4Scratch);
sunPositionWC = Transforms.pointToGLWindowCoordinates(viewProjectionMatrix, viewportTransformation, sunPosition, sunPositionWCScratch);
size.x *= downSampleWidth / width;
size.y *= downSampleHeight / height;
scissorRectangle = this._downSamplePassState.scissorTest.rectangle;
scissorRectangle.x = Math.max(sunPositionWC.x - size.x * 0.5, 0.0);
scissorRectangle.y = Math.max(sunPositionWC.y - size.y * 0.5, 0.0);
scissorRectangle.width = Math.min(size.x, width);
scissorRectangle.height = Math.min(size.y, height);
this._downSamplePassState.context = context;
this._upSamplePassState.context = context;
return this._fbo;
};
SunPostProcess.prototype.isDestroyed = function() {
return false;
};
SunPostProcess.prototype.destroy = function() {
this._fbo = this._fbo && this._fbo.destroy();
this._downSampleFBO1 = this._downSampleFBO1 && this._downSampleFBO1.destroy();
this._downSampleFBO2 = this._downSampleFBO2 && this._downSampleFBO2.destroy();
this._downSampleCommand = this._downSampleCommand && this._downSampleCommand.shaderProgram && this._downSampleCommand.shaderProgram.destroy();
this._brightPassCommand = this._brightPassCommand && this._brightPassCommand.shaderProgram && this._brightPassCommand.shaderProgram.destroy();
this._blurXCommand = this._blurXCommand && this._blurXCommand.shaderProgram && this._blurXCommand.shaderProgram.destroy();
this._blurYCommand = this._blurYCommand && this._blurYCommand.shaderProgram && this._blurYCommand.shaderProgram.destroy();
this._blendCommand = this._blendCommand && this._blendCommand.shaderProgram && this._blendCommand.shaderProgram.destroy();
this._fullScreenCommand = this._fullScreenCommand && this._fullScreenCommand.shaderProgram && this._fullScreenCommand.shaderProgram.destroy();
return destroyObject(this);
};
return SunPostProcess;
});