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

2.0 pbr #274

Merged
merged 6 commits into from
Jun 9, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions gulpfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -285,9 +285,11 @@ gulp.task('build-cesium', function () {
'findAccessorMinMax.js',
'ForEach.js',
'getAccessorByteStride.js',
'getJointCountForMaterials.js',
'getStatistics.js',
'numberOfComponentsForType.js',
'parseBinaryGltf.js',
'pbrToMaterialsCommon.js',
'processModelMaterialsCommon.js',
'removePipelineExtras.js',
'removeExtensionsRequired.js',
Expand Down
184 changes: 67 additions & 117 deletions lib/generateModelMaterialsCommon.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
'use strict';
var Cesium = require('cesium');
var addExtensionsRequired = require('./addExtensionsRequired');
var ForEach = require('./ForEach');
var getJointCountForMaterials = require('./getJointCountForMaterials');

var defaultValue = Cesium.defaultValue;
var defined = Cesium.defined;
Expand All @@ -26,7 +28,6 @@ function generateModelMaterialsCommon(gltf, kmcOptions) {
kmcOptions.technique = defaultValue(kmcOptions.technique, 'PHONG');
addExtensionsRequired(gltf, 'KHR_materials_common');
var materialsCommon;
var materials = gltf.materials;
var nodes = gltf.nodes;
var techniques = gltf.techniques;
var jointCountForMaterialId = getJointCountForMaterials(gltf);
Expand All @@ -41,133 +42,82 @@ function generateModelMaterialsCommon(gltf, kmcOptions) {
var lights = {};
materialsCommon.lights = lights;

for (var materialId in materials) {
if (materials.hasOwnProperty(materialId)) {
var material = materials[materialId];
var technique = techniques[material.technique];
var techniqueParameters = technique.parameters;
if (defined(techniqueParameters.ambient) && !defined(lights.defaultAmbient)) {
lights.defaultAmbient = {
ambient: {
color: [1, 1, 1]
},
name: 'defaultAmbient',
type: 'ambient'
};
}
for (var parameterId in techniqueParameters) {
if (techniqueParameters.hasOwnProperty(parameterId)) {
if (parameterId.indexOf('light') === 0 && parameterId.indexOf('Transform') >= 0) {
var lightId = parameterId.substring(0, parameterId.indexOf('Transform'));
var lightTransform = techniqueParameters[parameterId];
var lightNodeId = lightTransform.node;
var lightNode = nodes[lightNodeId];
var nodeExtensions = lightNode.extensions;
if (!defined(nodeExtensions)) {
nodeExtensions = {};
lightNode.extensions = nodeExtensions;
}
materialsCommon = {};
nodeExtensions.KHR_materials_common = materialsCommon;
materialsCommon.light = lightId;
var lightColor = techniqueParameters[lightId + 'Color'];
var light = {
name: lightId,
type: 'directional',
directional: {
color: defaultValue(lightColor.value, [1, 1, 1])
}
};
lights[lightId] = light;
ForEach.material(gltf, function(material, materialId) {
var technique = techniques[material.technique];
var techniqueParameters = technique.parameters;
if (defined(techniqueParameters.ambient) && !defined(lights.defaultAmbient)) {
lights.defaultAmbient = {
ambient: {
color: [1, 1, 1]
},
name: 'defaultAmbient',
type: 'ambient'
};
}
for (var parameterId in techniqueParameters) {
if (techniqueParameters.hasOwnProperty(parameterId)) {
if (parameterId.indexOf('light') === 0 && parameterId.indexOf('Transform') >= 0) {
var lightId = parameterId.substring(0, parameterId.indexOf('Transform'));
var lightTransform = techniqueParameters[parameterId];
var lightNodeId = lightTransform.node;
var lightNode = nodes[lightNodeId];
var nodeExtensions = lightNode.extensions;
if (!defined(nodeExtensions)) {
nodeExtensions = {};
lightNode.extensions = nodeExtensions;
}
materialsCommon = {};
nodeExtensions.KHR_materials_common = materialsCommon;
materialsCommon.light = lightId;
var lightColor = techniqueParameters[lightId + 'Color'];
var light = {
name: lightId,
type: 'directional',
directional: {
color: defaultValue(lightColor.value, [1, 1, 1])
}
};
lights[lightId] = light;
}
}
}

delete material.technique;
var extensions = material.extensions;
if (!defined(extensions)) {
extensions = {};
material.extensions = extensions;
}
materialsCommon = {};
extensions.KHR_materials_common = materialsCommon;
for (var kmcOption in kmcOptions) {
if (kmcOptions.hasOwnProperty(kmcOption) && kmcOption !== 'enable') {
materialsCommon[kmcOption] = kmcOptions[kmcOption];
}
}
var jointCount = jointCountForMaterialId[materialId];
if (defined(jointCount)) {
materialsCommon.jointCount = jointCount;
delete material.technique;
var extensions = material.extensions;
if (!defined(extensions)) {
extensions = {};
material.extensions = extensions;
}
materialsCommon = {};
extensions.KHR_materials_common = materialsCommon;
for (var kmcOption in kmcOptions) {
if (kmcOptions.hasOwnProperty(kmcOption) && kmcOption !== 'enable') {
materialsCommon[kmcOption] = kmcOptions[kmcOption];
}
}
var jointCount = jointCountForMaterialId[materialId];
if (defined(jointCount)) {
materialsCommon.jointCount = jointCount;
}

var materialValues = material.values;
var diffuseColor, transparency;
if (defined(materialValues)) {
diffuseColor = materialValues.diffuse;
transparency = materialValues.transparency;
materialsCommon.values = materialValues;
}
var materialValues = material.values;
var diffuseColor, transparency;
if (defined(materialValues)) {
diffuseColor = materialValues.diffuse;
transparency = materialValues.transparency;
materialsCommon.values = materialValues;
}

// Check if we have transparency and set transparent flag
if ((defined(transparency) && transparency < 1.0) ||
(defined(diffuseColor) && Array.isArray(diffuseColor) && diffuseColor[3] < 1.0)) {
materialsCommon.values.transparent = true;
}
delete material.values;
// Check if we have transparency and set transparent flag
if ((defined(transparency) && transparency < 1.0) ||
(defined(diffuseColor) && Array.isArray(diffuseColor) && diffuseColor[3] < 1.0)) {
materialsCommon.values.transparent = true;
}
}
delete material.values;
});
delete gltf.techniques;
delete gltf.programs;
delete gltf.shaders;
return gltf;
}

function getJointCountForMaterials(gltf) {
var accessors = gltf.accessors;
var meshes = gltf.meshes;
var nodes = gltf.nodes;
var skins = gltf.skins;
var jointCountForMaterialId = {};

var nodesForSkinId = {};
for (var nodeId in nodes) {
if (nodes.hasOwnProperty(nodeId)) {
var node = nodes[nodeId];
if (defined(node.skin)) {
if (!defined(nodesForSkinId[node.skin])) {
nodesForSkinId[node.skin] = [];
}
nodesForSkinId[node.skin].push(node);
}
}
}

for (var skinId in skins) {
if (skins.hasOwnProperty(skinId)) {
var skin = skins[skinId];
var jointCount = 1;
if (defined(skin.inverseBindMatrices)) {
jointCount = accessors[skin.inverseBindMatrices].count;
}
var skinnedNodes = nodesForSkinId[skinId];
var skinnedNodesLength = skinnedNodes.length;
for (var i = 0; i < skinnedNodesLength; i++) {
var skinnedNode = skinnedNodes[i];
var nodeMeshes = skinnedNode.meshes;
var nodeMeshesLength = nodeMeshes.length;
for (var j = 0; j < nodeMeshesLength; j++) {
var meshId = nodeMeshes[j];
var mesh = meshes[meshId];
var primitives = mesh.primitives;
var primitivesLength = primitives.length;
for (var k = 0; k < primitivesLength; k++) {
var primitive = primitives[k];
jointCountForMaterialId[primitive.material] = jointCount;
}
}
}
}
}
return jointCountForMaterialId;
}
41 changes: 41 additions & 0 deletions lib/getJointCountForMaterials.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
'use strict';
Copy link
Contributor

Choose a reason for hiding this comment

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

Now that it's a new file, does it need a spec?

var Cesium = require('cesium');
var ForEach = require('./ForEach');

var defined = Cesium.defined;

module.exports = getJointCountForMaterials;

function getJointCountForMaterials(gltf) {
var meshes = gltf.meshes;
var jointCountForMaterialId = {};

var nodesForSkinId = {};
ForEach.node(gltf, function(node) {
if (defined(node.skin)) {
if (!defined(nodesForSkinId[node.skin])) {
nodesForSkinId[node.skin] = [];
}
nodesForSkinId[node.skin].push(node);
}
});

ForEach.skin(gltf, function(skin, skinId) {
var jointCount = skin.joints.length;
var meshPrimitiveFunction = function(primitive) {
jointCountForMaterialId[primitive.material] = jointCount;
};
var skinnedNodes = nodesForSkinId[skinId];
var skinnedNodesLength = skinnedNodes.length;
for (var i = 0; i < skinnedNodesLength; i++) {
var skinnedNode = skinnedNodes[i];
var meshId = skinnedNode.mesh;
if (defined(meshId)) {
var mesh = meshes[meshId];
ForEach.meshPrimitive(mesh, meshPrimitiveFunction);
}
}
});

return jointCountForMaterialId;
}
119 changes: 119 additions & 0 deletions lib/pbrToMaterialsCommon.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
'use strict';
var Cesium = require('cesium');
var addExtensionsRequired = require('./addExtensionsRequired');
var ForEach = require('./ForEach');
var getJointCountForMaterials = require('./getJointCountForMaterials');
var removeExtensionsUsed = require('./removeExtensionsUsed');

var defined = Cesium.defined;

module.exports = pbrToMaterialsCommon;

/**
* Convert PBR materials to use a KHR_materials_common BLINN shader.
* This is a lossy conversion, and as such should only be used for
* compatibility reasons. Normal texture and metallic roughness information
* will be lost, and some color or texture information may be lost.
*
* @param {Object} gltf A javascript object containing a glTF asset.
* @returns {Object} The glTF asset with materials converted to KHR_materials_common
*/
function pbrToMaterialsCommon(gltf) {
var materialJointCount = getJointCountForMaterials(gltf);
Copy link
Contributor

Choose a reason for hiding this comment

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

If possible, transparent should be incorporated into this.

ForEach.material(gltf, function(material, materialId) {
var values = {
ambient : [ 0.0, 0.0, 0.0, 1.0 ],
diffuse : [ 0.0, 0.0, 0.0, 1.0 ],
emission : [ 0.0, 0.0, 0.0, 1.0 ],
specular : [ 0.0, 0.0, 0.0, 1.0],
shininess : [ 0.0 ]
};
var pbrMetallicRoughness = material.pbrMetallicRoughness;
var isPBR = defined(pbrMetallicRoughness) ||
(defined(material.extensions) && defined(material.extensions.KHR_materials_pbrSpecularGlossiness) ||
defined(material.occlusionTexture) ||
defined(material.emissiveFactor) ||
defined(material.emissiveTexture) ||
defined(material.doubleSided));

if (defined(pbrMetallicRoughness)) {
var baseColorFactor = pbrMetallicRoughness.baseColorFactor;
if (defined(baseColorFactor)) {
values.diffuse = baseColorFactor;
}
var baseColorTexture = pbrMetallicRoughness.baseColorTexture;
if (defined(baseColorTexture)) {
values.diffuse = [baseColorTexture.index];
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Is it possible to estimate specular and shininess from roughness?

Copy link

Choose a reason for hiding this comment

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

Should be possible to calculate, not estimate, I would expect.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@emackey do you know of any resources for this that I should be looking at?

}
var extensions = material.extensions;
if (defined(extensions)) {
var pbrSpecularGlossiness = extensions.KHR_materials_pbrSpecularGlossiness;
if (defined(pbrSpecularGlossiness)) {
var diffuseFactor = pbrSpecularGlossiness.diffuseFactor;
// Use baseColorTexture if it was defined
if (defined(diffuseFactor) && values.diffuse.length > 1) {
values.diffuse = diffuseFactor;
}
// diffuseTexture should be used instead of baseColorTexture if defined
var diffuseTexture = pbrSpecularGlossiness.diffuseTexture;
if (defined(diffuseTexture)) {
values.diffuse = [diffuseTexture.index];
}
var specularFactor = pbrSpecularGlossiness.specularFactor;
if (defined(specularFactor)) {
values.specular[0] = specularFactor[0];
values.specular[1] = specularFactor[1];
values.specular[2] = specularFactor[2];
}
var glossinessFactor = pbrSpecularGlossiness.glossinessFactor;
if (defined(glossinessFactor)) {
values.shininess[0] = glossinessFactor;
}
var specularGlossinessTexture = pbrSpecularGlossiness.specularGlossinessTexture;
if (defined(specularGlossinessTexture)) {
values.specular = [specularGlossinessTexture.index];
}
}
}
var occlusionTexture = material.occlusionTexture;
if (defined(occlusionTexture)) {
values.ambient = [occlusionTexture.index];
}
var emissiveFactor = material.emissiveFactor;
if (defined(emissiveFactor)) {
values.emission[0] = emissiveFactor[0];
values.emission[1] = emissiveFactor[1];
values.emission[2] = emissiveFactor[2];
}
var emissiveTexture = material.emissiveTexture;
if (defined(emissiveTexture)) {
values.emission = [emissiveTexture.index];
}
var doubleSided = material.doubleSided;
if (isPBR) {
delete material.doubleSided;
delete material.emissiveFactor;
delete material.emissiveTexture;
delete material.normalTexture;
delete material.occlusionTexture;
delete material.pbrMetallicRoughness;
var materialsCommon = {
technique: 'BLINN',
values: values
};
var jointCount = materialJointCount[materialId];
if (defined(jointCount)) {
materialsCommon.jointCount = jointCount;
}
if (defined(doubleSided)) {
materialsCommon.doubleSided = doubleSided;
}
material.extensions = {
KHR_materials_common: materialsCommon
};
addExtensionsRequired(gltf, 'KHR_materials_common');
removeExtensionsUsed(gltf, 'KHR_materials_pbrSpecularGlossiness');
}
});
}
Loading