From 1a4b221a1bdf27798953a529136c036a003d9e72 Mon Sep 17 00:00:00 2001 From: Sean Lilley Date: Thu, 18 May 2017 20:27:29 -0400 Subject: [PATCH 1/2] Fix issue with transparent diffuse texture setting the technique state --- lib/addDefaults.js | 67 ++++++++++++++++++++++++++---------- specs/lib/addDefaultsSpec.js | 40 ++++++++++++++++++--- 2 files changed, 84 insertions(+), 23 deletions(-) diff --git a/lib/addDefaults.js b/lib/addDefaults.js index bc246a73..63e90227 100644 --- a/lib/addDefaults.js +++ b/lib/addDefaults.js @@ -347,6 +347,42 @@ function addDefaultTechnique(gltf) { } } +function isTechniqueShared(gltf, techniqueId) { + var users = 0; + var materials = gltf.materials; + for (var materialId in materials) { + if (materials.hasOwnProperty(materialId)) { + var material = materials[materialId]; + if (material.technique === techniqueId) { + ++users; + } + } + } + return users > 1; +} + +function makeTechniqueTransparent(technique) { + technique.states = { + enable: [ + WebGLConstants.DEPTH_TEST, + WebGLConstants.BLEND + ], + depthMask: false, + functions: { + blendEquationSeparate: [ + WebGLConstants.FUNC_ADD, + WebGLConstants.FUNC_ADD + ], + blendFuncSeparate: [ + WebGLConstants.ONE, + WebGLConstants.ONE_MINUS_SRC_ALPHA, + WebGLConstants.ONE, + WebGLConstants.ONE_MINUS_SRC_ALPHA + ] + } + }; +} + function enableDiffuseTransparency(gltf) { var materials = gltf.materials; var techniques = gltf.techniques; @@ -364,30 +400,23 @@ function enableDiffuseTransparency(gltf) { diffuseTransparent = diffuse[3] < 1.0; } - var technique = techniques[material.technique]; + var techniqueId = material.technique; + var technique = techniques[techniqueId]; var blendingEnabled = technique.states.enable.indexOf(WebGLConstants.BLEND) > -1; // Override the technique's states if blending isn't already enabled if (diffuseTransparent && !blendingEnabled) { - technique.states = { - enable: [ - WebGLConstants.DEPTH_TEST, - WebGLConstants.BLEND - ], - depthMask: false, - functions: { - blendEquationSeparate: [ - WebGLConstants.FUNC_ADD, - WebGLConstants.FUNC_ADD - ], - blendFuncSeparate: [ - WebGLConstants.ONE, - WebGLConstants.ONE_MINUS_SRC_ALPHA, - WebGLConstants.ONE, - WebGLConstants.ONE_MINUS_SRC_ALPHA - ] + if (isTechniqueShared(gltf, techniqueId)) { + var transparentTechniqueId = techniqueId + '_transparent'; + if (!defined(techniques[transparentTechniqueId])) { + technique = clone(technique, true); + makeTechniqueTransparent(technique); + gltf.techniques[transparentTechniqueId] = technique; } - }; + material.technique = transparentTechniqueId; + } else { + makeTechniqueTransparent(technique); + } } } } diff --git a/specs/lib/addDefaultsSpec.js b/specs/lib/addDefaultsSpec.js index 93113164..8cffe522 100644 --- a/specs/lib/addDefaultsSpec.js +++ b/specs/lib/addDefaultsSpec.js @@ -14,7 +14,8 @@ var removePipelineExtras = require('../../lib/removePipelineExtras'); var fsReadFile = Promise.promisify(fs.readFile); -var transparentImageUri = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAYAAADED76LAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAA7DAAAOwwHHb6hkAAAAB3RJTUUH4AcGERIfpcOGjwAAAQZJREFUGNMFwcErQ3EAwPHv7+3JEw2FFe+lZ9vpTTnYiR2MsyKuE8VB/ojdlZuDg4sVyUU7TVK7KG05jFgWPdt6oqWI5/E87/l8RNO8zyoylF4EtTeB6wWMhH2mNMG3B3KHDMemxOFdQEj4qN3tPDoS9Q+HxaiPdNkS5G5+SUV1xoYG6VNcRvvh9ClMS+hIZ6aLocZY0M+Zj1X59CMcXXmsJUO4dh7Z0HTiEZvN3DQDvcNk5mrYyU5q5SUK1QuktGpxkE/x8OpSaVqUSxt81bfYKewxkVhF9h1BjxJHyBW84I/dk23ebVieWWF2fB1hNZ6zSlsXxdt9rhtFgsDH0CZJJzK43g//gYBjzrZ4jf0AAAAASUVORK5CYII='; +var opaqueImageUri = './specs/data/boxTexturedUnoptimized/Cesium_Logo_Flat.jpg'; +var transparentImageUri = './specs/data/boxTexturedUnoptimized/Cesium_Logo_Flat_Transparent.png'; var gltfTransparentPath = './specs/data/boxTexturedUnoptimized/CesiumTexturedBoxTestTransparent.gltf'; describe('addDefaults', function() { @@ -157,6 +158,13 @@ describe('addDefaults', function() { } }; + var opaqueBlendState = { + enable : [ + WebGLConstants.CULL_FACE, + WebGLConstants.DEPTH_TEST + ] + }; + it('generates a material with alpha blending if the diffuse texture is transparent and no technique or extension values are given', function(done) { var gltf = { "textures": { @@ -167,12 +175,24 @@ describe('addDefaults', function() { "source": "Image0001", "target": 3553, "type": 5121 + }, + "texture0002": { + "format": 6408, + "internalFormat": 6408, + "sampler": "sampler_0", + "source": "Image0002", + "target": 3553, + "type": 5121 } }, "images": { "Image0001": { "name": "Image0001", "uri": transparentImageUri + }, + "Image0002": { + "name": "Image0002", + "uri": opaqueImageUri } }, "materials": { @@ -182,16 +202,28 @@ describe('addDefaults', function() { "diffuse": "texture0001", "emission": [1, 0, 0, 1] } + }, + "material2": { + "values": { + "ambient": [0, 0, 0, 1], + "diffuse": "texture0002", + "emission": [1, 0, 0, 1] + } } } }; + var options = { + basePath : './' + }; addPipelineExtras(gltf); - expect(loadGltfUris(gltf) + expect(loadGltfUris(gltf, options) .then(function() { addDefaults(gltf); - var technique = gltf.techniques[Object.keys(gltf.techniques)[0]]; - expect(technique.states).toEqual(alphaBlendState); + var techniqueOpaque = gltf.techniques[Object.keys(gltf.techniques)[0]]; + var techniqueAlpha = gltf.techniques[Object.keys(gltf.techniques)[1]]; + expect(techniqueAlpha.states).toEqual(alphaBlendState); + expect(techniqueOpaque.states).toEqual(opaqueBlendState); }), done).toResolve(); }); From 883c4ab1e0ad64ea2a54f8e518f03a0711893cf8 Mon Sep 17 00:00:00 2001 From: Sean Lilley Date: Mon, 22 May 2017 10:14:18 -0400 Subject: [PATCH 2/2] Tweaks --- lib/addDefaults.js | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/lib/addDefaults.js b/lib/addDefaults.js index 63e90227..3d738d20 100644 --- a/lib/addDefaults.js +++ b/lib/addDefaults.js @@ -348,17 +348,20 @@ function addDefaultTechnique(gltf) { } function isTechniqueShared(gltf, techniqueId) { - var users = 0; + var referenced = false; var materials = gltf.materials; for (var materialId in materials) { if (materials.hasOwnProperty(materialId)) { var material = materials[materialId]; if (material.technique === techniqueId) { - ++users; + if (referenced) { + return true; + } + referenced = true; } } } - return users > 1; + return false; } function makeTechniqueTransparent(technique) {