Before r72 I was able to create a Line geometry without any vertex coloring by setting the Line material's vertexColors to THREE.NoColors) and later I would set it to THREE.VertexColors along with setting the Line geometry's colors array to a new array with one new THREE.Color for each vertex as well as setting the geometry's colorNeedUpdate flag. The next render call did respect this. Since r72 this doesn't seem to work anymore. Rendering fails with: [.WebGLRenderingContext-0x3ed1656ee000]GL ERROR :GL_INVALID_OPERATION : glDrawArrays: attempt to access out of range vertices in attribute 1
I looked into three.js and found the problem is very likely when the (now) LineSegment BufferGeometry is updated from its Geometry through BufferGeometry.updateFromObject: In copyColorsArray the new colors should be copied into the typed array of the attribute. However, this silently fails. The typed array has a length of zero and doesn't resize dynamically. Copying colors from the colors array doesn't have any effect and the colors attribute stays empty. I suspect this buffer is expected to have the correct size when used later on in the glDrawArrays() call.
Or is there anything that I missed in this updated that would re-initialize the typed array (like another flag or a call)?
Can you create a jsfiddle using r71 showing that doesn't work in r72? That'll help us to make it work again.
Sure, will do so later today.
On October 16, 2015 12:23:51 PM EDT, "Mr.doob" [email protected] wrote:
Can you create a jsfiddle using r71 showing that doesn't work in r72?
That'll help us to make it work again.
Reply to this email directly or view it on GitHub:
https://github.com/mrdoob/three.js/issues/7361#issuecomment-148759753
Alright, here are the jsFiddle examples. Both create a scene containing a simple two piece segmented line. The line is added with no vertex coloring. After the first rendering is done, the line's vertices are colored. This fails in r72 and r73 for the reason explained above.
Using vertex coloring already before the first render pass works (since the typed array is then initialized with the correct size). However, I need to do this dynamically, ideally without having to use vertex coloring (to initialize the typed vertex color array) if only one color is used.
A quick'n'dirty workaround would be adding this
geometry._bufferGeometry.addAttribute( "color", new THREE.BufferAttribute( new Float32Array( 4 * 3 ), 3 ) );
before geometry.colors = [...] in the fiddle.
Towards a solution: When creating the BufferGeometry attributes from the Geometry, we could initialize every attribute with the size of the position attribute as a default.
Since we have quite a few places where we change the colors attribute of Geometry, I used a more general workaround. This seems to work without problems for now:
(function() {
// Override THREE.Geometry to work around issue 7361
var originalGeometry = THREE.Geometry;
THREE.Geometry = function() {
// Call original constructor
originalGeometry.apply(this, arguments);
var colors = this.colors;
Object.defineProperty(this, "colors", {
get: function() {
return colors;
},
set: function(value) {
// Make sure the attribute has enough space
var nVertices = this.vertices.length;
if (this._bufferGeometry) {
if (nVertices !== this._bufferGeometry.attributes.color.count) {
this._bufferGeometry.addAttribute("color",
new THREE.BufferAttribute(new Float32Array(nVertices * 3), 3));
}
}
colors = value;
}});
};
THREE.Geometry.prototype = originalGeometry.prototype;
THREE.Geometry.constructor = originalGeometry.constructor;
})();
I just tested this again and dynamic vertex coloring is also not possible in r74, r75 and r76 without the workaround above.
Sorry this was overlooked...
I think this is known-behavior similar to https://github.com/mrdoob/three.js/issues/7179#issuecomment-144210254.
Add vertex colors at the start.
geometry = new THREE.Geometry();
geometry.colors = [ new THREE.Color(), new THREE.Color(), new THREE.Color(), new THREE.Color() ];
And then change the colors like so:
geometry.colors[ 0 ].setRGB( 1, 0, 0 );
...
geometry.colorsNeedUpdate = true;
material.vertexColors = THREE.VertexColors;
material.needsUpdate = true;
i have a try, if set color by face.color = new THREE.Color(Math.random() * 0xffffff); it doesnt work, but instead of face.color.copy(new THREE.Color(Math.random() * 0xffffff)) or face.color.set(new THREE.Color(Math.random() * 0xffffff)) it works!
@yangnianbing
Or simply face.color.set( Math.random() * 0xffffff )? :)
Most helpful comment
Sorry this was overlooked...
I think this is known-behavior similar to https://github.com/mrdoob/three.js/issues/7179#issuecomment-144210254.
Add vertex colors at the start.
And then change the colors like so: