Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update gltf Pipeline and support KHR_techniques_webgl and KHR_blend #6805

Merged
merged 61 commits into from
Sep 19, 2018

Conversation

ggetz
Copy link
Contributor

@ggetz ggetz commented Jul 16, 2018

Part of (fixes?) CesiumGS/gltf-pipeline#330

Ran through the Sandcastle examples to check the new updates, and the one issue I see is with classification (in this sandcastle demo). The classification model is still based on glTF 1.0, and the indices seem to be wrong. Any ideas?

Incorporates #6803 to fix bounding spheres, merge that first.

TODO:

@ggetz ggetz requested a review from lilleyse July 16, 2018 21:14
@cesium-concierge
Copy link

Thanks for the pull request @ggetz!

  • ✔️ Signed CLA found.
  • CHANGES.md was not updated.
    • If this change updates the public API in any way, please add a bullet point to CHANGES.md.
  • ❔ Changes to third party files were made.
    • Looks like a file in one of our ThirdParty folders (ThirdParty/, Source/ThirdParty/) has been added or modified. Please verify that it has a section in LICENSE.md and that its license information is up to date with this new version.

Reviewers, don't forget to make sure that:

  • Cesium Viewer works.
  • Works in 2D/CV.
  • Works (or fails gracefully) in IE11.

I am a bot who helps you make Cesium awesome! Contributions to my configuration are welcome.

🌍 🌎 🌏

Copy link
Contributor

@lilleyse lilleyse left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall looks pretty good. I like the organizational and cleanup changes, the more the better since it's not often that Model is updated so heavily.

For testing I would recommend:

Some other changes to make:

  • Some small edits have been made in gltf-pipeline since this PR was opened - make sure all files are up to date before we merge this.
  • Handle the ALPHA_MASK uniform for KHR_techniques_webgl (I saw there was a TODO for that)

To be safe, let's merge this after August 1st.

@@ -124,25 +124,25 @@ define([

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's probably worth doing a pass over the documentation to fix some of the existing problems like:

  • References the old KHR_binary_glTF extension
  • Some errors that are old
    • @exception {DeveloperError} bgltf is not a valid Binary glTF file.
    • @exception {DeveloperError} Only glTF Binary version 1 is supported.
  • @param {Object|ArrayBuffer|Uint8Array} options.gltf The object for the glTF JSON or an arraybuffer of Binary glTF defined by the KHR_binary_glTF extension. - only binary glTF is supported.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also for Model and Model.fromGltf.

var meshId = gltfNode.mesh;
if (gltfNodes.length !== 1 || !defined(meshId)) {
var gltfNode = gltfNodes.rootNode;
if (!defined(gltfNode) || !defined(gltfNode.meshes)) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The classification model is still based on glTF 1.0, and the indices seem to be wrong. Any ideas?

It looks like parseBinaryGltf used to also update the version but parseGlb does not. Make sure to call updateVersion and addDefaults after parseGlb.

After fixing that I suspect a lot of the other code changes below may not be needed.

@@ -646,7 +646,9 @@ define([
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Above in parseBuffers, and throughout - keep an eye out for ways to clean up the code using gltf-pipeline helper functions. For example, parseBuffers can use ForEach.buffer. Also it may not need the extras._pipeline lines.

buffer.extras = defaultValue(buffer.extras, {});
buffer.extras._pipeline = defaultValue(buffer.extras._pipeline, {});

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similarly ForEach.meshPrimitiveAttribute in createVertexArray.

var parameterName = uniforms[name];
ForEach.technique(model.gltf, function(technique) {
var parameters = technique.parameters;
ForEach.techniqueUniform(technique, function(parameterName, uniformName) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks like another area that is depending on the glTF being 1.0. Normally a 2.0 model with the techniques extension would not have parameters.

updateVersion(this.gltf);
if (defined(this.gltf.asset) && defined(this.gltf.asset.extras) &&
this.gltf.asset.extras.gltf_pipeline_upgrade_10to20) {
this._forwardAxis = Axis.X;
this.gltf.asset.extras.gltf_pipeline_upgrade_10to20) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is one thing that got lost between 2.0-cesium and 2.0 in gltf-pipeline.

CesiumGS/gltf-pipeline#371

One change - add gltf_pipeline_upgrade_10to20 to gltf.extras._pipeline instead of gltf.asset.extras

@@ -2250,7 +2265,7 @@ define([
var tx;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Above in createSamplers, use ForEach.sampler.

@@ -2528,7 +2545,7 @@ define([
stopTime : stopTime,
channelEvaluators : channelEvaluators
};
}
});
}

function createVertexArrays(model, context) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Below in createVertexArrays, use ForEach.mesh, ForEach.meshPrimitive, and ForEach.meshPrimitiveAttribute

// semantic or targeted via a source (for animation) are not
// targetable for material animations. Is this too strict?
//
// https://github.com/KhronosGroup/glTF/issues/142
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are these GLTF_SPEC comments here (and others throughout) still relevant?

shader = modifyShader(shader, id, model._vertexShaderLoaded);
toClipCoordinates[id] = ModelUtility.toClipCoordinatesGLSL(model.gltf, shader);
shader = modifyShader(shader, programId, model._vertexShaderLoaded);
toClipCoordinates[programId] = ModelUtility.toClipCoordinatesGLSL(model.gltf, shader);
}
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right below - model.gltf.glExtensionsUsed - this is now part of the techniques_webgl extension.

return undefined;

return function(parameterName, attributeOrUniformName) {
var attributeOrUniform = technique.parameters[parameterName];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this block needed? The KHR_techniques_webgl extension should be defined.

@lilleyse
Copy link
Contributor

@ggetz when this is ready can you publish a new version of the power plant tileset to ion?

I checked that upgrade converts it correctly and it loads in this branch. That's really good because it uses pretty complicated glTF techniques and shaders.

@lilleyse
Copy link
Contributor

lilleyse commented Aug 9, 2018

Related to #6805 (comment), since gltf-pipeline no longer adds pipeline extras to everything there is now a bug when a model has an unused material. A few areas of the code try to access material.extras._pipeline.primitive when extras._pipeline doesn't exist.

CUBE.gltf.txt

This model reveals another bug related to primitive.material being undefined. I'll open a gltf-pipeline fix for that.

@ggetz
Copy link
Contributor Author

ggetz commented Aug 20, 2018

@lilleyse Other than specs which I'm working on now, this should be updated. I handle ALPHA_MASK and have the latest build of gltf-pipeline here.

I removed pipeline extras where applicable, but they are needed for updateVersion. Also fixed the bug related to material.extras._pipeline.primitive

Tested the sample models as well as Polly.

@lilleyse
Copy link
Contributor

Thanks @ggetz, I hope to look at this later today.

@@ -103,17 +94,15 @@ define([
* @private
*
* @param {Object} [options] Object with the following properties:
* @param {Object|ArrayBuffer|Uint8Array} options.gltf The object for the glTF JSON or an arraybuffer of Binary glTF defined by the KHR_binary_glTF extension.
* @param {Resource|String} [options.basePath=''] The base path that paths in the glTF JSON are relative to.
* @param {ArrayBuffer|Uint8Array} [options.gltf] A binary glTF buffer.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

options and options.gltf are required

@@ -242,13 +225,15 @@ define([
* Cesium supports glTF assets with the following extensions:
* <ul>
* <li>
* {@link https://github.com/KhronosGroup/glTF/blob/master/extensions/1.0/Khronos/KHR_binary_glTF/README.md|KHR_binary_glTF}
* </li><li>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Technically this can be left in since we do support that extension.

});
}

function parsePrograms(model) {
ForEach.program(model.gltf, function(program, id) {
model._loadResources.programsToCreate.enqueue(id);
var sourcePrograms = model._sourcePrograms = {};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be better to initialize _sourcePrograms in the constructor where _sourceTechniques and _sourceShaders are also initialized.

@@ -1499,6 +1373,9 @@ define([
var buffers = gltf.buffers;
var bufferViews = gltf.bufferViews;
ForEach.shader(gltf, function(shader, id) {
// retain reference to source shader text
var sourceShader = model._sourceShaders[id] = clone(shader.extras._pipeline.source);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think clone is needed for a string.

if (defined(this.gltf.asset) && defined(this.gltf.asset.extras) &&
this.gltf.asset.extras.gltf_pipeline_upgrade_10to20) {
this._forwardAxis = Axis.X;
if (this.gltf.extras._pipeline.gltf_pipeline_upgrade_10to20) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There will need to be a small PR into gltf-pipeline that adds this property in updateVersion.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was from merging in the previous forward axis fixes. I would rather do a check of the original version number before the update than update gltf-pipeline itself.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, that sounds like a better approach.

rendererRenderStates[id] = RenderState.fromCache({
frontFace : defined(statesFunctions.frontFace) ? statesFunctions.frontFace[0] : WebGLConstants.CCW,
var enableCulling = !material.doubleSided;
var blendingEnabled = (material.alphaMode !== 'OPAQUE');
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See #6805 (comment)

I think this should actually be material.alphaMode === 'BLEND'); since MASK does not require blending to be enabled, just that discard is called in the shader.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It still needs the depth states, I will make a separate path though for MASK.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

MASK can use the same depth states as OPAQUE.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, my mistake, it was blending that needs to be enabled if alphaMode is MASK. Otherwise this model will not render correctly:

image

Copy link
Contributor

@lilleyse lilleyse Aug 27, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok I thought the PBR shader was calling discard if the alpha value was below the cutoff, but it looks like it isn't. Tweaking the shader to use discard would be preferable to enabling blending for MASK.

@@ -4314,6 +4101,8 @@ define([
}

if (loadResources.finished()) {
ModelUtility.removePipelineExtras(this.gltf);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is ModelUtility.removePipelineExtras still needed? Can gltf-pipeline's removePipelineExtras be used now instead?

@ggetz
Copy link
Contributor Author

ggetz commented Sep 13, 2018

@lilleyse, this should be ready for another look. I've incorporated the changes made via gltf-pipeline, fixed a bug I noticed with model caching and the forward axis, fixed the current specs, and added additional specs for loading 2.0 models and 2.0 models using the techniques extension.

@lilleyse
Copy link
Contributor

Thanks @ggetz, I will do some final testing later today.

if (!this._loadRendererResourcesFromCache) {
var gltf = this.gltf;
// Add the original version so it remains cached
gltf.extras.sourceVersion = gltf.asset.version;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If it still works, maybe it is cleaner to store the source version as a property on model rather than extras?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll have to set up a new cache just for the version number since it's the processed gltf object which becomes cached. That seems messier than adding it to extras to me, but I can if we really want to avoid adding it.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, that makes sense. The method here sounds a lot easier for caching than my suggestion.

if (!this._loadRendererResourcesFromCache) {
var gltf = this.gltf;
// Add the original version so it remains cached
gltf.extras.sourceVersion = gltf.asset.version;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I ran into an old tileset that doesn't actually set gltf.asset which is technically valid for gltf 1.0. The code here and in ModelUtility should account for that and assume 1.0 if asset is undefined.

// so we should apply PBR unless no materials are found.
if (gltf.materials.length === 0) {
return gltf;
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hit a weird edge case where a gltf didn't have any meshes so it didn't even create any default materials and failed at this line. I guess a quick check that gltf.materials is defined should fix this. CC @OmarShehata.

@lilleyse
Copy link
Contributor

I'm seeing three test failures:

  • Scene/ModelInstanceCollection renders rigged figure
  • Scene/ModelInstanceCollection renders with animations when instancing is disabled
  • Scene/Model renders with a silhouette

The last two pass when run individually.

* </li><li>
* {@link https://github.com/KhronosGroup/glTF/blob/master/extensions/2.0/Khronos/KHR_techniques_webgl/README.md|KHR_techniques_webgl}
* </li><li>
* {@link https://github.com/KhronosGroup/glTF/blob/master/extensions/2.0/Khronos/KHR_blend/README.md|KHR_blend}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add KHR_materials_unlit and KHR_materials_pbrSpecularGlossiness to this list. Forgot to add those in the other PRs.

* </li><li>
* {@link https://github.com/KhronosGroup/glTF/blob/master/extensions/2.0/Khronos/KHR_techniques_webgl/README.md|KHR_techniques_webgl}
* </li><li>
* {@link https://github.com/KhronosGroup/glTF/blob/master/extensions/2.0/Khronos/KHR_blend/README.md|KHR_blend}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also add those two extensions here.

@lilleyse
Copy link
Contributor

I think that's it from me. Besides those edge cases I haven't seen any other issues. 👍


scene.renderForSpecs();
});
});
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@OmarShehata The above 3 tests have no expectations and don't remove the model. This is causing the last of the failing tests in this branch. Can you take a look soon? We're trying to get this merged early so it has some time in master before the release.

@OmarShehata OmarShehata mentioned this pull request Sep 19, 2018
@ggetz
Copy link
Contributor Author

ggetz commented Sep 19, 2018

Thanks @lilleyse! Tests are all cleaned up, and your feedback has been addressed.

@lilleyse
Copy link
Contributor

Thanks @ggetz. Awesome to get this in!

@lilleyse lilleyse merged commit 0ffd273 into master Sep 19, 2018
@lilleyse lilleyse deleted the gltf-update-pipeline branch September 19, 2018 18:05
@emackey
Copy link
Contributor

emackey commented Sep 19, 2018

Congrats @ggetz, @OmarShehata, and everyone involved. It's great to have the PBR shader generation moved into core Cesium like this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Remove pipeline extras for glTF
6 participants