glTF Snapshot Tests (#913)

This commit is contained in:
Georgios Karnas 2019-02-23 11:11:04 -08:00 committed by GitHub
parent f4b50f877b
commit 050f58f2be
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 126 additions and 41 deletions

View File

@ -3,7 +3,7 @@ import {AnimationLoop, setParameters, clear, GLTFInstantiator, log} from 'luma.g
import {Matrix4, radians} from 'math.gl';
import document from 'global/document';
const GLTF_BASE_URL = "https://raw.githubusercontent.com/KhronosGroup/glTF-Sample-Models/master/2.0/";
export const GLTF_BASE_URL = "https://raw.githubusercontent.com/KhronosGroup/glTF-Sample-Models/master/2.0/";
const INFO_HTML = `
<p><b>glTF</b> rendering.</p>
@ -75,14 +75,19 @@ const INFO_HTML = `
</div>
`;
function loadGLTF(urlOrPromise, gl) {
const DEFAULT_OPTIONS = {
pbrDebug: true,
pbrIbl: true
};
function loadGLTF(urlOrPromise, gl, options = DEFAULT_OPTIONS) {
const promise = urlOrPromise instanceof Promise ? urlOrPromise : window.fetch(urlOrPromise).then(res => res.arrayBuffer());
return promise.then(data => {
const gltfParser = new GLTFParser();
const gltf = gltfParser.parse(data);
const instantiator = new GLTFInstantiator(gl, {pbrDebug: true});
const instantiator = new GLTFInstantiator(gl, options);
const scenes = instantiator.instantiate(gltf);
log.info(4, "gltfParser: ", gltfParser)();
@ -96,11 +101,11 @@ function loadGLTF(urlOrPromise, gl) {
});
}
class DemoApp {
constructor() {
export class DemoApp {
constructor({modelFile = null, initialZoom = 2} = {}) {
this.scenes = [];
this.gl = null;
this.loadedModelUrl = null;
this.modelFile = modelFile;
this.glOptions = {
// Use to test gltf with webgl 1.0 and 2.0
@ -112,7 +117,7 @@ class DemoApp {
lastY: 0
};
this.translate = 2;
this.translate = initialZoom;
this.rotation = [0, 0];
this.rotationStart = [0, 0];
@ -177,19 +182,30 @@ class DemoApp {
});
this.gl = gl;
const modelSelector = document.getElementById("modelSelector");
loadGLTF(GLTF_BASE_URL + modelSelector.value, this.gl).then(scenes => (this.scenes = scenes));
modelSelector.onchange = event => {
if (this.modelFile) {
// options for unit testing
const options = {
pbrDebug: false,
pbrIbl: false
};
loadGLTF(this.modelFile, this.gl, options).then(scenes => (this.scenes = scenes));
} else {
const modelSelector = document.getElementById("modelSelector");
loadGLTF(GLTF_BASE_URL + modelSelector.value, this.gl).then(scenes => (this.scenes = scenes));
};
modelSelector.onchange = event => {
loadGLTF(GLTF_BASE_URL + modelSelector.value, this.gl).then(scenes => (this.scenes = scenes));
};
}
const showSelector = document.getElementById("showSelector");
showSelector.onchange = event => {
const value = showSelector.value.split(" ").map(x => parseFloat(x));
this.u_ScaleDiffBaseMR = value.slice(0, 4);
this.u_ScaleFGDSpec = value.slice(4);
};
if (showSelector) {
showSelector.onchange = event => {
const value = showSelector.value.split(" ").map(x => parseFloat(x));
this.u_ScaleDiffBaseMR = value.slice(0, 4);
this.u_ScaleFGDSpec = value.slice(4);
};
}
this.initalizeEventHandling(canvas);
}
@ -212,12 +228,14 @@ class DemoApp {
const uProjection = new Matrix4().perspective({fov: radians(40), aspect, near: 0.1, far: 9000});
if (!this.scenes.length) return;
if (!this.scenes.length) return false;
let success = true;
this.scenes[0].traverse((model, {worldMatrix}) => {
// In glTF, meshes and primitives do no have their own matrix.
const u_MVPMatrix = new Matrix4(uProjection).multiplyRight(uView).multiplyRight(worldMatrix);
model.draw({
success = success && model.draw({
uniforms: {
u_Camera: cameraPos,
u_MVPMatrix,
@ -229,6 +247,8 @@ class DemoApp {
}
});
});
return success;
}
}

View File

@ -18,7 +18,8 @@ const ATTRIBUTE_TYPE_TO_COMPONENTS = {
const DEFAULT_OPTIONS = {
modelOptions: {},
pbrDebug: false
pbrDebug: false,
pbrIbl: null
};
// GLTF instantiator for luma.gl
@ -113,7 +114,8 @@ export default class GLTFInstantiator {
attributes: this.createAttributes(gltfPrimitive.attributes, gltfPrimitive.indices),
material: gltfPrimitive.material,
modelOptions: this.options.modelOptions,
debug: this.options.pbrDebug
debug: this.options.pbrDebug,
ibl: this.options.pbrIbl
});
return model;

View File

@ -137,12 +137,10 @@ class GLTFEnv {
}
class GLTFMaterialParser {
constructor(gl, {attributes, material, debug}) {
constructor(gl, {attributes, material, debug, ibl}) {
this.gl = gl;
this.env = new GLTFEnv(gl);
this.defines = {
USE_IBL: 1,
USE_TEX_LOD: 1,
// TODO: Use EXT_sRGB if available (Standard in WebGL 2.0)
@ -157,14 +155,16 @@ class GLTFMaterialParser {
u_LightDirection: [0.0, 0.5, 0.5],
u_LightColor: [1.0, 1.0, 1.0],
u_MetallicRoughnessValues: [1, 1], // Default is 1 and 1
u_MetallicRoughnessValues: [1, 1] // Default is 1 and 1
};
// IBL
if (ibl) {
this.env = new GLTFEnv(gl);
// u_DiffuseEnvSampler: this.env.getDiffuseEnvSampler(),
// u_SpecularEnvSampler: this.env.getSpecularEnvSampler(),
u_brdfLUT: this.env.getBrdfTex(),
u_ScaleIBLAmbient: [1, 1]
};
this.uniforms.u_brdfLUT = this.env.getBrdfTex();
this.uniforms.u_ScaleIBLAmbient = [1, 1];
}
if (debug) {
// Override final color for reference app visualization
@ -177,6 +177,7 @@ class GLTFMaterialParser {
this.defineIfPresent(attributes.TANGENT, 'HAS_TANGENTS');
this.defineIfPresent(attributes.TEXCOORD_0, 'HAS_UV');
this.defineIfPresent(ibl, 'USE_IBL');
this.defineIfPresent(debug, 'PBR_DEBUG');
if (material) {
@ -264,9 +265,9 @@ function addVersionToShader(gl, source) {
export function createGLTFModel(
gl,
{id, drawMode, vertexCount, attributes, material, modelOptions, debug = false}
{id, drawMode, vertexCount, attributes, material, modelOptions, debug, ibl}
) {
const materialParser = new GLTFMaterialParser(gl, {attributes, material, debug});
const materialParser = new GLTFMaterialParser(gl, {attributes, material, debug, ibl});
log.info(4, 'createGLTFModel defines: ', materialParser.defines)();
@ -289,17 +290,19 @@ export function createGLTFModel(
model.setProps({attributes});
model.setUniforms(materialParser.uniforms);
materialParser.env.getDiffuseEnvSampler().then(cubeTex => {
model.setUniforms({
u_DiffuseEnvSampler: cubeTex
if (ibl) {
materialParser.env.getDiffuseEnvSampler().then(cubeTex => {
model.setUniforms({
u_DiffuseEnvSampler: cubeTex
});
});
});
materialParser.env.getSpecularEnvSampler().then(cubeTex => {
model.setUniforms({
u_SpecularEnvSampler: cubeTex
materialParser.env.getSpecularEnvSampler().then(cubeTex => {
model.setUniforms({
u_SpecularEnvSampler: cubeTex
});
});
});
}
return model;
}

View File

@ -56,13 +56,14 @@
"@babel/plugin-transform-runtime": "^7.0.0",
"@babel/preset-env": "^7.0.0",
"@babel/register": "^7.0.0",
"@loaders.gl/gltf": "^0.6.2",
"@probe.gl/test-utils": "^3.0.0-alpha.4",
"babel-eslint": "^9.0.0",
"babel-loader": "^8.0.0",
"babel-plugin-istanbul": "^5.0.0",
"babel-plugin-version-inline": "^1.0.0",
"babel-plugin-inline-webgl-constants": "^1.0.0",
"babel-plugin-istanbul": "^5.0.0",
"babel-plugin-remove-glsl-comments": "^1.0.0",
"babel-plugin-version-inline": "^1.0.0",
"codecov": "^3.1.0",
"coveralls": "^2.13.0",
"eslint": "4.13.1",

View File

@ -0,0 +1,38 @@
import {AnimationLoop} from '@luma.gl/core';
import {DemoApp, GLTF_BASE_URL} from '../../examples/gltf/app';
const examples = {
damagedHelmet: {
modelFile: `${GLTF_BASE_URL}DamagedHelmet/glTF-Binary/DamagedHelmet.glb`,
initialZoom: 5
},
duck: {
modelFile: `${GLTF_BASE_URL}Duck/glTF-Binary/Duck.glb`,
initialZoom: 8
},
monster: {
modelFile: `${GLTF_BASE_URL}Monster/glTF-Binary/Monster.glb`,
initialZoom: 120
}
};
export default Object.keys(examples).map(name => {
const app = new DemoApp(examples[name]);
const animationLoop = new AnimationLoop(app);
return {
name,
onInitialize: params => {
return animationLoop.onInitialize(params);
},
onRender: params => {
const result = animationLoop.onRender(params);
if (result !== false) {
params.done();
}
},
timeout: 5000,
onFinalize: animationLoop.onFinalize.bind(animationLoop),
goldenImage: `./test/render/golden-images/${name}.png`
};
});

Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

View File

@ -2,6 +2,7 @@ import test from 'tape-catch';
import {SnapshotTestRunner} from '@luma.gl/test-utils';
import EXAMPLE_TEST_CASES from './example-test-cases';
import GLTF_TEST_CASES from './gltf-test-cases';
const renderTestCaseCount = EXAMPLE_TEST_CASES.length;
@ -11,6 +12,7 @@ test('RenderTest', t => {
new SnapshotTestRunner({width: 600, height: 400})
.add(EXAMPLE_TEST_CASES)
.add(GLTF_TEST_CASES)
.run({
onTestStart: testCase => t.comment(testCase.name),
onTestPass: (testCase, result) => t.pass(`match: ${result.matchPercentage}`),

View File

@ -720,6 +720,20 @@
lodash "^4.17.10"
to-fast-properties "^2.0.0"
"@loaders.gl/core@^0.6.2":
version "0.6.2"
resolved "https://registry.yarnpkg.com/@loaders.gl/core/-/core-0.6.2.tgz#d4260e27c367e4c41ea7ba69a2d9525ee608511b"
integrity sha512-dG8mTy+c+xqgkYKe/We6mgLfesCy3ITlEdfWccKjWupIa6iKPBnf/CgDQE8+C4IOzKR5njDCMMKKOM0kZIdDQw==
dependencies:
text-encoding "^0.6.4"
"@loaders.gl/gltf@^0.6.2":
version "0.6.2"
resolved "https://registry.yarnpkg.com/@loaders.gl/gltf/-/gltf-0.6.2.tgz#03f4546840d0bf6c2e64cb0c08c3723af3106a6f"
integrity sha512-vZZV029K0ZOg/7lOJ/FF7mu5a1UZg0OTNrDMBpUFLlyX7gEheErGOpLD3WlDA+SxBdsdb4RLA7rCdpRLN5yyAQ==
dependencies:
"@loaders.gl/core" "^0.6.2"
"@luma.gl/glfx@^6.3.0-alpha.2":
version "6.3.0"
resolved "https://registry.yarnpkg.com/@luma.gl/glfx/-/glfx-6.3.0.tgz#08929e3488b58ddf339c6df0627282543d78c66a"
@ -7557,6 +7571,11 @@ test-exclude@^5.0.0:
read-pkg-up "^4.0.0"
require-main-filename "^1.0.1"
text-encoding@^0.6.4:
version "0.6.4"
resolved "https://registry.yarnpkg.com/text-encoding/-/text-encoding-0.6.4.tgz#e399a982257a276dae428bb92845cb71bdc26d19"
integrity sha1-45mpgiV6J22uQou5KEXLcb3CbRk=
text-extensions@^1.0.0:
version "1.8.0"
resolved "https://registry.yarnpkg.com/text-extensions/-/text-extensions-1.8.0.tgz#6f343c62268843019b21a616a003557bdb952d2b"