diff --git a/Source/Scene/CustomSensorVolume.js b/Source/Scene/CustomSensorVolume.js index 9656ad2d9c2a..f857d19ac8d4 100644 --- a/Source/Scene/CustomSensorVolume.js +++ b/Source/Scene/CustomSensorVolume.js @@ -16,6 +16,7 @@ define([ '../Renderer/CommandLists', '../Renderer/DrawCommand', '../Renderer/createPickFragmentShaderSource', + '../Renderer/CullFace', './Material', '../Shaders/SensorVolume', '../Shaders/CustomSensorVolumeVS', @@ -38,6 +39,7 @@ define([ CommandLists, DrawCommand, createPickFragmentShaderSource, + CullFace, Material, ShadersSensorVolume, CustomSensorVolumeVS, @@ -64,14 +66,22 @@ define([ this._pickId = undefined; this._pickIdThis = defaultValue(options._pickIdThis, this); - this._colorCommand = new DrawCommand(); - this._colorCommand.owner = this; + this._frontFaceColorCommand = new DrawCommand(); + this._backFaceColorCommand = new DrawCommand(); this._pickCommand = new DrawCommand(); - this._pickCommand.owner = this; this._commandLists = new CommandLists(); - this._colorCommand.primitiveType = this._pickCommand.primitiveType = PrimitiveType.TRIANGLES; - this._colorCommand.boundingVolume = this._pickCommand.boundingVolume = new BoundingSphere(); + this._frontFaceColorCommand.primitiveType = PrimitiveType.TRIANGLES; + this._frontFaceColorCommand.boundingVolume = new BoundingSphere(); + this._frontFaceColorCommand.owner = this; + + this._backFaceColorCommand.primitiveType = this._frontFaceColorCommand.primitiveType; + this._backFaceColorCommand.boundingVolume = this._frontFaceColorCommand.boundingVolume; + this._backFaceColorCommand.owner = this; + + this._pickCommand.primitiveType = this._frontFaceColorCommand.primitiveType; + this._pickCommand.boundingVolume = this._frontFaceColorCommand.boundingVolume; + this._pickCommand.owner = this; /** * true if this sensor will be shown; otherwise, false @@ -209,6 +219,9 @@ define([ }, u_intersectionWidth : function() { return that.intersectionWidth; + }, + u_normalDirection : function() { + return 1.0; } }; @@ -264,7 +277,7 @@ define([ boundingVolumePositions.push(p); } - BoundingSphere.fromPoints(boundingVolumePositions, customSensorVolume._colorCommand.boundingVolume); + BoundingSphere.fromPoints(boundingVolumePositions, customSensorVolume._frontFaceColorCommand.boundingVolume); return positions; } @@ -348,7 +361,7 @@ define([ } // Initial render state creation - if ((this._showThroughEllipsoid !== this.showThroughEllipsoid) || (typeof this._colorCommand.renderState === 'undefined')) { + if ((this._showThroughEllipsoid !== this.showThroughEllipsoid) || (typeof this._frontFaceColorCommand.renderState === 'undefined')) { this._showThroughEllipsoid = this.showThroughEllipsoid; var rs = context.createRenderState({ @@ -359,10 +372,42 @@ define([ enabled : !this.showThroughEllipsoid }, depthMask : false, - blending : BlendingState.ALPHA_BLEND + blending : BlendingState.ALPHA_BLEND, + cull : { + enabled : true, + face : CullFace.BACK + } + }); + + this._frontFaceColorCommand.renderState = rs; + + rs = context.createRenderState({ + depthTest : { + // This would be better served by depth testing with a depth buffer that does not + // include the ellipsoid depth - or a g-buffer containing an ellipsoid mask + // so we can selectively depth test. + enabled : !this.showThroughEllipsoid + }, + depthMask : false, + blending : BlendingState.ALPHA_BLEND, + cull : { + enabled : true, + face : CullFace.FRONT + } }); - this._colorCommand.renderState = rs; + this._backFaceColorCommand.renderState = rs; + + rs = context.createRenderState({ + depthTest : { + // This would be better served by depth testing with a depth buffer that does not + // include the ellipsoid depth - or a g-buffer containing an ellipsoid mask + // so we can selectively depth test. + enabled : !this.showThroughEllipsoid + }, + depthMask : false, + blending : BlendingState.ALPHA_BLEND + }); this._pickCommand.renderState = rs; } @@ -374,26 +419,32 @@ define([ var directions = this._directions; if (directions && (directions.length >= 3)) { - this._colorCommand.vertexArray = this._pickCommand.vertexArray = createVertexArray(this, context); + this._frontFaceColorCommand.vertexArray = createVertexArray(this, context); + this._backFaceColorCommand.vertexArray = this._frontFaceColorCommand.vertexArray; + this._pickCommand.vertexArray = this._frontFaceColorCommand.vertexArray; } } - if (typeof this._colorCommand.vertexArray === 'undefined') { + if (typeof this._frontFaceColorCommand.vertexArray === 'undefined') { return; } var pass = frameState.passes; - this._colorCommand.modelMatrix = this._pickCommand.modelMatrix = this.modelMatrix; this._commandLists.removeAll(); + this._frontFaceColorCommand.modelMatrix = this.modelMatrix; + this._backFaceColorCommand.modelMatrix = this._frontFaceColorCommand.modelMatrix; + this._pickCommand.modelMatrix = this._frontFaceColorCommand.modelMatrix; + var materialChanged = this._material !== this.material; this._material = this.material; if (pass.color) { - var colorCommand = this._colorCommand; + var frontFaceColorCommand = this._frontFaceColorCommand; + var backFaceColorCommand = this._backFaceColorCommand; // Recompile shader when material changes - if (materialChanged || typeof colorCommand.shaderProgram === 'undefined') { + if (materialChanged || typeof frontFaceColorCommand.shaderProgram === 'undefined') { var fsSource = '#line 0\n' + ShadersSensorVolume + @@ -402,12 +453,19 @@ define([ '#line 0\n' + CustomSensorVolumeFS; - colorCommand.shaderProgram = context.getShaderCache().replaceShaderProgram( - colorCommand.shaderProgram, CustomSensorVolumeVS, fsSource, attributeIndices); - colorCommand.uniformMap = combine([this._uniforms, this._material._uniforms], false, false); + frontFaceColorCommand.shaderProgram = context.getShaderCache().replaceShaderProgram( + frontFaceColorCommand.shaderProgram, CustomSensorVolumeVS, fsSource, attributeIndices); + frontFaceColorCommand.uniformMap = combine([this._uniforms, this._material._uniforms], false, false); + + backFaceColorCommand.shaderProgram = frontFaceColorCommand.shaderProgram; + backFaceColorCommand.uniformMap = combine([this._uniforms, this._material._uniforms], false, false); + backFaceColorCommand.uniformMap.u_normalDirection = function() { + return -1.0; + }; } - this._commandLists.colorList.push(colorCommand); + this._commandLists.colorList.push(backFaceColorCommand); + this._commandLists.colorList.push(frontFaceColorCommand); } if (pass.pick) { @@ -459,8 +517,8 @@ define([ * @memberof CustomSensorVolume */ CustomSensorVolume.prototype.destroy = function() { - this._colorCommand.vertexArray = this._colorCommand.vertexArray && this._colorCommand.vertexArray.destroy(); - this._colorCommand.shaderProgram = this._colorCommand.shaderProgram && this._colorCommand.shaderProgram.release(); + this._frontFaceColorCommand.vertexArray = this._frontFaceColorCommand.vertexArray && this._frontFaceColorCommand.vertexArray.destroy(); + this._frontFaceColorCommand.shaderProgram = this._frontFaceColorCommand.shaderProgram && this._frontFaceColorCommand.shaderProgram.release(); this._pickCommand.shaderProgram = this._pickCommand.shaderProgram && this._pickCommand.shaderProgram.release(); this._pickId = this._pickId && this._pickId.destroy(); return destroyObject(this); diff --git a/Source/Shaders/CustomSensorVolumeFS.glsl b/Source/Shaders/CustomSensorVolumeFS.glsl index f08c85853295..59ae691b48ba 100644 --- a/Source/Shaders/CustomSensorVolumeFS.glsl +++ b/Source/Shaders/CustomSensorVolumeFS.glsl @@ -6,6 +6,7 @@ uniform bool u_showIntersection; uniform bool u_showThroughEllipsoid; uniform float u_sensorRadius; +uniform float u_normalDirection; varying vec3 v_positionWC; varying vec3 v_positionEC; @@ -23,11 +24,10 @@ vec4 getColor(float sensorRadius, vec3 pointEC) materialInput.positionToEyeEC = positionToEyeEC; vec3 normalEC = normalize(v_normalEC); - normalEC = mix(normalEC, -normalEC, step(normalEC.z, 0.0)); // Normal facing viewer - materialInput.normalEC = normalEC; + materialInput.normalEC = u_normalDirection * normalEC; czm_material material = czm_getMaterial(materialInput); - return czm_phong(normalize(positionToEyeEC), material); + return mix(czm_phong(normalize(positionToEyeEC), material), vec4(material.diffuse, material.alpha), 0.4); } bool isOnBoundary(float value, float epsilon)