Instanced rendering problem - LWJGL 2

Started by Thiird, January 01, 2018, 21:55:57

Previous topic - Next topic

Thiird

Hi this is my first post on the forum.

I started learning opengl 6 months ago, and now Im putting to use all the knowledge to make a 3D app for a school project.

I've been following a brilliant series of tutorials on LWJGL from a guy on yt, in particular Im stuck at this video: https://www.youtube.com/watch?v=Rm-By2NJsrc&t=1305s

I need to implement instanced rendering since my application can host lots of Entities, wich all share the same texturedModel (over 5k entities for each kind).

For testing purposes I am only try to get 1 entity to render with this technique.

Basically the problem is that the model is there, but it has some strange artifacts.

This is what the model should looks like:
http://prntscr.com/htaq2j

This is what I got after implementing instancing:
http://prntscr.com/htapq3

You can actually see some pieces of the model in the right place, but its all covered in that mess of polygons.

So then I tried to render to points instead of triangles, and this what came out:
http://prntscr.com/htayx8

All vertices are there, but they are surrounded by a "sphere" of vertices, and another plane of vertices ( :o).

I've manually checked the transformation matrix, since its the only per-instance attribute that I have in my VAO right now (I use just that and not the modelViewMatrix since the only thing that changes per-instance is the transfMatrix) and it is ok (compared against the same model's matrix in the rendering engine without instancing, where the models renderes fine).

That made me think that the indices are not loaded correctly in the loadToVAO() method in the DataManager class, but I can't see the problem with that method...

I've stripped down the project with just a few classes in order to be easy to debug.

http://www.mediafire.com/file/lllanhbkmwv6cru/Test_instance.zip

Can some one tell me what Im missing? Thanks.

KaiHH

The problem is that you are using glDrawArraysInstanced() which is not using indices/element arrays, but only draws all vertices specified in the buffer object bound to GL_ARRAY_BUFFER. Since your OBJ loader does load (reused) indices, you have to use the indices/element arrays instead when drawing.
To fix this, simply use glDrawElementsInstanced() in your EntityRenderer.render() method like so:
GL31.glDrawElementsInstanced(GL11.GL_TRIANGLES, tm.getRawModel().getVertexCount(), GL11.GL_UNSIGNED_INT, 0L, tempEntityList.size());

Also, a bit misleading, is the fact that your RawModel.getVertexCount() is not the actual number of vertices in the vertex buffer but the number of indices/elements.

Thiird

Thanks for the quick reply.

QuoteAlso, a bit misleading, is the fact that your RawModel.getVertexCount() is not the actual number of vertices in the vertex buffer but the number of indices/elements.
Yes I just realised that with
RawModel.getVertexCount()
I was getting the indeces count, and not the vertex count, dumb me (now Im wondering how the hell it worked with the standard renderer, but whatever).
I fixed that, now the return statement of the loadToVAO method in the DataManager class returns:
return new RawModel(vaoID, positions.length);

At first I had changed it to
return new RawModel(vaoID, (positions.length)/3);
Since a vertex is defined by 3 coords, but that renderes to this: http://prntscr.com/hv2ij5

And I dont understand why.

Anyway,I also changed the rendering function with what you have suggested, and this is the result so far:
http://prntscr.com/hv2dgh

What am I still missing?

KaiHH

Quote
I was getting the indeces count, and not the vertex count, dumb me (now Im wondering how the hell it worked with the standard renderer, but whatever).
I fixed that, now the return statement of the loadToVAO method in the DataManager class returns:
That is not what I intended to say. You actually need the number of indices and not the number of vertices. So, you could have simply renamed that method to getIndexCount() or whatever. But anyway, forget about my comment on that.

Everything would have worked fine had you just only changed the glDrawArraysInstanced call to the glDrawElementsInstanced call.
So, please only change that draw call and everything will work.

Quote
return new RawModel(vaoID, (positions.length)/3);
That will of course also not work, since with indexed drawing the total number of triangles/primitives is _not_ the number of vertices divided by three; and you would also still need the effective vertex count as argument there, and not the number of primitives.

Thiird

YES not it works!

Thank you so much.

Now I reach ~42 +/-5fps when rendering a scene like this:
http://prntscr.com/hv3ny9

Wich has a grid of 200*200 simple cubes, where as before, with 1 draw call for every cube I could reach ~13fps.
And this is with lots of optimizing techniques not yet implemented.

Just for the sake of understanding, can you explain more in detail why I cant use glDrawArraysInstanced()?
I'd like to stick to that like the tutorial does.

QuoteThe problem is that you are using glDrawArraysInstanced() which is not using indices/element arrays, but only draws all vertices specified in the buffer object bound to GL_ARRAY_BUFFER. Since your OBJ loader does load (reused) indices, you have to use the indices/element arrays instead when drawing.

Do you mean that I should also bind the vbo wich contains the positions data about the model Im abouy to intance render?


KaiHH

Please google for "OpenGL indexed drawing/rendering" and get familiar with how your own OBJ loader works.

Thiird

I perfectly know how my obj loader works, I just wanted to understand clearly.

I'll read the gl docs.

Thank you again for you help. ;D