# Rendering same vertex-array in different modes

here is my vertex array I am using:

vertices = [
-1.0,  1.0,  0.0,
0.0,  1.0,  0.0,
-0.5,  1.0,  0.0,
0.5,  1.0,  0.0,
1.0,  1.0,  0.0,
1.0,  0.5,  0.0,
0.0,  0.5,  0.0,
0.5,  0.5,  0.0,
-0.5,  0.5,  0.0,
-1.0,  0.5,  0.0,

-1.0,  0.0,  0.0,
-0.5,  0.0,  0.0,
0.0,  0.0,  0.0,
0.5,  0.0,  0.0,
1.0,  0.0,  0.0,

-1.0, -0.5,  0.0,
0.0, -0.5,  0.0,
-0.5, -0.5,  0.0,
0.5, -0.5,  0.0,
1.0, -0.5,  0.0,
1.0, -1.0,  0.0,
0.0, -1.0,  0.0,
0.5, -1.0,  0.0,
-0.5, -1.0,  0.0,
-1.0, -1.0,  0.0,
];

In a html-select I want to select a rendering mode and use it inmy drawScene-method:

var renderModeSelector = document.getElementById("renderModeDropDown");
var selectedRenderModeValue = renderModeSelector.options[renderModeSelector.selectedIndex].value;

switch (selectedRenderModeValue) {
case "0":
gl.drawArrays(gl.POINTS, 0, squareVertexPositionBuffer.numItems);
break;
case "1":
gl.drawArrays(gl.TRIANGLE_FAN, 0, squareVertexPositionBuffer.numItems);
break;
case "2":
gl.drawArrays(gl.LINE_LOOP, 0, squareVertexPositionBuffer.numItems);
break;
default:
console.log("No rendering mode selected.");
}
1. Case '0' is supposed to draw the points which works fine

2. Case '1' should draw a filled rectangle, with the shader below. Unfortunately it is messed up, see also in the picture below.

precision mediump float;

varying vec4 vColor;

void main(void) {
gl_FragColor = vColor;
}

attribute vec3 aVertexPosition;
attribute vec4 aVertexColor;

uniform mat4 uMVMatrix;
uniform mat4 uPMatrix;

varying vec4 vColor;

void main(void) {
gl_Position = uPMatrix * uMVMatrix * vec4(aVertexPosition, 1.0);
vColor = aVertexColor;
gl_PointSize = 5.0;
}

3. And finally in case '2' it is supposed to draw only the outlines, which also does not work as expected, see below.

So I wonder if it is possible to meet my requirements while using one vertexPositionBuffer. Should I maybe create another vertexPositionBuffer or can I just change mine "on the fly", before rendering?

• You need only 4 vertices for all cases. 1:- You could easily use nested for loops to draw the case 0. You could get 4 end points by simple maths and then draw lines and triangles between them for case 1, case 2 respectively. 2:- Or you can have the end points and then divide them up for case 0. I would probably do the latter. – A---B Jul 11 '16 at 19:08
• Your data is off. You do not account for winding rules. – joojaa Jul 11 '16 at 20:00
• @ritwiksinha Yeah the thing is I want it to be that many vertices. – チーズパン Jul 12 '16 at 7:19
• @joojaa What do you mean by "data is off"? I know some of the points are not in the right order I changed that, It does not fix the issue. – チーズパン Jul 12 '16 at 7:21
• @Käsebrot Why don't you use section formula to calculate the points in between the 4 vertices, namely $(1, 1), (-1, 1), (-1, -1), (1, -1)$ – A---B Jul 12 '16 at 9:00

Your shaders are fine, the problem is topological, that is the way the vertices are connected to create triangles.

For cases 1 & 2: You cannot really draw a grid of points in this mode (GL_TRIANGLE_FAN) as vertex 0 (the top left one) will be used in every triangle, as well as other issues. You should be using Triangle/Line strips, although these aren't so straightforward as some vertices are shared between each row.

For example, imagine you have vertices arranged like so:

0 1 2

3 4 5

6 7 8

You would draw strips by sending the above vertices in the following order:

0,3,1 (outputs triangle 0,1,3)

4, (outputs triangle 1,3,4)

2, (outputs triangle 1,2,4)

etc...

This you can do in code by scanning across 1 row of vertices and including the vertex on the next row for every other vertex.

e.g.

int numColumns = 5;   // As per your example..
int numRows = 5;
int vertexOffset = 0;
int vertexSize = 3;          // 3 floats per vertex
int nextRow = numColumns * vertexSize;

// This loop is for each row-strip, which requires 2 vertex rows..
for(int j = 0; j < numRows - 1; j++) {

// Inner loop sends vertices for each row-strip
for(int n = 0; n < numColumns; n++, vertexOffset += vertexSize) {
glVertex3fv(vertices + vertexOffset);            // Current row
glVertex3fv(vertices + vertexOffset + nextRow);  // Row below
}
// This is special, we send a duplicate vertex to restart a new strip for the next row (This can be omitted if j == numRows - 1)
glVertex3fv(vertices + vertexOffset - vertexSize + nextRow);
}

If you are concerned about sending duplicate vertices you could use an additional index buffer, as that will allow you to use the exact same vertex buffer you used for the GL_POINTS version.

• I've made some minor edits, and edited the code to match. Hopefully this leaves the answer as you intended it but feel free to revert anything that doesn't. – trichoplax Aug 2 '16 at 12:47