import { Cartesian3 } from "../../Source/Cesium.js"; import { HeadingPitchRange } from "../../Source/Cesium.js"; import { HeadingPitchRoll } from "../../Source/Cesium.js"; import { Matrix4 } from "../../Source/Cesium.js"; import { Transforms } from "../../Source/Cesium.js"; import { Model } from "../../Source/Cesium.js"; import { PostProcessStageLibrary } from "../../Source/Cesium.js"; import createCanvas from "../createCanvas.js"; import createScene from "../createScene.js"; import pollToPromise from "../pollToPromise.js"; import ViewportPrimitive from "../ViewportPrimitive.js"; import { when } from "../../Source/Cesium.js"; describe( "Scene/PostProcessStageLibrary", function () { var scene; beforeAll(function () { scene = createScene({ canvas: createCanvas(3, 3), }); }); afterAll(function () { scene.destroyForSpecs(); }); afterEach(function () { scene.postProcessStages.removeAll(); scene.primitives.removeAll(); scene.postProcessStages.fxaa.enabled = false; scene.postProcessStages.bloom.enabled = false; scene.postProcessStages.ambientOcclusion.enabled = false; scene.renderForSpecs(); }); var model; function loadModel(url) { model = scene.primitives.add( Model.fromGltf({ modelMatrix: Transforms.eastNorthUpToFixedFrame( Cartesian3.fromDegrees(0.0, 0.0, 100.0) ), url: url, }) ); model.zoomTo = function () { var camera = scene.camera; var center = Matrix4.multiplyByPoint( model.modelMatrix, model.boundingSphere.center, new Cartesian3() ); var r = 4.0 * Math.max(model.boundingSphere.radius, camera.frustum.near); camera.lookAt(center, new HeadingPitchRange(0.0, 0.0, r)); }; return pollToPromise( function () { // Render scene to progressively load the model scene.renderForSpecs(); return model.ready; }, { timeout: 10000 } ) .then(function () { return model; }) .otherwise(function () { return when.reject(model); }); } it("black and white", function () { var fs = "void main() { \n" + " gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); \n" + "} \n"; scene.primitives.add(new ViewportPrimitive(fs)); expect(scene).toRenderAndCall(function (rgba) { for (var i = 0; i < 3; ++i) { for (var j = 0; j < 3; ++j) { var k = i * 4 * 3 + 4 * j; expect(rgba[k]).toEqual(255); expect(rgba[k + 1]).toEqual(0); expect(rgba[k + 2]).toEqual(0); expect(rgba[k + 3]).toEqual(255); } } }); scene.postProcessStages.add( PostProcessStageLibrary.createBlackAndWhiteStage() ); scene.renderForSpecs(); expect(scene).toRenderAndCall(function (rgba) { expect(rgba[0]).toBeGreaterThan(0); expect(rgba[1]).toEqual(rgba[0]); expect(rgba[2]).toEqual(rgba[0]); expect(rgba[3]).toEqual(255); for (var i = 0; i < 3; ++i) { for (var j = 0; j < 3; ++j) { var k = i * 4 * 3 + 4 * j; expect(rgba[k]).toEqual(rgba[0]); expect(rgba[k + 1]).toEqual(rgba[1]); expect(rgba[k + 2]).toEqual(rgba[2]); expect(rgba[k + 3]).toEqual(rgba[3]); } } }); }); it("per-feature black and white", function () { return loadModel("./Data/Models/Box/CesiumBoxTest.gltf").then( function () { model.zoomTo(); var stage = scene.postProcessStages.add( PostProcessStageLibrary.createBlackAndWhiteStage() ); stage.selected = []; return pollToPromise(function () { scene.renderForSpecs(); return stage.ready; }).then(function () { var color; expect(scene).toRenderAndCall(function (rgba) { color = rgba; expect(rgba[1]).toEqual(rgba[0]); expect(rgba[2]).toEqual(rgba[0]); expect(rgba[3]).toEqual(255); }); stage.selected = [model]; expect(scene).toRenderAndCall(function (rgba) { expect(rgba).not.toEqual(color); }); }); } ); }); it("brightness", function () { var fs = "void main() { \n" + " gl_FragColor = vec4(vec3(0.25), 1.0); \n" + "} \n"; scene.primitives.add(new ViewportPrimitive(fs)); var red; var green; var blue; expect(scene).toRenderAndCall(function (rgba) { for (var i = 0; i < 3; ++i) { for (var j = 0; j < 3; ++j) { var k = i * 4 * 3 + 4 * j; expect(rgba[k]).toEqualEpsilon(Math.floor(255 * 0.25), 1.0); expect(rgba[k + 1]).toEqual(rgba[k]); expect(rgba[k + 2]).toEqual(rgba[k]); expect(rgba[k + 3]).toEqual(255); } } red = rgba[0]; green = rgba[1]; blue = rgba[2]; }); scene.postProcessStages.add( PostProcessStageLibrary.createBrightnessStage() ); scene.renderForSpecs(); expect(scene).toRenderAndCall(function (rgba) { expect(rgba[0]).not.toEqual(red); expect(rgba[1]).not.toEqual(green); expect(rgba[2]).not.toEqual(blue); expect(rgba[3]).toEqual(255); for (var i = 0; i < 3; ++i) { for (var j = 0; j < 3; ++j) { var k = i * 4 * 3 + 4 * j; expect(rgba[k]).toEqual(rgba[0]); expect(rgba[k + 1]).toEqual(rgba[1]); expect(rgba[k + 2]).toEqual(rgba[2]); expect(rgba[k + 3]).toEqual(rgba[3]); } } }); }); it("night vision", function () { var fs = "void main() { \n" + " gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); \n" + "} \n"; scene.primitives.add(new ViewportPrimitive(fs)); expect(scene).toRenderAndCall(function (rgba) { for (var i = 0; i < 3; ++i) { for (var j = 0; j < 3; ++j) { var k = i * 4 * 3 + 4 * j; expect(rgba[k]).toEqual(255); expect(rgba[k + 1]).toEqual(0); expect(rgba[k + 2]).toEqual(0); expect(rgba[k + 3]).toEqual(255); } } }); scene.postProcessStages.add( PostProcessStageLibrary.createNightVisionStage() ); scene.renderForSpecs(); expect(scene).toRenderAndCall(function (rgba) { for (var i = 0; i < 3; ++i) { for (var j = 0; j < 3; ++j) { var k = i * 4 * 3 + 4 * j; expect(rgba[k]).toEqual(0); expect(rgba[k + 1]).toBeGreaterThan(0); expect(rgba[k + 2]).toEqual(0); expect(rgba[k + 3]).toEqual(255); } } }); }); it("depth view", function () { if (!scene.context.depthTexture) { return; } var fs = "void main() { \n" + " gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); \n" + "} \n"; scene.primitives.add(new ViewportPrimitive(fs)); expect(scene).toRenderAndCall(function (rgba) { for (var i = 0; i < 3; ++i) { for (var j = 0; j < 3; ++j) { var k = i * 4 * 3 + 4 * j; expect(rgba[k]).toEqual(255); expect(rgba[k + 1]).toEqual(0); expect(rgba[k + 2]).toEqual(0); expect(rgba[k + 3]).toEqual(255); } } }); scene.postProcessStages.add( PostProcessStageLibrary.createDepthViewStage() ); scene.renderForSpecs(); expect(scene).toRenderAndCall(function (rgba) { for (var i = 0; i < 3; ++i) { for (var j = 0; j < 3; ++j) { var k = i * 4 * 3 + 4 * j; expect(rgba[k]).toEqual(255); expect(rgba[k + 1]).toEqual(255); expect(rgba[k + 2]).toEqual(255); expect(rgba[k + 3]).toEqual(255); } } }); }); it("blur", function () { var fs = "void main() { \n" + " gl_FragColor = all(equal(floor(gl_FragCoord.xy), vec2(1.0, 1.0))) ? vec4(1.0, 0.0, 0.0, 1.0) : vec4(0.0, 0.0, 1.0, 1.0); \n" + "} \n"; scene.primitives.add(new ViewportPrimitive(fs)); expect(scene).toRenderAndCall(function (rgba) { for (var i = 0; i < 3; ++i) { for (var j = 0; j < 3; ++j) { if (i === 1 && j === 1) { continue; } var k = i * 4 * 3 + 4 * j; expect(rgba[k]).toEqual(0); expect(rgba[k + 1]).toEqual(0); expect(rgba[k + 2]).toEqual(255); expect(rgba[k + 3]).toEqual(255); } } expect(rgba[16]).toEqual(255); expect(rgba[17]).toEqual(0); expect(rgba[18]).toEqual(0); expect(rgba[19]).toEqual(255); }); scene.postProcessStages.add(PostProcessStageLibrary.createBlurStage()); scene.renderForSpecs(); expect(scene).toRenderAndCall(function (rgba) { expect(rgba[16]).toBeGreaterThan(0); expect(rgba[17]).toEqual(0); expect(rgba[18]).toBeGreaterThan(0); expect(rgba[19]).toEqual(255); }); }); it("blur uniforms", function () { var blur = PostProcessStageLibrary.createBlurStage(); expect(blur.uniforms.delta).toEqual(1.0); expect(blur.uniforms.sigma).toEqual(2.0); expect(blur.uniforms.stepSize).toEqual(1.0); blur.uniforms.delta = 2.0; blur.uniforms.sigma = 3.0; blur.uniforms.stepSize = 2.0; expect(blur.uniforms.delta).toEqual(2.0); expect(blur.uniforms.sigma).toEqual(3.0); expect(blur.uniforms.stepSize).toEqual(2.0); }); it("depth of field", function () { if (!scene.context.depthTexture) { return; } var origin = Cartesian3.fromDegrees(-123.0744619, 44.0503706, 100.0); var modelMatrix = Transforms.headingPitchRollToFixedFrame( origin, new HeadingPitchRoll() ); var model = scene.primitives.add( Model.fromGltf({ url: "./Data/Models/Box/CesiumBoxTest.gltf", modelMatrix: modelMatrix, scale: 40.0, }) ); var ready = false; model.readyPromise.then(function () { ready = true; }); var offset = new Cartesian3( -37.048378684557974, -24.852967044804245, 4.352023653686047 ); scene.camera.lookAt(origin, offset); return pollToPromise(function () { scene.render(); return ready; }).then(function () { expect(scene).toRenderAndCall(function (rgba) { for (var i = 0; i < rgba.length; i += 4) { expect(rgba[i]).toBeGreaterThan(0); expect(rgba[i + 1]).toEqual(0); expect(rgba[i + 2]).toEqual(0); expect(rgba[i + 3]).toEqual(255); } scene.postProcessStages.add( PostProcessStageLibrary.createDepthOfFieldStage() ); scene.renderForSpecs(); expect(scene).toRenderAndCall(function (rgba2) { for (var i = 0; i < rgba.length; i += 4) { expect(rgba2[i]).toBeGreaterThan(0); expect(rgba2[i + 1]).toEqual(0); expect(rgba2[i + 2]).toEqual(0); expect(rgba2[i + 3]).toEqual(255); expect(rgba2[i]).not.toEqual(rgba[i]); } }); }); }); }); it("depth of field uniforms", function () { var dof = PostProcessStageLibrary.createDepthOfFieldStage(); expect(dof.uniforms.focalDistance).toEqual(5.0); expect(dof.uniforms.delta).toEqual(1.0); expect(dof.uniforms.sigma).toEqual(2.0); expect(dof.uniforms.stepSize).toEqual(1.0); dof.uniforms.focalDistance = 6.0; dof.uniforms.delta = 2.0; dof.uniforms.sigma = 3.0; dof.uniforms.stepSize = 2.0; expect(dof.uniforms.focalDistance).toEqual(6.0); expect(dof.uniforms.delta).toEqual(2.0); expect(dof.uniforms.sigma).toEqual(3.0); expect(dof.uniforms.stepSize).toEqual(2.0); }); it("ambient occlusion", function () { if (!scene.context.depthTexture) { return; } scene.postProcessStages.ambientOcclusion.enabled = true; scene.postProcessStages.ambientOcclusion.uniforms.ambientOcclusionOnly = true; scene.renderForSpecs(); expect(scene).toRenderAndCall(function (rgba) { for (var i = 0; i < rgba.length; i += 4) { expect(rgba[i]).toEqual(255); expect(rgba[i + 1]).toEqual(255); expect(rgba[i + 2]).toEqual(255); expect(rgba[i + 3]).toEqual(255); } }); scene.postProcessStages.ambientOcclusion.enabled = false; }); it("ambient occlusion uniforms", function () { var ao = PostProcessStageLibrary.createAmbientOcclusionStage(); expect(ao.uniforms.ambientOcclusionOnly).toEqual(false); expect(ao.uniforms.intensity).toEqual(3.0); expect(ao.uniforms.bias).toEqual(0.1); expect(ao.uniforms.lengthCap).toEqual(0.26); expect(ao.uniforms.stepSize).toEqual(1.95); expect(ao.uniforms.frustumLength).toEqual(1000.0); expect(ao.uniforms.randomTexture).not.toBeDefined(); expect(ao.uniforms.delta).toEqual(1.0); expect(ao.uniforms.sigma).toEqual(2.0); expect(ao.uniforms.blurStepSize).toEqual(0.86); ao.uniforms.ambientOcclusionOnly = true; ao.uniforms.intensity = 4.0; ao.uniforms.bias = 0.2; ao.uniforms.lengthCap = 0.3; ao.uniforms.stepSize = 2.0; ao.uniforms.frustumLength = 1001.0; ao.uniforms.delta = 2.0; ao.uniforms.sigma = 3.0; ao.uniforms.blurStepSize = 2.0; expect(ao.uniforms.ambientOcclusionOnly).toEqual(true); expect(ao.uniforms.intensity).toEqual(4.0); expect(ao.uniforms.bias).toEqual(0.2); expect(ao.uniforms.lengthCap).toEqual(0.3); expect(ao.uniforms.stepSize).toEqual(2.0); expect(ao.uniforms.frustumLength).toEqual(1001.0); expect(ao.uniforms.delta).toEqual(2.0); expect(ao.uniforms.sigma).toEqual(3.0); expect(ao.uniforms.blurStepSize).toEqual(2.0); }); it("bloom", function () { var origin = Cartesian3.fromDegrees(-123.0744619, 44.0503706, 100.0); var modelMatrix = Transforms.headingPitchRollToFixedFrame( origin, new HeadingPitchRoll() ); var model = scene.primitives.add( Model.fromGltf({ url: "./Data/Models/Box/CesiumBoxTest.gltf", modelMatrix: modelMatrix, scale: 40.0, }) ); var ready = false; model.readyPromise.then(function () { ready = true; }); var offset = new Cartesian3( -37.048378684557974, -24.852967044804245, 4.352023653686047 ); scene.camera.lookAt(origin, offset); return pollToPromise(function () { scene.render(); return ready; }).then(function () { expect(scene).toRenderAndCall(function (rgba) { for (var i = 0; i < rgba.length; i += 4) { expect(rgba[i]).toBeGreaterThan(0); expect(rgba[i + 1]).toEqual(0); expect(rgba[i + 2]).toEqual(0); expect(rgba[i + 3]).toEqual(255); } scene.postProcessStages.bloom.enabled = true; scene.renderForSpecs(); expect(scene).toRenderAndCall(function (rgba2) { for (var i = 0; i < rgba.length; i += 4) { expect(rgba2[i]).toBeGreaterThan(0); expect(rgba2[i + 1]).toEqual(0); expect(rgba2[i + 2]).toEqual(0); expect(rgba2[i + 3]).toEqual(255); expect(rgba2[i]).not.toEqual(rgba[i]); } }); scene.postProcessStages.bloom.enabled = false; }); }); }); it("bloom uniforms", function () { var bloom = PostProcessStageLibrary.createBloomStage(); expect(bloom.uniforms.glowOnly).toEqual(false); expect(bloom.uniforms.contrast).toEqual(128.0); expect(bloom.uniforms.brightness).toEqual(-0.3); expect(bloom.uniforms.delta).toEqual(1.0); expect(bloom.uniforms.sigma).toEqual(2.0); expect(bloom.uniforms.stepSize).toEqual(1.0); bloom.uniforms.glowOnly = true; bloom.uniforms.contrast = 0.0; bloom.uniforms.brightness = 3.0; bloom.uniforms.delta = 2.0; bloom.uniforms.sigma = 3.0; bloom.uniforms.stepSize = 2.0; expect(bloom.uniforms.glowOnly).toEqual(true); expect(bloom.uniforms.contrast).toEqual(0.0); expect(bloom.uniforms.brightness).toEqual(3.0); expect(bloom.uniforms.delta).toEqual(2.0); expect(bloom.uniforms.sigma).toEqual(3.0); expect(bloom.uniforms.stepSize).toEqual(2.0); }); }, "WebGL" );