0

I am using instancing in my OpenGL-app and since only one drawcall are made I have to calculate a larger matrix that consists of smaller matrices and that larger matrix is sent to the shader where gl_InstanceID can distinguish between successive matrices.

Its put on the bus with the following call

GLES30.glUniformMatrix4fv(mMVPMatrixHandleBall, nBalls, false, mMVPMatrixMajor, 0);

and in the shader the multiplication si made by

gl_Position =  u_MVPMatrix[gl_InstanceID] * a_Position;

simple!

On the client-side the larger matrix is created by the following code:

 private void setLargeMVPmatrix() {

    int cnt = 0;
    for (Iterator<Ball> shapeIterator = arrayListBalls.iterator(); shapeIterator.hasNext(); ) {

        Ball ball = shapeIterator.next();

        mModelMatrix = ball.getmModelMatrix();

        //multipl.
        Matrix.multiplyMM(mMVPMatrix, 0, mViewMatrix, 0, mModelMatrix, 0);
        Matrix.multiplyMM(mMVPMatrix, 0, mProjectionMatrix, 0, mMVPMatrix, 0);
        //subst. in matrisdata i en större vektor dvs vi får en stor matris som innehhåller flera mindre matriser
        for (int i = 0; i < CreateGLContext.MATRIX_SIZE; i++) {

            mMVPMatrixMajor[i + CreateGLContext.MATRIX_SIZE * cnt] = mMVPMatrix[i];
        }
        cnt++;
    }
}

If I have moving-objects on the screen, like bouncing balls, for instance 100 balls bouncing around it means I have to continously translate their positions each frame which in turn means I have to call this method every frame. And the consequence is that it becomes a real performance bottelneck. I know it by just commenting out the method just to see what happends - and a real performance boost but the balls doesnt not move any longer, of course.

So my question - Is there a soluition to this problem? If I use instancing, I have to send a large matrix according to above.

Edit:

I've even tried the following which I thought could at least partially solve my problem. In the drawMethod:

  int cnt = 0;
    for (Iterator <Ball> it = arrayListBalls.iterator(); it.hasNext();) {

        Ball ball = it.next();
        mModelMatrix = ball.getmModelMatrix();

        //multipl.
        Matrix.multiplyMM(mMVPMatrix, 0, mViewMatrix, 0, mModelMatrix, 0);
        Matrix.multiplyMM(mMVPMatrix, 0, mProjectionMatrix, 0, mMVPMatrix, 0);
        GLES30.glUniformMatrix4fv( (mMVPMatrixHandleBall + cnt), 1, false, mMVPMatrix, 0);
        cnt++;
    }

Thanks in advance!!!

Rabbid76
  • 202,892
  • 27
  • 131
  • 174
java
  • 1,165
  • 1
  • 25
  • 50

1 Answers1

1

If the data that change are positions and rotations then that's what you should update to the shader.

Doing most of matrix stuff at CPU is slow, unless the needed operations are tiny, like computing the new view and projection matrices, same for all objects, and they are cheap to pass as uniforms

For every frame I'd re-fill a BufferData, perhaps with the help of glMapBufferRange or glBufferSubData, with the new positions and rotations.
Then, in the shader, build the matrices needed and do matrices multiplication there.

If initial positions and rotations are needed to build new matrices, then you must also pass them in another buffer, although just update it for the first frame.

With the proper attributes order you read in the shader these positions and rotations. The gl_InstanceID is then not needed for gl_Position calculus, perhaps needed for other object property.

If you need help on how to build matrices inside the shaders, look for glRotate and glTranslate in OpenGL 2.1 docs where you can find the definitions.

Also note that passing a big matrix for all objects by an uniform may exceed the limit on the size for the whole uniform data.

Ripi2
  • 7,031
  • 1
  • 17
  • 33
  • _If the data that change are positions and rotations then that's what you should update to the shader._ .. what about scaling? – java Oct 25 '17 at 19:40
  • Scaling is another set of (Sx,Sy,Sz) values, just as position (x,y,z) is. – Ripi2 Oct 25 '17 at 19:41