cesium
Version:
CesiumJS is a JavaScript library for creating 3D globes and 2D maps in a web browser without a plugin.
255 lines (214 loc) • 9.45 kB
JavaScript
import BoundingRectangle from '../Core/BoundingRectangle.js';
import Cartesian2 from '../Core/Cartesian2.js';
import Cartesian4 from '../Core/Cartesian4.js';
import defined from '../Core/defined.js';
import destroyObject from '../Core/destroyObject.js';
import CesiumMath from '../Core/Math.js';
import Matrix4 from '../Core/Matrix4.js';
import Transforms from '../Core/Transforms.js';
import AdditiveBlend from '../Shaders/PostProcessStages/AdditiveBlend.js';
import BrightPass from '../Shaders/PostProcessStages/BrightPass.js';
import GaussianBlur1D from '../Shaders/PostProcessStages/GaussianBlur1D.js';
import PassThrough from '../Shaders/PostProcessStages/PassThrough.js';
import PostProcessStage from './PostProcessStage.js';
import PostProcessStageComposite from './PostProcessStageComposite.js';
import PostProcessStageSampleMode from './PostProcessStageSampleMode.js';
import PostProcessStageTextureCache from './PostProcessStageTextureCache.js';
import SceneFramebuffer from './SceneFramebuffer.js';
function SunPostProcess() {
this._sceneFramebuffer = new SceneFramebuffer();
var scale = 0.125;
var stages = new Array(6);
stages[0] = new PostProcessStage({
fragmentShader : PassThrough,
textureScale : scale,
forcePowerOfTwo : true,
sampleMode : PostProcessStageSampleMode.LINEAR
});
var brightPass = stages[1] = new PostProcessStage({
fragmentShader : BrightPass,
uniforms : {
avgLuminance : 0.5, // A guess at the average luminance across the entire scene
threshold : 0.25,
offset : 0.1
},
textureScale : scale,
forcePowerOfTwo : true
});
var that = this;
this._delta = 1.0;
this._sigma = 2.0;
this._blurStep = new Cartesian2();
stages[2] = new PostProcessStage({
fragmentShader : GaussianBlur1D,
uniforms : {
step : function() {
that._blurStep.x = that._blurStep.y = 1.0 / brightPass.outputTexture.width;
return that._blurStep;
},
delta : function() {
return that._delta;
},
sigma : function() {
return that._sigma;
},
direction : 0.0
},
textureScale : scale,
forcePowerOfTwo : true
});
stages[3] = new PostProcessStage({
fragmentShader : GaussianBlur1D,
uniforms : {
step : function() {
that._blurStep.x = that._blurStep.y = 1.0 / brightPass.outputTexture.width;
return that._blurStep;
},
delta : function() {
return that._delta;
},
sigma : function() {
return that._sigma;
},
direction : 1.0
},
textureScale : scale,
forcePowerOfTwo : true
});
stages[4] = new PostProcessStage({
fragmentShader : PassThrough,
sampleMode : PostProcessStageSampleMode.LINEAR
});
this._uCenter = new Cartesian2();
this._uRadius = undefined;
stages[5] = new PostProcessStage({
fragmentShader : AdditiveBlend,
uniforms : {
center : function() {
return that._uCenter;
},
radius : function() {
return that._uRadius;
},
colorTexture2 : function() {
return that._sceneFramebuffer.getFramebuffer().getColorTexture(0);
}
}
});
this._stages = new PostProcessStageComposite({
stages : stages
});
var textureCache = new PostProcessStageTextureCache(this);
var length = stages.length;
for (var i = 0; i < length; ++i) {
stages[i]._textureCache = textureCache;
}
this._textureCache = textureCache;
this.length = stages.length;
}
SunPostProcess.prototype.get = function(index) {
return this._stages.get(index);
};
SunPostProcess.prototype.getStageByName = function(name) {
var length = this._stages.length;
for (var i = 0; i < length; ++i) {
var stage = this._stages.get(i);
if (stage.name === name) {
return stage;
}
}
return undefined;
};
var sunPositionECScratch = new Cartesian4();
var sunPositionWCScratch = new Cartesian2();
var sizeScratch = new Cartesian2();
var postProcessMatrix4Scratch= new Matrix4();
function updateSunPosition(postProcess, context, viewport) {
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;
postProcess._uCenter = Cartesian2.clone(sunPositionWC, postProcess._uCenter);
postProcess._uRadius = Math.max(size.x, size.y) * 0.15;
var width = context.drawingBufferWidth;
var height = context.drawingBufferHeight;
var stages = postProcess._stages;
var firstStage = stages.get(0);
var downSampleWidth = firstStage.outputTexture.width;
var downSampleHeight = firstStage.outputTexture.height;
var downSampleViewport = new BoundingRectangle();
downSampleViewport.width = downSampleWidth;
downSampleViewport.height = downSampleHeight;
// 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;
var scissorRectangle = firstStage.scissorRectangle;
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);
for (var i = 1; i < 4; ++i) {
BoundingRectangle.clone(scissorRectangle, stages.get(i).scissorRectangle);
}
}
SunPostProcess.prototype.clear = function(context, passState, clearColor) {
this._sceneFramebuffer.clear(context, passState, clearColor);
this._textureCache.clear(context);
};
SunPostProcess.prototype.update = function(passState) {
var context = passState.context;
var viewport = passState.viewport;
var sceneFramebuffer = this._sceneFramebuffer;
sceneFramebuffer.update(context, viewport);
var framebuffer = sceneFramebuffer.getFramebuffer();
this._textureCache.update(context);
this._stages.update(context, false);
updateSunPosition(this, context, viewport);
return framebuffer;
};
SunPostProcess.prototype.execute = function(context) {
var colorTexture = this._sceneFramebuffer.getFramebuffer().getColorTexture(0);
var stages = this._stages;
var length = stages.length;
stages.get(0).execute(context, colorTexture);
for (var i = 1; i < length; ++i) {
stages.get(i).execute(context, stages.get(i - 1).outputTexture);
}
};
SunPostProcess.prototype.copy = function(context, framebuffer) {
if (!defined(this._copyColorCommand)) {
var that = this;
this._copyColorCommand = context.createViewportQuadCommand(PassThrough, {
uniformMap : {
colorTexture : function() {
return that._stages.get(that._stages.length - 1).outputTexture;
}
},
owner : this
});
}
this._copyColorCommand.framebuffer = framebuffer;
this._copyColorCommand.execute(context);
};
SunPostProcess.prototype.isDestroyed = function() {
return false;
};
SunPostProcess.prototype.destroy = function() {
this._textureCache.destroy();
this._stages.destroy();
return destroyObject(this);
};
export default SunPostProcess;