From 077e225ff1f9e50c1874fcbf1ab69bc7d2f4c095 Mon Sep 17 00:00:00 2001 From: Sean Lilley Date: Mon, 12 Dec 2016 14:23:41 -0500 Subject: [PATCH] Added tests --- Source/Scene/Model.js | 4 +- Specs/Scene/ModelSpec.js | 130 ++++++++++++++++++++++++++++++++++++++- Specs/createScene.js | 1 + 3 files changed, 132 insertions(+), 3 deletions(-) diff --git a/Source/Scene/Model.js b/Source/Scene/Model.js index 7fe5ccc1dd75..e620037690f2 100644 --- a/Source/Scene/Model.js +++ b/Source/Scene/Model.js @@ -3614,7 +3614,7 @@ define([ 'void main() \n' + '{ \n' + ' gltf_silhouette_main(); \n' + - ' vec3 n = normalize(czm_normal * ' + normalAttributeName + '); \n' + + ' vec3 n = normalize(czm_normal3D * ' + normalAttributeName + '); \n' + ' n.x *= czm_projection[0][0]; \n' + ' n.y *= czm_projection[1][1]; \n' + ' vec4 clip = gl_Position; \n' + @@ -3647,7 +3647,7 @@ define([ for (var i = 0; i < length; ++i) { var nodeCommand = nodeCommands[i]; var command = nodeCommand.command; - if (command.renderState.blending.enabled) { + if (command.pass === Pass.TRANSLUCENT) { return true; } } diff --git a/Specs/Scene/ModelSpec.js b/Specs/Scene/ModelSpec.js index 5c484eee2b8d..5c56d9c4c468 100644 --- a/Specs/Scene/ModelSpec.js +++ b/Specs/Scene/ModelSpec.js @@ -28,6 +28,7 @@ defineSuite([ 'Renderer/WebGLConstants', 'Scene/ColorBlendMode', 'Scene/HeightReference', + 'Scene/Pass', 'Scene/ModelAnimationLoop', 'Specs/createScene', 'Specs/pollToPromise', @@ -61,6 +62,7 @@ defineSuite([ WebGLConstants, ColorBlendMode, HeightReference, + Pass, ModelAnimationLoop, createScene, pollToPromise, @@ -237,7 +239,9 @@ defineSuite([ expect(texturedBoxModel.distanceDisplayCondition).toBeUndefined(); expect(texturedBoxModel.silhouetteColor).toEqual(Color.RED); expect(texturedBoxModel.silhouetteSize).toEqual(0.0); - + expect(texturedBoxModel.color).toEqual(Color.WHITE); + expect(texturedBoxModel.colorBlendMode).toEqual(ColorBlendMode.HIGHLIGHT); + expect(texturedBoxModel.colorBlendAmount).toEqual(0.5); }); it('renders', function() { @@ -1934,6 +1938,130 @@ defineSuite([ }); }); + it('silhouetteSupported', function() { + expect(Model.silhouetteSupported(scene)).toBe(true); + scene.context._stencilBits = 0; + expect(Model.silhouetteSupported(scene)).toBe(false); + scene.context._stencilBits = 8; + }); + + it('renders with a silhouette', function() { + return loadModel(boxUrl).then(function(model) { + model.show = true; + model.zoomTo(); + + var commands = scene.frameState.commandList; + + // No silhouette + model.silhouetteSize = 0.0; + scene.renderForSpecs(); + expect(commands.length).toBe(1); + expect(commands[0].renderState.stencilTest.enabled).toBe(false); + expect(commands[0].pass).toBe(Pass.OPAQUE); + + // Opaque silhouette + model.silhouetteSize = 1.0; + scene.renderForSpecs(); + expect(commands.length).toBe(2); + expect(commands[0].renderState.stencilTest.enabled).toBe(true); + expect(commands[0].pass).toBe(Pass.OPAQUE); + expect(commands[1].renderState.stencilTest.enabled).toBe(true); + expect(commands[1].pass).toBe(Pass.OPAQUE); + + // Translucent silhouette + model.silhouetteColor = Color.fromAlpha(Color.GREEN, 0.5); + scene.renderForSpecs(); + expect(commands.length).toBe(2); + expect(commands[0].renderState.stencilTest.enabled).toBe(true); + expect(commands[0].pass).toBe(Pass.OPAQUE); + expect(commands[1].renderState.stencilTest.enabled).toBe(true); + expect(commands[1].pass).toBe(Pass.TRANSLUCENT); + + // Invisible silhouette. The model is rendered normally. + model.silhouetteColor = Color.fromAlpha(Color.GREEN, 0.0); + scene.renderForSpecs(); + expect(commands.length).toBe(1); + expect(commands[0].renderState.stencilTest.enabled).toBe(false); + expect(commands[0].pass).toBe(Pass.OPAQUE); + + // Invisible model with no silhouette. No commands. + model.color = Color.fromAlpha(Color.WHITE, 0.0); + model.silhouetteColor = Color.GREEN; + model.silhouetteSize = 0.0; + scene.renderForSpecs(); + expect(commands.length).toBe(0); + + // Invisible model with silhouette. Model command is stencil-only. + model.silhouetteSize = 1.0; + scene.renderForSpecs(); + expect(commands.length).toBe(2); + expect(commands[0].renderState.colorMask).toEqual({ + red : false, + green : false, + blue : false, + alpha : false + }); + expect(commands[0].renderState.depthMask).toEqual(false); + expect(commands[0].renderState.stencilTest.enabled).toBe(true); + expect(commands[0].pass).toBe(Pass.OPAQUE); + expect(commands[1].renderState.stencilTest.enabled).toBe(true); + expect(commands[1].pass).toBe(Pass.OPAQUE); + + // Translucent model with opaque silhouette. Silhouette is placed in the translucent pass. + model.color = Color.fromAlpha(Color.WHITE, 0.5); + scene.renderForSpecs(); + expect(commands.length).toBe(2); + expect(commands[0].renderState.stencilTest.enabled).toBe(true); + expect(commands[0].pass).toBe(Pass.TRANSLUCENT); + expect(commands[1].renderState.stencilTest.enabled).toBe(true); + expect(commands[1].pass).toBe(Pass.TRANSLUCENT); + + // Model with translucent commands with silhouette + model.color = Color.WHITE; + model._nodeCommands[0].command.pass = Pass.TRANSLUCENT; + scene.renderForSpecs(); + expect(commands.length).toBe(2); + expect(commands[0].renderState.stencilTest.enabled).toBe(true); + expect(commands[0].pass).toBe(Pass.TRANSLUCENT); + expect(commands[1].renderState.stencilTest.enabled).toBe(true); + expect(commands[1].pass).toBe(Pass.TRANSLUCENT); + model._nodeCommands[0].command.pass = Pass.OPAQUE; // Revert change + + // Translucent model with translucent silhouette. + model.color = Color.fromAlpha(Color.WHITE, 0.5); + model.silhouetteColor = Color.fromAlpha(Color.GREEN, 0.5); + scene.renderForSpecs(); + expect(commands.length).toBe(2); + expect(commands[0].renderState.stencilTest.enabled).toBe(true); + expect(commands[0].pass).toBe(Pass.TRANSLUCENT); + expect(commands[1].renderState.stencilTest.enabled).toBe(true); + expect(commands[1].pass).toBe(Pass.TRANSLUCENT); + + model.color = Color.WHITE; + model.silhouetteColor = Color.GREEN; + + // Load a second model + return loadModel(boxUrl).then(function(model) { + model.show = true; + model.silhouetteSize = 1.0; + scene.renderForSpecs(); + expect(commands.length).toBe(4); + expect(commands[0].renderState.stencilTest.enabled).toBe(true); + expect(commands[0].pass).toBe(Pass.OPAQUE); + expect(commands[1].renderState.stencilTest.enabled).toBe(true); + expect(commands[1].pass).toBe(Pass.OPAQUE); + expect(commands[2].renderState.stencilTest.enabled).toBe(true); + expect(commands[2].pass).toBe(Pass.OPAQUE); + expect(commands[3].renderState.stencilTest.enabled).toBe(true); + expect(commands[3].pass).toBe(Pass.OPAQUE); + + var reference1 = commands[0].renderState.stencilTest.reference; + var reference2 = commands[2].renderState.stencilTest.reference; + expect(reference2).toEqual(reference1 + 1); + }); + }); + }); + describe('height referenced model', function() { function createMockGlobe() { var globe = { diff --git a/Specs/createScene.js b/Specs/createScene.js index bbb1d7e7009f..6b070ae6772a 100644 --- a/Specs/createScene.js +++ b/Specs/createScene.js @@ -32,6 +32,7 @@ define([ var contextOptions = options.contextOptions; contextOptions.webgl = defaultValue(contextOptions.webgl, {}); contextOptions.webgl.antialias = defaultValue(contextOptions.webgl.antialias, false); + contextOptions.webgl.stencil = defaultValue(contextOptions.webgl.stencil, true); var scene = new Scene(options);