-
Notifications
You must be signed in to change notification settings - Fork 3.5k
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
Conversation
Thanks for the pull request @ggetz!
Reviewers, don't forget to make sure that:
I am a bot who helps you make Cesium awesome! Contributions to my configuration are welcome. 🌍 🌎 🌏 |
There was a problem hiding this 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:
- Run all model and 3D Tiles Sandcastle demos
- Test changing a model's color or clipping planes to make sure shader regeneration still works
- Load all 1.0 and 2.0 models in https://github.com/KhronosGroup/glTF-Sample-Models and Polly
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 forKHR_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([ | |||
|
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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
.
Source/Scene/ClassificationModel.js
Outdated
var meshId = gltfNode.mesh; | ||
if (gltfNodes.length !== 1 || !defined(meshId)) { | ||
var gltfNode = gltfNodes.rootNode; | ||
if (!defined(gltfNode) || !defined(gltfNode.meshes)) { |
There was a problem hiding this comment.
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([ | |||
} |
There was a problem hiding this comment.
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, {});
There was a problem hiding this comment.
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
.
Source/Scene/ClassificationModel.js
Outdated
var parameterName = uniforms[name]; | ||
ForEach.technique(model.gltf, function(technique) { | ||
var parameters = technique.parameters; | ||
ForEach.techniqueUniform(technique, function(parameterName, uniformName) { |
There was a problem hiding this comment.
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
.
Source/Scene/Model.js
Outdated
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) { |
There was a problem hiding this comment.
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.
One change - add gltf_pipeline_upgrade_10to20
to gltf.extras._pipeline
instead of gltf.asset.extras
@@ -2250,7 +2265,7 @@ define([ | |||
var tx; |
There was a problem hiding this comment.
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) { |
There was a problem hiding this comment.
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 |
There was a problem hiding this comment.
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); | ||
} | ||
} | ||
|
There was a problem hiding this comment.
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]; |
There was a problem hiding this comment.
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.
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 This model reveals another bug related to |
@lilleyse Other than specs which I'm working on now, this should be updated. I handle I removed pipeline extras where applicable, but they are needed for Tested the sample models as well as Polly. |
Thanks @ggetz, I hope to look at this later today. |
Source/Scene/ClassificationModel.js
Outdated
@@ -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. |
There was a problem hiding this comment.
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
Source/Scene/Model.js
Outdated
@@ -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> |
There was a problem hiding this comment.
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.
Source/Scene/Model.js
Outdated
}); | ||
} | ||
|
||
function parsePrograms(model) { | ||
ForEach.program(model.gltf, function(program, id) { | ||
model._loadResources.programsToCreate.enqueue(id); | ||
var sourcePrograms = model._sourcePrograms = {}; |
There was a problem hiding this comment.
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.
Source/Scene/Model.js
Outdated
@@ -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); |
There was a problem hiding this comment.
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.
Source/Scene/Model.js
Outdated
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) { |
There was a problem hiding this comment.
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
.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
Source/Scene/Model.js
Outdated
rendererRenderStates[id] = RenderState.fromCache({ | ||
frontFace : defined(statesFunctions.frontFace) ? statesFunctions.frontFace[0] : WebGLConstants.CCW, | ||
var enableCulling = !material.doubleSided; | ||
var blendingEnabled = (material.alphaMode !== 'OPAQUE'); |
There was a problem hiding this comment.
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');
sinceMASK
does not require blending to be enabled, just thatdiscard
is called in the shader.
There was a problem hiding this comment.
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
.
There was a problem hiding this comment.
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
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
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
.
Source/Scene/Model.js
Outdated
@@ -4314,6 +4101,8 @@ define([ | |||
} | |||
|
|||
if (loadResources.finished()) { | |||
ModelUtility.removePipelineExtras(this.gltf); |
There was a problem hiding this comment.
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?
@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. |
Thanks @ggetz, I will do some final testing later today. |
Support glTF Specular Glossiness Extension
Source/Scene/Model.js
Outdated
if (!this._loadRendererResourcesFromCache) { | ||
var gltf = this.gltf; | ||
// Add the original version so it remains cached | ||
gltf.extras.sourceVersion = gltf.asset.version; |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
Source/Scene/Model.js
Outdated
if (!this._loadRendererResourcesFromCache) { | ||
var gltf = this.gltf; | ||
// Add the original version so it remains cached | ||
gltf.extras.sourceVersion = gltf.asset.version; |
There was a problem hiding this comment.
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.
Source/Scene/processPbrMaterials.js
Outdated
// so we should apply PBR unless no materials are found. | ||
if (gltf.materials.length === 0) { | ||
return gltf; | ||
} |
There was a problem hiding this comment.
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.
I'm seeing three test failures:
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} |
There was a problem hiding this comment.
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} |
There was a problem hiding this comment.
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.
I think that's it from me. Besides those edge cases I haven't seen any other issues. 👍 |
Specs/Scene/ModelSpec.js
Outdated
|
||
scene.renderForSpecs(); | ||
}); | ||
}); |
There was a problem hiding this comment.
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.
Thanks @lilleyse! Tests are all cleaned up, and your feedback has been addressed. |
Thanks @ggetz. Awesome to get this in! |
Congrats @ggetz, @OmarShehata, and everyone involved. It's great to have the PBR shader generation moved into core Cesium like this. |
Part of (fixes?) CesiumGS/gltf-pipeline#330
ThirdParty/gltfPipeline
files to use the2.0
branchKHR_techniques_webgl
extensionKHR_blend
extensionRan 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:
CHANGES.md