Reputation: 563
For now I have three separate vertex buffers: 1. XYZ-buffer 2. NX,NY,NZ-buffer 3. UV-buffer
So this is 8 floats total. In future will add also tangent and bitangent info, so +6 floats.
Here's how I declare them for shader:
shaderProgram.vertexPositionAttribute = gl.getAttribLocation(shaderProgram, "aVertexPosition");
gl.enableVertexAttribArray(shaderProgram.vertexPositionAttribute);
shaderProgram.vertexNormalAttribute = gl.getAttribLocation(shaderProgram, "aVertexNormal");
gl.enableVertexAttribArray(shaderProgram.vertexNormalAttribute);
shaderProgram.textureCoordAttribute = gl.getAttribLocation(shaderProgram, "aTextureCoord");
gl.enableVertexAttribArray(shaderProgram.textureCoordAttribute);
Here I pass them to shader program:
gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexCoordBuffer);
gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, 3, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexNormalBuffer);
gl.vertexAttribPointer(shaderProgram.vertexNormalAttribute, 3, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexTextureCoordBuffer);
gl.vertexAttribPointer(shaderProgram.textureCoordAttribute, 2, gl.FLOAT, false, 0, 0);
Since buffers are separate I can define them as vec3 and vec2 in shader:
attribute vec3 aVertexPosition;
attribute vec3 aVertexNormal;
attribute vec2 aTextureCoord;
But what if I combine them to a single buffer with 8 floats per vertex? So, the item size will be 8:
gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexCoordBuffer);
gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, 8, gl.FLOAT, false, 0, 0);
But how do I access them in shader? vec8 ? There's maximum vec4! So how do I ?
Upvotes: 4
Views: 2206
Reputation: 43872
You can create a single buffer which holds all the attributes for each vertex, using the stride and offset parameters (which you have currently set to 0) to define an interleaving the attributes. In fact, I have heard you should do this to improve locality of memory access per vertex.
The stride is the total number of bytes per vertex (rather, the spacing between occurrences of the same attribute), and the offset is the byte index where the first occurrence of the particular attribute is. So, to take your example attributes and read them from a single buffer:
gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexAttrBuffer);
var step = Float32Array.BYTES_PER_ELEMENT;
var total = 3 + 3 + 2;
var stride = step * total;
gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, 3, gl.FLOAT, stride, 0);
gl.vertexAttribPointer(shaderProgram.vertexNormalAttribute, 3, gl.FLOAT, false, stride, step * 3);
gl.vertexAttribPointer(shaderProgram.textureCoordAttribute, 2, gl.FLOAT, false, stride, step * 6);
The buffer would be loaded from a Float32Array
whose elements go
[px1, py1, pz1, nx1, ny1, nz1, u1, v1,
px2, py2, pz2, nx2, ny2, nz2, u2, v2,
...]
Upvotes: 5
Reputation: 7781
Maximum is vec4, you're right, and only way for webGL. You might try passing arrays as attribute: GLSL per vertex fixed size array, but OpenGL ES 2.0 doesn't support it, so this option is available only in desktop OpenGL. But I don't see real need of doing that, so you will be okay with vec4 no matter what you do, and passing arrays attribute is something you probably shouldn't do.
Hope this helps.
Upvotes: 0