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

Support for emissive-only materials #6501

Merged
merged 7 commits into from
Apr 27, 2018
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ Change Log
* Fixed crash bug in PolylineCollection when a polyline was updated and removed at the same time. [#6455](https://github.com/AnalyticalGraphicsInc/cesium/pull/6455)
* Fixed Imagery Layers Texture Filters Sandcastle example. [#6472](https://github.com/AnalyticalGraphicsInc/cesium/pull/6472).
* Fixed a bug causing Cesium 3D Tilesets to not clip properly when tiles were unloaded and reloaded. [#6484](https://github.com/AnalyticalGraphicsInc/cesium/issues/6484)
* Improved rendering of glTF models that don't contain normals with a temporary unlit shader workaround. [#6501](https://github.com/AnalyticalGraphicsInc/cesium/pull/6501)
* Fixed rendering of glTF models with emissive-only materials. [#6501](https://github.com/AnalyticalGraphicsInc/cesium/pull/6501)

### 1.44 - 2018-04-02

Expand Down
122 changes: 74 additions & 48 deletions Source/ThirdParty/GltfPipeline/processPbrMetallicRoughness.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ define([

var hasPbrMetallicRoughness = false;
ForEach.material(gltf, function(material) {
if (defined(material.pbrMetallicRoughness)) {
if (isPbrMaterial(material)) {
hasPbrMetallicRoughness = true;
}
});
Expand All @@ -46,17 +46,17 @@ define([
gltf.techniques = [];
}

// Pre-processing to address incompatibilities between primitives using the same materials. Handles skinning and vertex color incompatibilities.
// Pre-processing to address incompatibilities between primitives using the same materials.
splitIncompatibleMaterials(gltf);

ForEach.material(gltf, function(material, materialIndex) {
var pbrMetallicRoughness = material.pbrMetallicRoughness;
if (defined(pbrMetallicRoughness)) {
var technique = generateTechnique(gltf, material, materialIndex, options);

material.values = pbrMetallicRoughness;
material.technique = technique;
delete material.pbrMetallicRoughness;
if (isPbrMaterial(material)) {
var values = {};
var technique = generateTechnique(gltf, material, materialIndex, values, options);
gltf.materials[materialIndex] = {
values : values,
technique : technique
};
}
});

Expand All @@ -68,7 +68,18 @@ define([
return gltf;
}

function generateTechnique(gltf, material, materialIndex, options) {
function isPbrMaterial(material) {
return defined(material.pbrMetallicRoughness) ||
defined(material.normalTexture) ||
defined(material.occlusionTexture) ||
defined(material.emissiveTexture) ||
defined(material.emissiveFactor) ||
defined(material.alphaMode) ||
defined(material.alphaCutoff) ||
defined(material.doubleSided);
}

function generateTechnique(gltf, material, materialIndex, values, options) {
var optimizeForCesium = defaultValue(options.optimizeForCesium, false);
var hasCesiumRTCExtension = defined(gltf.extensions) && defined(gltf.extensions.CESIUM_RTC);
var addBatchIdToGeneratedShaders = defaultValue(options.addBatchIdToGeneratedShaders, false);
Expand All @@ -77,7 +88,15 @@ define([
var shaders = gltf.shaders;
var programs = gltf.programs;

var parameterValues = material.pbrMetallicRoughness;
var parameterValues = values;
var pbrMetallicRoughness = material.pbrMetallicRoughness;
if (defined(pbrMetallicRoughness)) {
for (var parameterName in pbrMetallicRoughness) {
if (pbrMetallicRoughness.hasOwnProperty(parameterName)) {
parameterValues[parameterName] = pbrMetallicRoughness[parameterName];
}
}
}
for (var additional in material) {
if (material.hasOwnProperty(additional) && ((additional.indexOf('Texture') >= 0) || additional.indexOf('Factor') >= 0) || additional === 'doubleSided') {
parameterValues[additional] = material[additional];
Expand All @@ -98,34 +117,34 @@ define([
var skinningInfo;
var hasSkinning = false;
var hasVertexColors = false;
var hasMorphTargets = false;
var hasNormals = false;
var hasTangents = false;
var hasTexCoords = false;

if (defined(primitiveInfo)) {
skinningInfo = primitiveInfo.skinning;
hasSkinning = skinningInfo.skinned && (joints.length > 0);
hasVertexColors = primitiveInfo.hasVertexColors;
hasMorphTargets = primitiveInfo.hasMorphTargets;
hasNormals = primitiveInfo.hasNormals;
hasTangents = primitiveInfo.hasTangents;
hasTexCoords = primitiveInfo.hasTexCoords;
}

var hasNormals = true;
var hasTangents = false;
var hasMorphTargets = false;
var morphTargets;
if (hasMorphTargets) {
ForEach.mesh(gltf, function(mesh) {
ForEach.meshPrimitive(mesh, function(primitive) {
if (primitive.material === materialIndex) {
var targets = primitive.targets;
if (!hasMorphTargets && defined(targets)) {
hasMorphTargets = true;
if (defined(targets)) {
morphTargets = targets;
}
var attributes = primitive.attributes;
for (var attribute in attributes) {
if (attribute.indexOf('TANGENT') >= 0) {
hasTangents = true;
}
}
}
});
});
}

// Add techniques
var techniqueParameters = {
Expand Down Expand Up @@ -164,16 +183,10 @@ define([
}

// Add material parameters
var hasTexCoords = false;
for (var name in parameterValues) {
//generate shader parameters
if (parameterValues.hasOwnProperty(name)) {
var valType = getPBRValueType(name);
if (!hasTexCoords && (valType === WebGLConstants.SAMPLER_2D)) {
hasTexCoords = true;
}
techniqueParameters[name] = {
type : valType
type : getPBRValueType(name)
};
}
}
Expand Down Expand Up @@ -237,10 +250,12 @@ define([
type : WebGLConstants.FLOAT_VEC3
};
vertexShader += 'attribute vec3 a_position;\n';
if (hasNormals) {
vertexShader += 'varying vec3 v_positionEC;\n';
if (optimizeForCesium) {
vertexShader += 'varying vec3 v_positionWC;\n';
}
}

// Morph Target Weighting
vertexShaderMain += ' vec3 weightedPosition = a_position;\n';
Expand Down Expand Up @@ -280,16 +295,14 @@ define([
} else {
vertexShaderMain += ' vec4 position = vec4(weightedPosition, 1.0);\n';
}
if (optimizeForCesium) {
if (hasNormals && optimizeForCesium) {
vertexShaderMain += ' v_positionWC = (czm_model * position).xyz;\n';
}
vertexShaderMain += ' position = u_modelViewMatrix * position;\n';
if (hasNormals) {
vertexShaderMain += ' v_positionEC = position.xyz;\n';
vertexShaderMain += ' gl_Position = u_projectionMatrix * position;\n';
fragmentShader += 'varying vec3 v_positionEC;\n';
if (optimizeForCesium) {
fragmentShader += 'varying vec3 v_positionWC;\n';
}
vertexShaderMain += ' gl_Position = u_projectionMatrix * position;\n';

// Final normal computation
if (hasNormals) {
Expand All @@ -307,6 +320,11 @@ define([
}

fragmentShader += 'varying vec3 v_normal;\n';
fragmentShader += 'varying vec3 v_positionEC;\n';

if (optimizeForCesium) {
fragmentShader += 'varying vec3 v_positionWC;\n';
}
}

// Read tangents if available
Expand Down Expand Up @@ -387,6 +405,7 @@ define([
vertexShader += '}\n';

// Fragment shader lighting
if (hasNormals) {
fragmentShader += 'const float M_PI = 3.141592653589793;\n';

fragmentShader += 'vec3 lambertianDiffuse(vec3 diffuseColor) \n' +
Expand Down Expand Up @@ -421,6 +440,7 @@ define([
' float f = (NdotH * roughnessSquared - NdotH) * NdotH + 1.0;\n' +
' return roughnessSquared / (M_PI * f * f);\n' +
'}\n\n';
}

fragmentShader += 'vec3 SRGBtoLINEAR3(vec3 srgbIn) \n' +
'{\n' +
Expand Down Expand Up @@ -503,6 +523,8 @@ define([
}

fragmentShader += ' vec3 baseColor = baseColorWithAlpha.rgb;\n';

if (hasNormals) {
// Add metallic-roughness to fragment shader
if (defined(parameterValues.metallicRoughnessTexture)) {
fragmentShader += ' vec3 metallicRoughness = texture2D(u_metallicRoughnessTexture, ' + v_texcoord + ').rgb;\n';
Expand Down Expand Up @@ -607,6 +629,9 @@ define([
fragmentShader += ' vec3 IBLColor = (diffuseIrradiance * diffuseColor) + (specularIrradiance * SRGBtoLINEAR3(specularColor * brdfLut.x + brdfLut.y));\n';
fragmentShader += ' color += IBLColor;\n';
}
} else {
fragmentShader += ' vec3 color = baseColor;\n';
}

if (defined(parameterValues.occlusionTexture)) {
fragmentShader += ' color *= texture2D(u_occlusionTexture, ' + v_texcoord + ').r;\n';
Expand Down Expand Up @@ -763,7 +788,7 @@ define([

var attributes = primitive.attributes;
for (var target in targets) {
if (defined(target)) {
if (targets.hasOwnProperty(target)) {
var targetAttributes = targets[target];
for (var attribute in targetAttributes) {
if (attribute !== 'extras') {
Expand Down Expand Up @@ -829,14 +854,9 @@ define([
var isSkinned = defined(jointAccessorId);
var hasVertexColors = defined(primitive.attributes.COLOR_0);
var hasMorphTargets = defined(primitive.targets);

var hasTangents = false;
var attributes = primitive.attributes;
for (var attribute in attributes) {
if (attribute.indexOf('TANGENT') >= 0) {
hasTangents = true;
}
}
var hasNormals = defined(primitive.attributes.NORMAL);
var hasTangents = defined(primitive.attributes.TANGENT);
var hasTexCoords = defined(primitive.attributes.TEXCOORD_0);

var primitiveInfo = material.extras._pipeline.primitive;
if (!defined(primitiveInfo)) {
Expand All @@ -848,27 +868,33 @@ define([
},
hasVertexColors : hasVertexColors,
hasMorphTargets : hasMorphTargets,
hasTangents : hasTangents
hasNormals : hasNormals,
hasTangents : hasTangents,
hasTexCoords : hasTexCoords
};
} else if ((primitiveInfo.skinning.skinned !== isSkinned) ||
(primitiveInfo.skinning.type !== type) ||
(primitiveInfo.hasVertexColors !== hasVertexColors) ||
(primitiveInfo.hasMorphTargets !== hasMorphTargets) ||
(primitiveInfo.hasTangents !== hasTangents)) {
(primitiveInfo.hasNormals !== hasNormals) ||
(primitiveInfo.hasTangents !== hasTangents) ||
(primitiveInfo.hasTexCoords !== hasTexCoords)) {
// This primitive uses the same material as another one that either:
// * Isn't skinned
// * Uses a different type to store joints and weights
// * Doesn't have vertex colors, tangents, or morph targets
// * Doesn't have vertex colors, morph targets, normals, tangents, or texCoords
var clonedMaterial = clone(material, true);
clonedMaterial.extras._pipeline.skinning = {
clonedMaterial.extras._pipeline.primitive = {
skinning : {
skinned : isSkinned,
componentType : componentType,
type : type
},
hasVertexColors : hasVertexColors,
hasMorphTargets : hasMorphTargets,
hasTangents : hasTangents
hasNormals : hasNormals,
hasTangents : hasTangents,
hasTexCoords : hasTexCoords
};
// Split this off as a separate material
materialId = addToArray(materials, clonedMaterial);
Expand Down