diff --git a/CHANGES.md b/CHANGES.md index d1fb853b1431..9a5e80931296 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,6 +1,11 @@ Change Log ========== +### 1.50 - 2018-10-01 + +##### Additions :tada: +* Added support for glTF extension [KHR_materials_unlit](https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_materials_unlit) [#6977](https://github.com/AnalyticalGraphicsInc/cesium/pull/6977). + ### 1.49 - 2018-09-04 ##### Breaking Changes :mega: @@ -15,7 +20,6 @@ Change Log * Added `GeocoderViewModel.destinationFound` for specifying a function that is called upon a successful geocode. The default behavior is to fly to the destination found by the geocoder. [#6915](https://github.com/AnalyticalGraphicsInc/cesium/pull/6915 * Added `ClippingPlaneCollection.planeAdded` and `ClippingPlaneCollection.planeRemoved` events. `planeAdded` is raised when a new plane is added to the collection and `planeRemoved` is raised when a plane is removed. [#6875](https://github.com/AnalyticalGraphicsInc/cesium/pull/6875) * Added `Matrix4.setScale` for setting the scale on an affine transformation matrix [#6888](https://github.com/AnalyticalGraphicsInc/cesium/pull/6888) -) * Added optional `width` and `height` to `Scene.drillPick` for specifying a search area. [#6922](https://github.com/AnalyticalGraphicsInc/cesium/pull/6922) * Added `Cesium3DTileset.root` for getting the root tile of a tileset. [#6944](https://github.com/AnalyticalGraphicsInc/cesium/pull/6944) * Added `Cesium3DTileset.extras` and `Cesium3DTile.extras` for getting application specific metadata from 3D Tiles. [#6974](https://github.com/AnalyticalGraphicsInc/cesium/pull/6974) diff --git a/Source/Scene/ModelUtility.js b/Source/Scene/ModelUtility.js index 1e61a1a63eb2..b63a5e02ce0a 100644 --- a/Source/Scene/ModelUtility.js +++ b/Source/Scene/ModelUtility.js @@ -473,7 +473,8 @@ define([ 'KHR_draco_mesh_compression' : true, 'KHR_materials_common' : true, 'KHR_techniques_webgl' : true, - 'WEB3D_quantized_attributes' : true + 'WEB3D_quantized_attributes' : true, + 'KHR_materials_unlit' : true }; ModelUtility.checkSupportedExtensions = function(extensionsRequired) { diff --git a/Source/Scene/processPbrMetallicRoughness.js b/Source/Scene/processPbrMetallicRoughness.js index 1d98bd9b35b2..745b13f64a16 100644 --- a/Source/Scene/processPbrMetallicRoughness.js +++ b/Source/Scene/processPbrMetallicRoughness.js @@ -143,6 +143,7 @@ define([ var hasNormals = false; var hasTangents = false; var hasTexCoords = false; + var isUnlit = false; if (defined(primitiveInfo)) { skinningInfo = primitiveInfo.skinning; @@ -181,6 +182,12 @@ define([ } }; + if (defined(material.extensions) && defined(material.extensions.KHR_materials_unlit)) { + isUnlit = true; + hasNormals = false; + hasTangents = false; + } + if (hasNormals) { techniqueUniforms.u_normalMatrix = { semantic : 'MODELVIEWINVERSETRANSPOSE', @@ -628,19 +635,21 @@ define([ fragmentShader += ' vec3 color = baseColor;\n'; } - if (defined(generatedMaterialValues.u_occlusionTexture)) { - fragmentShader += ' color *= texture2D(u_occlusionTexture, ' + v_texcoord + ').r;\n'; - } - if (defined(generatedMaterialValues.u_emissiveTexture)) { - fragmentShader += ' vec3 emissive = SRGBtoLINEAR3(texture2D(u_emissiveTexture, ' + v_texcoord + ').rgb);\n'; - if (defined(generatedMaterialValues.u_emissiveFactor)) { - fragmentShader += ' emissive *= u_emissiveFactor;\n'; + // Ignore occlusion and emissive when unlit + if (!isUnlit) { + if (defined(generatedMaterialValues.u_occlusionTexture)) { + fragmentShader += ' color *= texture2D(u_occlusionTexture, ' + v_texcoord + ').r;\n'; } - fragmentShader += ' color += emissive;\n'; - } - else if (defined(generatedMaterialValues.u_emissiveFactor)) { + if (defined(generatedMaterialValues.u_emissiveTexture)) { + fragmentShader += ' vec3 emissive = SRGBtoLINEAR3(texture2D(u_emissiveTexture, ' + v_texcoord + ').rgb);\n'; + if (defined(generatedMaterialValues.u_emissiveFactor)) { + fragmentShader += ' emissive *= u_emissiveFactor;\n'; + } + fragmentShader += ' color += emissive;\n'; + } else if (defined(generatedMaterialValues.u_emissiveFactor)) { fragmentShader += ' color += u_emissiveFactor;\n'; } + } // Final color fragmentShader += ' color = LINEARtoSRGB(color);\n'; diff --git a/Specs/Data/Models/PBR/BoxUnlit/BoxUnlit.gltf b/Specs/Data/Models/PBR/BoxUnlit/BoxUnlit.gltf new file mode 100644 index 000000000000..f4bda300552c --- /dev/null +++ b/Specs/Data/Models/PBR/BoxUnlit/BoxUnlit.gltf @@ -0,0 +1,151 @@ +{ + "asset": { + "generator": "COLLADA2GLTF", + "version": "2.0" + }, + "extensionsUsed": [ + "KHR_materials_unlit" + ], + "extensionsRequired": [ + "KHR_materials_unlit" + ], + "scene": 0, + "scenes": [ + { + "nodes": [ + 0 + ] + } + ], + "nodes": [ + { + "children": [ + 1 + ], + "matrix": [ + 1.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + -1.0, + 0.0, + 0.0, + 1.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 1.0 + ] + }, + { + "mesh": 0 + } + ], + "meshes": [ + { + "primitives": [ + { + "attributes": { + "NORMAL": 1, + "POSITION": 2 + }, + "indices": 0, + "mode": 4, + "material": 0 + } + ], + "name": "Mesh" + } + ], + "accessors": [ + { + "bufferView": 0, + "byteOffset": 0, + "componentType": 5123, + "count": 36, + "max": [ + 23 + ], + "min": [ + 0 + ], + "type": "SCALAR" + }, + { + "bufferView": 1, + "byteOffset": 0, + "componentType": 5126, + "count": 24, + "max": [ + 1.0, + 1.0, + 1.0 + ], + "min": [ + -1.0, + -1.0, + -1.0 + ], + "type": "VEC3" + }, + { + "bufferView": 1, + "byteOffset": 288, + "componentType": 5126, + "count": 24, + "max": [ + 0.5, + 0.5, + 0.5 + ], + "min": [ + -0.5, + -0.5, + -0.5 + ], + "type": "VEC3" + } + ], + "materials": [ + { + "pbrMetallicRoughness": { + "baseColorFactor": [ + 0.0, + 1.0, + 0.0, + 1.0 + ], + "metallicFactor": 1.0 + }, + "name": "Unlit Green", + "extensions": { + "KHR_materials_unlit": {} + } + } + ], + "bufferViews": [ + { + "buffer": 0, + "byteOffset": 576, + "byteLength": 72, + "target": 34963 + }, + { + "buffer": 0, + "byteOffset": 0, + "byteLength": 576, + "byteStride": 12, + "target": 34962 + } + ], + "buffers": [ + { + "byteLength": 648, + "uri": "data:application/octet-stream;base64,AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAvwAAAL8AAAA/AAAAPwAAAL8AAAA/AAAAvwAAAD8AAAA/AAAAPwAAAD8AAAA/AAAAPwAAAL8AAAA/AAAAvwAAAL8AAAA/AAAAPwAAAL8AAAC/AAAAvwAAAL8AAAC/AAAAPwAAAD8AAAA/AAAAPwAAAL8AAAA/AAAAPwAAAD8AAAC/AAAAPwAAAL8AAAC/AAAAvwAAAD8AAAA/AAAAPwAAAD8AAAA/AAAAvwAAAD8AAAC/AAAAPwAAAD8AAAC/AAAAvwAAAL8AAAA/AAAAvwAAAD8AAAA/AAAAvwAAAL8AAAC/AAAAvwAAAD8AAAC/AAAAvwAAAL8AAAC/AAAAvwAAAD8AAAC/AAAAPwAAAL8AAAC/AAAAPwAAAD8AAAC/AAABAAIAAwACAAEABAAFAAYABwAGAAUACAAJAAoACwAKAAkADAANAA4ADwAOAA0AEAARABIAEwASABEAFAAVABYAFwAWABUA" + } + ] +} diff --git a/Specs/Scene/ModelSpec.js b/Specs/Scene/ModelSpec.js index 43dd98bdd943..73b32b67f846 100644 --- a/Specs/Scene/ModelSpec.js +++ b/Specs/Scene/ModelSpec.js @@ -120,6 +120,7 @@ defineSuite([ var boomBoxUrl = './Data/Models/PBR/BoomBox/BoomBox.gltf'; var boxPbrUrl = './Data/Models/PBR/Box/Box.gltf'; + var boxPbrUnlitUrl = './Data/Models/PBR/BoxUnlit/BoxUnlit.gltf'; var boxAnimatedPbrUrl = './Data/Models/PBR/BoxAnimated/BoxAnimated.gltf'; var boxInterleavedPbrUrl = './Data/Models/PBR/BoxInterleaved/BoxInterleaved.gltf'; var riggedSimplePbrUrl = './Data/Models/PBR/RiggedSimple/RiggedSimple.gltf'; @@ -2693,6 +2694,21 @@ defineSuite([ }); }); + it('renders with the unlit extension', function() { + return loadModel(boxPbrUnlitUrl).then(function(model) { + model.show = true; + model.zoomTo(); + // We expect to see the base color when unlit + expect(scene).toRenderAndCall(function(rgba) { + expect(rgba[0]).toEqual(0); + expect(rgba[1]).toEqual(255); + expect(rgba[2]).toEqual(0); + }); + + primitives.remove(model); + }); + }); + it('silhouetteSupported', function() { expect(Model.silhouetteSupported(scene)).toBe(true); scene.context._stencilBits = 0;