Translating - GLES translateM() - a floatbuffer in android - android

Dabbling around with OGLES in Android. I want to create some triangles and translate them. Straightforward enough.
I look at the examples and see that FloatBuffers are recommended as the storage construct for polygon coordinates using GLES in Android, because they are on native code steroids. Good stuff! Explanation here.
Why FloatBuffer instead of float[]?
Now what's confusing to me is the Matrix class in Android operates almost exclusively on java float arrays. So on one hand I'm being told to use FloatBuffers for speed, but on the other hand every transformation I want to do now has to look like this?
float[] myJavaFloatArray = new float[polylength];
myFloatBuffer.get(myJavaFloatArray);
Matrix.translateM(myJavaFloatArray,0,-1.0f,0.0f,0.0f);
myFloatBuffer.put(myJavaFloatArray);
Is this really the best practice? Is the assumption just that my ratio of translates to draws will be low enough that this expense is worth it? What if I'm doing lots of translates, one on every object per frame, is that an argument for using java float arrays throughout?

First of all, isn't there a method array() for FloatBuffer that returns float[] value pointing directly to the buffer data? You should use that in translate method so you don't copy the data around the memory, this should turn your 4 lines of code into a single line:
Matrix.translateM(myFloatBuffer.array(),0,-1.0f,0.0f,0.0f);
Second it is not best practice to transform your vertex data on the CPU, you have a vertex shader for that. Use matrices and push them to the GPU so you can benefit from it. Also if you transform those data the way you do you kind of corrupt them: If the float buffer contained vertex array for some object you want to draw in several location you would have to either translate it back to 0 before translating it to a new location for each draw call or have multiple instances of the vertex data.
Any way, although it can be very handy to be able to transform the array buffer you should avoid using it per frame if possible. Do it in loading time or in background when preparing some element. As for per frame rather try to use vertex shader for that. In case you are dealing with ES1 and you have no vertex shader there are still matrix operations that work in the same way (translate, rotate, scale, set, push, pop...)

Related

Fastest way to draw sprites in opengles 2.0 on android

So Im trying to figure out how to draw a single textured quad many times. My issue is that since these are create and deleted and every one of them has a unique position and rotation. Im not sure a vbo is the best solution as I've heard modifying buffers is extremely slow on android and it seems I would need to create a new one each frame since different quads might disappear randomly (collide with an enemy). If I simply do a draw call for each one I get 20fps around 100, which is unusable. any advice?
Edit: I'm trying to create a bullethell, but figuring out how to draw 500+ things is hurting my head.
I think you're after a particle system. A similar question is here: Drawing many textured particles quickly in OpenGL ES 1.1.
Using point sprites is quite cheap, but you have to do extra work in the fragment shader and I'm not sure if GLES2 supports gl_PointSize if you need different sized particles. gl_PointSize Corresponding to World Space Size
My go-to particle system is storing positions in a double buffered texture, then draw using a single draw call and a static array of quads. This is related but I'll describe it a bit more here...
Create a texture (floating point if you can, but this may limit the supported devices). Each pixel holds the particle position and maybe rotation information.
[EDITED] If you need to animate the particles you want to change the values in the texture each frame. To make it fast, get the GPU to do it in a shader. Using an FBO, draw a fullscreen polygon and update the values in the fragment shader. The problem is you can't read and write to the same texture (or shouldn't). The common approach is to double buffer the texture by creating a second one to render to while you read from the first, then ping-pong between them.
Create a VBO for drawing triangles. The positions are all the same, filling a -1 to 1 quad. However make texture coordinates for each quad address the correct pixel in the above texture.
Draw the VBO, binding your positions texture. In the vertex shader, read the position given the vertex texture coordinate. Scale the -1 to 1 vertex positions to the right size, apply the position and any rotation. Use the original -1 to 1 position as the texture coordinate to pass to the fragment shader to add any regular colour textures.
If you ever have a GLSL version with gl_Vertex, I quite like generating these coordinates in the vertex shader, saving storing unnecessarily trivial data just to draw simple objects. This for example.
To spawn particles, use glTexSubImage2D and write a block of particles into the position texture. You may need a few textures if you start storing more particle attributes.

Shared vertex indices with normals in opengl

In opengl or opengl-es you can use indices to share a vertices. This works fine if you are only using vertex coords and texture coords that don't change, but when using normals, the normal on a vertex may change depending on the face. Does this mean that you are essentially forced to scrap vertex sharing in opengl? This article http://www.opengl-tutorial.org/intermediate-tutorials/tutorial-9-vbo-indexing/
seems to imply that this is the case, but I wanted a second opinion. I'm using .obj models so should I just forget about trying to share verts? This seems like it would increase the size of my model though as I iterate and recreate the array since i am repeating tons of verts and their tex/normal attributes.
The link you posted explains the situation well. I had the same question in my mind couple months ago.I remember I read that tutorial.
If you need exactly 2 different normal, so you should add that vertex twice in your index list. For example, if your mesh is a cube you should add your vertices twice.
Otherwise indexing one vertex and calculating an average normal is kind of smoothing your normal transitions on your mesh. For example if your mesh is a terrain or a detailed player model etc. you can use this technique which you save free space and get better looking result.
If you ask how to calculate average normal, I used average normal calculating algorithm from this question and result is fast and good.
If the normals are flat faces then you can annotate the varying use in the fragment shader with the "flat" qualifier. This means only the value from the provoking vertex is used. With a good model exporter you can get relatively good vertex sharing with this.
Not sure on availability on GLES2, but is part of GLES3.
Example: imagine two triangles, expressed as a tri-strip:
V0 - Norm0
V1 - Norm1
V2 - Norm2
V2 - Norm3
Your two triangles will be V0/1/2 and V1/2/3. If you mark the varying variable for the normal as "flat" then the first triangle will use Norm0 and the second triangle will use Norm1 (i.e. only the first vertex in the triangle - known as the provoking vertex - needs to have the correct normal). This means that you can safely reuse vertices in other triangles, even if the normal is "wrong" provides that you make sure that it isn't the provoking vertex for that triangle.

In OpenGL ES for Android, what is the optimal way to translate objects onto a map?

I've begun working with android, so I'm developing a little game (mostly for learning purposes). My game has a simple 2d non-scrolling map, and I have many objects that will be placed in the map. The objects are already modeled statically in their classes, and I understand how to shift these into a float buffer and send them to the shaders.
I understand the gist of the model, view, and project matrices, but I've heard that translating in the shader, or passing specific model matrices for each object is inefficient.
How do I, optimally, take the modeled objects, and place them in the appropriate spot on the map (world coordinates)? Where should that translate occur (before or durring shaders? As part of the model matrix?)
(Pseudo-code is sufficient for an answer if necessary.)
Thank you!
It all comes down to the ratio of how many vertices (of a model) come to a single translation (change of transformation). As a general rule, for rendering the bulk of geometry, about at least 100 vertices should be sent for a given uniform if you want to max out the pipeline. Note that if your total number of vertices is relatively small about below 10000, you'll probably not notice any performance penality on modern systems.
So, if your objects are nontrivial, i.e. have a significant number of vertices, changing the uniforms is the way to go. If your objects are simple, placing them into a shared Vertex Array, with an additional vertex attribute indexing into a uniform arrays of transformations will make better use of the pipeline.
It really depends on how complex your objects are.

how to change the content of a FloatBuffer, keeping performance?

i've tried using
floatbuffer.put(float[]);
but as i am handling more than 200 squares, all with diferent texture coordinates that are updated each frame, my fps drop drastically, and the game becomes too far to be fluid.
y thought the method mentioned on badlogicgames.com, about of, instead use floatbuffer, use a intbuffer but, is the same thing, equal of slow at the moment of the method "put" of the buffer.
so, how i could update all my floatbuffers with a best performance?
EDIT: i've solved my problem, the "put" method itself is not slow, the problem is when a new float is initialized for each floatbuffer, instead of that, i just change the value of each element contained in the floatarray and that avoids many GC activity.. well i think.
There are a number of ways to improve performance. Briefly, here are a few:
1) Initialize the floatbuffer and an apply a transformation each each frame: - If your squares are moving across the screen, place them once in a floatbuffer, and then apply a separate matrix transformation to each one. In this method, you fill the floatbuffer once, and just update the transformations each turn.
2) Put only unique shapes in the floatbuffer - If any of your squares are duplicates of each other, call the same buffer each frame to conserve memory.
3) Use Vertex Buffer Objects and Index Buffer Objects - It sounds like you might have done this, but store the data in a vertex buffer, and call the vertices using the indices of the array.
If you are still having issues, I recommend taking a look at this tutorial: http://www.learnopengles.com/android-lesson-one-getting-started/

Android OpenGL ES glDrawArrays or glDrawElements?

What is the best way: if I use glDrawArrays, or if I use glDrawElements? Any difference?
For both, you pass OpenGL some buffers containing vertex data.
glDrawArrays is basically "draw this contiguous range of vertices, using the data I gave you earlier".
Good:
You don't need to build an index buffer
Bad:
If you organise your data into GL_TRIANGLES, you will have duplicate vertex data for adjacent triangles. This is obviously wasteful.
If you use GL_TRIANGLE_STRIP and GL_TRIANGLE_FAN to try and avoid duplicating data: it isn't terribly effective and you'd have to make a rendering call for each strip and fan. OpenGL calls are expensive and should be avoided where possible
With glDrawElements, you pass in buffer containing the indices of the vertices you want to draw.
Good
No duplicate vertex data - you just index the same data for different triangles
You can just use GL_TRIANGLES and rely on the vertex cache to avoid processing the same data twice - no need to re-organise your geometry data or split rendering over multiple calls
Bad
Memory overhead of index buffer
My recommendation is to use glDrawElements
The performance implications are probably similar on the iphone, the OpenGL ES Programming Guide for iOS recommends using triangle strips and joining multiple strips through degenerate triangles.
The link has a nice illustration of the concept. This way you could reuse some vertices and still do all the drawing in one step.
For best performance, your models should be submitted as a single unindexed triangle strip using glDrawArrays with as few duplicated vertices as possible. If your models require many vertices to be duplicated (because many vertices are shared by triangles that do not appear sequentially in the triangle strip or because your application merged many smaller triangle strips), you may obtain better performance using a separate index buffer and calling glDrawElements instead. There is a trade off: an unindexed triangle strip must periodically duplicate entire vertices, while an indexed triangle list requires additional memory for the indices and adds overhead to look up vertices. For best results, test your models using both indexed and unindexed triangle strips, and use the one that performs the fastest.
Where possible, sort vertex and index data so that that triangles that share common vertices are drawn reasonably close to each other in the triangle strip. Graphics hardware often caches recent vertex calculations, so locality of reference may allow the hardware to avoid calculating a vertex multiple times.
The downside is that you probably need a preprocessing step that sorts your mesh in order to obtain long enough strips.
I could not come up with a nice algorithm for this yet, so I can not give any performance or space numbers compared to GL_TRIANGLES. Of course this is also highly dependent on the meshes you want to draw.
Actually you can degenerate the triangle strip to create continuous strips so that you don't have to split it while using glDrawArray.
I have been using glDrawElements and GL_TRIANGLES but thinking about using glDrawArray instead with GL_TRIANGLE_STRIP. This way there is no need for creating inidices vector.
Anyone that knows more about the vertex cache thing that was mentioned above in one of the posts? Thinking about the performance between glDrawElements/GL_TRIANGLE vs glDrawArray/GL_TRIANGLE_STRIP.
The accepted answer is slightly outdated. Following the doc link in Jorn Horstmann's answer, OpenGL ES Programming Guide for iOS, Apple describes how to use "degenerate-triangles" trick with DrawElements, thereby gaining the best of both worlds.
The minor savings of a few indices by using DrawArrays isn't worth the savings you get by combining all your data into a single GL call, DrawElements. (You could combine all using DrawArrays, but then any "wasted elements" would be wasting vertices, which are much larger than indices, and require more render time too.)
This also means you don't need to carefully consider all your models, as to whether most of them can be rendered as a minimal number of strips, or they are too complex. One uniform solution, that handles everything. (But do try to organize into strips where possible, to minimize data sent, and maximize GPU likeliness of re-using recently cached vertex calculations.)
BEST: A single DrawElements call with GL_TRIANGLE_STRIP, containing all your data (that is changing in each frame).

Categories

Resources