Last active
September 6, 2020 02:46
-
-
Save regou/29398475a287071fa6f05f5a539ee678 to your computer and use it in GitHub Desktop.
Test WebGL in jest
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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}; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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