You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

322 lines
10 KiB
JavaScript

import { BoundingRectangle } from "../../Source/Cesium.js";
import { Cartesian3 } from "../../Source/Cesium.js";
import { Color } from "../../Source/Cesium.js";
import { defined } from "../../Source/Cesium.js";
import { HeadingPitchRange } from "../../Source/Cesium.js";
import { Matrix4 } from "../../Source/Cesium.js";
import { PixelFormat } from "../../Source/Cesium.js";
import { Transforms } from "../../Source/Cesium.js";
import { PixelDatatype } from "../../Source/Cesium.js";
import { Model } from "../../Source/Cesium.js";
import { PostProcessStage } from "../../Source/Cesium.js";
import { PostProcessStageSampleMode } from "../../Source/Cesium.js";
import createScene from "../createScene.js";
import pollToPromise from "../pollToPromise.js";
import { when } from "../../Source/Cesium.js";
describe(
"Scene/PostProcessStage",
function () {
var scene;
beforeAll(function () {
scene = createScene();
scene.postProcessStages.fxaa.enabled = false;
});
afterAll(function () {
scene.destroyForSpecs();
});
afterEach(function () {
scene.postProcessStages.removeAll();
scene.primitives.removeAll();
});
it("constructs", function () {
var fragmentShader =
"uniform vec4 color; void main() { gl_FragColor = color; }";
var uniforms = { color: Color.clone(Color.RED) };
var textureScale = 0.5;
var forcePowerOfTwo = true;
var sampleMode = PostProcessStageSampleMode.LINEAR;
var pixelFormat = PixelFormat.RGB;
var pixelDatatype = PixelDatatype.UNSIGNED_INT;
var clearColor = Color.clone(Color.BLUE);
var scissorRectangle = new BoundingRectangle(0, 0, 5, 5);
var name = "wonka vision";
var stage = new PostProcessStage({
fragmentShader: fragmentShader,
uniforms: uniforms,
textureScale: textureScale,
forcePowerOfTwo: forcePowerOfTwo,
sampleMode: sampleMode,
pixelFormat: pixelFormat,
pixelDatatype: pixelDatatype,
clearColor: clearColor,
scissorRectangle: scissorRectangle,
name: name,
});
expect(stage.fragmentShader).toEqual(fragmentShader);
expect(stage.uniforms.color).toBeDefined();
expect(stage.textureScale).toEqual(textureScale);
expect(stage.forcePowerOfTwo).toEqual(forcePowerOfTwo);
expect(stage.sampleMode).toEqual(sampleMode);
expect(stage.pixelFormat).toEqual(stage.pixelFormat);
expect(stage.pixelDatatype).toEqual(pixelDatatype);
expect(stage.clearColor).toEqual(clearColor);
expect(stage.scissorRectangle).toEqual(scissorRectangle);
expect(stage.name).toEqual(name);
expect(stage.outputTexture).not.toBeDefined();
});
it("default constructs", function () {
var fragmentShader = "void main() { gl_FragColor = vec4(1.0); }";
var stage = new PostProcessStage({
fragmentShader: fragmentShader,
});
expect(stage.fragmentShader).toEqual(fragmentShader);
expect(stage.uniforms).not.toBeDefined();
expect(stage.textureScale).toEqual(1.0);
expect(stage.forcePowerOfTwo).toEqual(false);
expect(stage.sampleMode).toEqual(PostProcessStageSampleMode.NEAREST);
expect(stage.pixelFormat).toEqual(PixelFormat.RGBA);
expect(stage.pixelDatatype).toEqual(PixelDatatype.UNSIGNED_BYTE);
expect(stage.clearColor).toEqual(Color.BLACK);
expect(stage.scissorRectangle).toEqual(new BoundingRectangle());
expect(stage.name).toBeDefined();
expect(stage.outputTexture).not.toBeDefined();
});
it("throws without fragment shader", function () {
expect(function () {
return new PostProcessStage();
}).toThrowDeveloperError();
});
it("throws with invalid texture scale", function () {
var fs = "void main() { gl_FragColor = vec4(1.0); }";
expect(function () {
return new PostProcessStage({
fragmentShader: fs,
textureScale: -1.0,
});
}).toThrowDeveloperError();
expect(function () {
return new PostProcessStage({
fragmentShader: fs,
textureScale: 2.0,
});
}).toThrowDeveloperError();
});
it("throws if pixel format is not a color format", function () {
expect(function () {
return new PostProcessStage({
fragmentShader: "void main() { gl_FragColor = vec4(1.0); }",
pixelFormat: PixelFormat.DEPTH_STENCIL,
});
}).toThrowDeveloperError();
});
it("executes", function () {
expect(scene).toRender([0, 0, 0, 255]);
scene.postProcessStages.add(
new PostProcessStage({
fragmentShader:
"void main() { gl_FragColor = vec4(1.0, 1.0, 0.0, 1.0); }",
})
);
scene.renderForSpecs(); // render one frame so the stage is ready
expect(scene).toRender([255, 255, 0, 255]);
});
it("can use a texture uniform", function () {
expect(scene).toRender([0, 0, 0, 255]);
var stage = scene.postProcessStages.add(
new PostProcessStage({
fragmentShader:
"uniform sampler2D texture; varying vec2 v_textureCoordinates; void main() { gl_FragColor = texture2D(texture, v_textureCoordinates); }",
uniforms: {
texture: "./Data/Images/Green2x2.png",
},
})
);
return pollToPromise(function () {
scene.renderForSpecs();
return stage.ready;
}).then(function () {
expect(scene).toRender([0, 255, 0, 255]);
stage.uniforms.texture = "./Data/Images/Blue2x2.png";
return pollToPromise(function () {
scene.renderForSpecs();
return stage.ready;
}).then(function () {
expect(scene).toRender([0, 0, 255, 255]);
});
});
});
it("can use a image uniform", function () {
var ready = false;
var image = new Image();
image.src = "./Data/Images/Blue2x2.png";
image.onload = function () {
ready = true;
};
return pollToPromise(function () {
return ready;
}).then(function () {
expect(scene).toRender([0, 0, 0, 255]);
var stage = scene.postProcessStages.add(
new PostProcessStage({
fragmentShader:
"uniform sampler2D texture; void main() { gl_FragColor = texture2D(texture, vec2(0.5)); }",
uniforms: {
texture: image,
},
})
);
return pollToPromise(function () {
scene.renderForSpecs();
return stage.ready;
}).then(function () {
expect(scene).toRender([0, 0, 255, 255]);
});
});
});
it("does not run a stage that requires depth textures when depth textures are not supported", function () {
var s = createScene();
s.context._depthTexture = false;
if (defined(s._view.globeDepth)) {
s._view.globeDepth.destroy();
s._view.globeDepth = undefined;
if (defined(s._view.oit)) {
s._view.oit.destroy();
s._view.oit = undefined;
}
}
expect(s).toRender([0, 0, 0, 255]);
// Dummy Stage
var bgColor = 51; // Choose a factor of 255 to make sure there aren't rounding issues
s.postProcessStages.add(
new PostProcessStage({
fragmentShader:
"void main() { gl_FragColor = vec4(vec3(" +
bgColor / 255 +
"), 1.0); }",
})
);
var stage = s.postProcessStages.add(
new PostProcessStage({
fragmentShader:
"uniform sampler2D depthTexture; void main() { gl_FragColor = vec4(1.0); }",
})
);
return pollToPromise(function () {
s.renderForSpecs();
return stage.ready;
})
.then(function () {
expect(s).toRender([bgColor, bgColor, bgColor, 255]);
})
.always(function (e) {
s.destroyForSpecs();
if (e) {
return when.reject(e);
}
});
});
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("per-feature post process stage", function () {
return loadModel("./Data/Models/Box/CesiumBoxTest.gltf").then(
function () {
model.zoomTo();
var fs =
"uniform sampler2D colorTexture; \n" +
"varying vec2 v_textureCoordinates; \n" +
"void main() { \n" +
" if (czm_selected(v_textureCoordinates)) { \n" +
" gl_FragColor = texture2D(colorTexture, v_textureCoordinates); \n" +
" } else { \n" +
" gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); \n" +
" } \n" +
"} \n";
var stage = scene.postProcessStages.add(
new PostProcessStage({
fragmentShader: fs,
})
);
stage.selected = [];
return pollToPromise(function () {
scene.renderForSpecs();
return stage.ready;
}).then(function () {
expect(scene).toRender([255, 0, 0, 255]);
stage.selected = [model];
expect(scene).toRenderAndCall(function (rgba) {
expect(rgba).not.toEqual([255, 0, 0, 255]);
});
});
}
);
});
it("destroys", function () {
var stage = new PostProcessStage({
fragmentShader: "void main() { gl_FragColor = vec4(1.0); }",
});
expect(stage.isDestroyed()).toEqual(false);
stage.destroy();
expect(stage.isDestroyed()).toEqual(true);
});
},
"WebGL"
);