diff --git a/CHANGES.md b/CHANGES.md index 4dacacc39149..6b01ad5ab2df 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -22,6 +22,7 @@ Change Log * Added `Transforms.localFrameToFixedFrameGenerator` to generate a function that computes a 4x4 transformation matrix from a local reference frame to fixed reference frame. * Fixed an issue where the camera would zoom past an object and flip to the other side of the globe. [#4967](https://github.com/AnalyticalGraphicsInc/cesium/pull/4967) and [#4982](https://github.com/AnalyticalGraphicsInc/cesium/pull/4982) * Fixed exception in 2D in certain cases with polylines when rotating the map. [#4619](https://github.com/AnalyticalGraphicsInc/cesium/issues/4619) +* Fixed an issue with constant `VertexArray` attributes not being set correctly. [#4995](https://github.com/AnalyticalGraphicsInc/cesium/pull/4995) ### 1.30 - 2017-02-01 diff --git a/Source/Renderer/VertexArray.js b/Source/Renderer/VertexArray.js index dff60ec1a532..a02d27dc7996 100644 --- a/Source/Renderer/VertexArray.js +++ b/Source/Renderer/VertexArray.js @@ -256,11 +256,11 @@ define([ * context : context, * attributes : attributes * }); - * + * * @see Buffer#createVertexBuffer * @see Buffer#createIndexBuffer * @see Context#draw - * + * * @private */ function VertexArray(options) { @@ -285,6 +285,7 @@ define([ var vaAttributes = []; var numberOfVertices = 1; // if every attribute is backed by a single value var hasInstancedAttributes = false; + var hasConstantAttributes = false; var length = attributes.length; for (i = 0; i < length; ++i) { @@ -306,7 +307,9 @@ define([ for (i = 0; i < length; ++i) { if (vaAttributes[i].instanceDivisor > 0) { hasInstancedAttributes = true; - break; + } + if (defined(vaAttributes[i].value)) { + hasConstantAttributes = true; } } @@ -334,6 +337,7 @@ define([ this._numberOfVertices = numberOfVertices; this._hasInstancedAttributes = hasInstancedAttributes; + this._hasConstantAttributes = hasConstantAttributes; this._context = context; this._gl = gl; this._vao = vao; @@ -515,7 +519,7 @@ define([ * // Example 3. When the caller destroys the vertex array, it also destroys the * // attached vertex buffer(s) and index buffer. * va = va.destroy(); - * + * * @see Buffer#createVertexBuffer * @see Buffer#createIndexBuffer * @see GeometryPipeline.createAttributeLocations @@ -714,12 +718,28 @@ define([ } } + // Vertex attributes backed by a constant value go through vertexAttrib[1234]f[v] + // which is part of context state rather than VAO state. + function setConstantAttributes(vertexArray, gl) { + var attributes = vertexArray._attributes; + var length = attributes.length; + for (var i = 0; i < length; ++i) { + var attribute = attributes[i]; + if (attribute.enabled && defined(attribute.value)) { + attribute.vertexAttrib(gl); + } + } + } + VertexArray.prototype._bind = function() { if (defined(this._vao)) { this._context.glBindVertexArray(this._vao); if (this._context.instancedArrays) { setVertexAttribDivisor(this); } + if (this._hasConstantAttributes) { + setConstantAttributes(this, this._gl); + } } else { bind(this._gl, this._attributes, this._indexBuffer); } diff --git a/Specs/Renderer/VertexArraySpec.js b/Specs/Renderer/VertexArraySpec.js index e0c9335525da..4c5cbbf05f40 100644 --- a/Specs/Renderer/VertexArraySpec.js +++ b/Specs/Renderer/VertexArraySpec.js @@ -429,6 +429,82 @@ defineSuite([ va = va.destroy(); }); + it('renders two vertex arrays with constant values', function() { + var vs = + 'attribute float firefoxWorkaround;' + + 'attribute vec4 attr;' + + 'varying vec4 v_color;' + + 'void main() { ' + + ' v_color = attr + vec4(firefoxWorkaround);' + + ' gl_PointSize = 1.0;' + + ' gl_Position = vec4(0.0, 0.0, 0.0, 1.0);' + + '}'; + + var fs = + 'varying vec4 v_color;' + + 'void main() { gl_FragColor = v_color; }'; + + var sp = ShaderProgram.fromCache({ + context : context, + vertexShaderSource : vs, + fragmentShaderSource : fs, + attributeLocations : { + firefoxWorkaround : 0, + attr : 1 + } + }); + + var vertexBuffer = Buffer.createVertexBuffer({ + context : context, + sizeInBytes : Float32Array.BYTES_PER_ELEMENT, + usage : BufferUsage.STATIC_DRAW + }); + + var vaRed = new VertexArray({ + context : context, + attributes : [{ + vertexBuffer : vertexBuffer, + componentsPerAttribute : 1 + }, { + value : [1, 0, 0, 1] + }] + }); + + var vaGreen = new VertexArray({ + context : context, + attributes : [{ + vertexBuffer : vertexBuffer, + componentsPerAttribute : 1 + }, { + value : [0, 1, 0, 1] + }] + }); + + var commandRed = new DrawCommand({ + primitiveType : PrimitiveType.POINTS, + shaderProgram : sp, + vertexArray : vaRed, + count : 1 + }); + + var commandGreen = new DrawCommand({ + primitiveType : PrimitiveType.POINTS, + shaderProgram : sp, + vertexArray : vaGreen, + count : 1 + }); + + commandRed.execute(context); + expect(context).toReadPixels([255, 0, 0, 255]); + + commandGreen.execute(context); + expect(context).toReadPixels([0, 255, 0, 255]); + + sp = sp.destroy(); + vaRed = vaRed.destroy(); + vaGreen = vaGreen.destroy(); + }); + it('destroys', function() { var va = new VertexArray({ context : context,