1
votes

As I did not find success in drawing multiple triangles with different matrices for each, for now I am stuck with transforming vertices on CPU and use a shader without matrix transformation..

Help will be greatly appreciated !

Here is my current shader :

    attribute vec2 vertices;
    attribute vec2 textureUvs;
    varying vec2 textureUv;
    void main()
    {
      gl_Position = vec4(vertices,0.0,1.0);
      textureUv = textureUvs;
    };

It works very well except that all vertices are transformed by the CPU before calling OpenGL drawArray(),I suppose that I will get better performance if I can send each triangles matrix and let OpenGL compute vertices.

And here is the draw call :

public final static void drawTexture(FloatBuffer vertices, FloatBuffer textureUvs, int textureHandle, int count, boolean triangleFan)
{
    GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureHandle);
    GLES20.glUseProgram(progTexture);
    GLES20.glEnableVertexAttribArray(progTextureVertices);
    GLES20.glVertexAttribPointer(progTextureVertices, 2, GLES20.GL_FLOAT, false,  2*Float.BYTES, vertices);
    GLES20.glEnableVertexAttribArray(progTextureUvs);
    GLES20.glVertexAttribPointer(progTextureUvs, 2, GLES20.GL_FLOAT, false, 2*Float.BYTES, textureUvs);
  
    if(triangleFan)
    {
        GLES20.glDrawArrays(GLES20.GL_TRIANGLE_FAN, 0, 4 * count); //Faster 10%
    }
    else
    {
        GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, 6 * count);
    }
    GLES20.glDisableVertexAttribArray(progTextureVertices);
    GLES20.glDisableVertexAttribArray(progTextureUvs);

}

Note that it is a Sprite renderer that's why I used only 2d vertices.

1
You may be probably right after all,one side we have 6 vertices to compute on CPU and to send per sprite to the GPU and other side we have 16 values of matrices + 6 vertices to send per sprite.Would be nice if someone have some statistics about this. Here are my results with my current method (compute vertices on CPU) for displaying 3600 sprites : Pixel 4 => 89FPS, GalaxyS9 => 45FPS, GalaxyTab2 => 20FPS. - DzzD
I use 3x3 matrix CPU side (they are more convenient as there is a hirarchy parent=>child=>child etc...and they are also (invert) used to convert from screen space to local space for touch event for example), also three components may not be enough as sprite can have pivot, rotation and "scale" multiple times. But that's a good idea I could pass some parameters rather than matrices but I still dont know how to do that wih OpenGLES and drawArray(). So the question is still the same, how to pass parameters (or matrix) per two triangle to OpenGL ? - DzzD

1 Answers

0
votes

I finally answered my own question, and yes it is possible to draw mutiple triangles with differents matrices with OpenGLES2 and it worth it !

The answer is related to this one How to include model matrix to a VBO? and @httpdigest comment.

Basically for sprites it only reqiere two vec3 as attributes of the shader that you fill with first and second row of your matrix 3x3.

Here is the shader I am using :

    attribute vec3 xTransform;
    attribute vec3 yTransform;
    attribute vec2 vertices;
    attribute vec2 textureUvs;
    varying vec2 textureUv;
    void main()
    {
      gl_Position = vec4(dot(vec3(vertices,1.0), xTransform), dot(vec3(vertices,1.0), yTransform), 0.0,1.0) ;
      textureUv = textureUvs;
    }

First you get two attributes pointers :

int progTextureXTransform = GLES20.glGetAttribLocation(progTexture, "xTransform");
int progTextureYTransform = GLES20.glGetAttribLocation(progTexture, "yTransform");

And for drawing you pass one vector of each per vertex :

    GLES20.glEnableVertexAttribArray(progTextureXTransform);
    GLES20.glVertexAttribPointer(progTextureXTransform, 3, GLES20.GL_FLOAT, false, 3*Float.BYTES, xTransforms);
    GLES20.glEnableVertexAttribArray(progTextureYTransform);
    GLES20.glVertexAttribPointer(progTextureYTransform, 3, GLES20.GL_FLOAT, false, 3*Float.BYTES, yTransforms);

On a galaxy Tab 2 this is twice faster than computing vertices with CPU.

xTransform is the first row of your 3x3 matrix

yTransform is the second row of your 3x3 matrix

And of course this can be extended for 3d rendering by adding a zTransform + switch to vec4