Skip to content

Instantly share code, notes, and snippets.

@regou
Last active September 6, 2020 02:46
Show Gist options
  • Select an option

  • Save regou/29398475a287071fa6f05f5a539ee678 to your computer and use it in GitHub Desktop.

Select an option

Save regou/29398475a287071fa6f05f5a539ee678 to your computer and use it in GitHub Desktop.
Test WebGL in jest
const THREE = global.THREE = require('three');
const headlessGl = require("gl");
const pngStream = require('three-png-stream');
const fs = require('fs');
const path = require('path');
const looksSame = require('looks-same');
const width = 400;
const height = 300;
const VIEW_ANGLE = 45;
const NEAR = 0.1;
const FAR = 10000;
function init(camerax, cameray, cameraz) {
const camera = new THREE.PerspectiveCamera(VIEW_ANGLE, width / height, NEAR, FAR);
const scene = new THREE.Scene();
let gl = headlessGl(width, height, { preserveDrawingBuffer: true });
let canvas = document.createElement('canvas');
canvas.width = width;
canvas.height = height;
scene.add(camera);
camera.position.set(camerax || 0, cameray || 0, cameraz || 10);
camera.lookAt(scene.position);
const light = new THREE.HemisphereLight(0xe3c586, 0xcb3ac2, 1);
scene.add(light)
let target = new THREE.WebGLRenderTarget(
width, height, {
minFilter: THREE.LinearFilter,
magFilter: THREE.NearestFilter,
format: THREE.RGBAFormat
});
let renderer = new THREE.WebGLRenderer({
antialias: false,
canvas: canvas,
context:gl
});
// renderer.setClearColor(new THREE.Color( 0xff0000 ), 1);
return {renderer,canvas,camera,scene,target};
}
function genPng(renderer, target, name, isSpec) {
var output = fs.createWriteStream(getImagePath(name,isSpec ? 'spec':'cur'));
let s = pngStream(renderer, target)
.pipe(output)
return streamToPromise(s);
}
function streamToPromise(stream) {
return new Promise(function(resolve, reject) {
stream.on("finish", resolve);
stream.on("error", reject);
})
}
/**
* Get image path base on test name.
* @private
* @param {String} name The test case name.
* @param {String} type spec|cur|diff
* @returns {String} path
*/
function getImagePath(name,type) {
return `./__tests__/comparisons/${name}.${type}.png`;
}
function isSameImage(imageName) {
return new Promise(function (res,rej) {
try{
let specImage = getImagePath(imageName,'spec');
let curImage = getImagePath(imageName,'cur');
looksSame(specImage, curImage, {ignoreAntialiasing: true}, function(error, equal) {
if(error){rej(error)}
res(equal);
if(!equal){
console.error(`${imageName} is NOT same with spec image!
See ${imageName}.diff.png
`);
genDiffImage(imageName);
}
});
}catch (error){
rej(error);
}
});
}
function genDiffImage(imageName) {
looksSame.createDiff({
reference: getImagePath(imageName,'spec'),
current: getImagePath(imageName,'cur'),
diff: getImagePath(imageName,'diff'),
highlightColor: '#ff00ff', //color to highlight the differences
strict: false,//strict comparsion
tolerance: 2.5
}, function(error) {
});
}
module.exports = {init,genPng,getImagePath,isSameImage};
const THREE = global.THREE = require('three');
const headlessGl = require("gl");
const pngStream = require('three-png-stream');
const fs = require('fs');
const testUtils = require('./gl_utils');
describe('Raw', function () {
test('vertex ok',async function () {
var ls = testUtils.init(-1, 3, 3);
let geometry = new THREE.BoxGeometry( 3, 1, 2 )
let material = new THREE.ShaderMaterial()
let vec4 = new THREE.Vector4( 1.0, 0.0, 0.0, 1.0 );//red
material.vertexShader = `
void main() {
gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
}
`;
material.fragmentShader = `
uniform vec4 solidColor;
void main() {
gl_FragColor = solidColor;
}
`
material.uniforms = { solidColor: { type: "v4", value: vec4 } };
let cube = new THREE.Mesh(geometry, material)
cube.position.set(0,0,0);
ls.scene.add(cube)
ls.renderer.render(ls.scene, ls.camera, ls.target, true);
await testUtils.genPng(ls.renderer,ls.target,'vertex_ok');
let isSame = await testUtils.isSameImage('vertex_ok');
expect(isSame).toBe(true)
});
test('three ok',async function () {
const {renderer,canvas,camera,scene,target} = testUtils.init(-1, 3, 3);
var bodyGeometry = new THREE.BoxGeometry(1, 1, 1);
var bodyMaterial = new THREE.MeshLambertMaterial({color: 0x398cf1});
var body = new THREE.Mesh(bodyGeometry, bodyMaterial);
body.position.set(0,0,0);
scene.add(body);
renderer.render(scene, camera, target, true);
await testUtils.genPng(renderer,target,'three_ok');
let isSame = await testUtils.isSameImage('three_ok');
expect(isSame).toBe(true)
});
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment