4
$\begingroup$

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

    enter image description here

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

    Fragment shader:

    precision mediump float;
    
    varying vec4 vColor;
    
    void main(void) {
    gl_FragColor = vColor;
    }
    

    Vertex-shader:

    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;
    }
    

    enter image description here

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

    enter image description here

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?

$\endgroup$
6
  • $\begingroup$ 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. $\endgroup$
    – user3437
    Jul 11, 2016 at 19:08
  • 2
    $\begingroup$ Your data is off. You do not account for winding rules. $\endgroup$
    – joojaa
    Jul 11, 2016 at 20:00
  • $\begingroup$ @ritwiksinha Yeah the thing is I want it to be that many vertices. $\endgroup$ Jul 12, 2016 at 7:19
  • $\begingroup$ @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. $\endgroup$ Jul 12, 2016 at 7:21
  • $\begingroup$ @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)$ $\endgroup$
    – user3437
    Jul 12, 2016 at 9:00

1 Answer 1

4
+50
$\begingroup$

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.

$\endgroup$
1
  • $\begingroup$ 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. $\endgroup$ Aug 2, 2016 at 12:47

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.