Best way to save data of many instances - java

I have a particle system and for that I render (for 1 particle effect for example) 100 quads with texture on it. If I add several particle effects it lags because each particle has its own velicity (2f vector), position (3f vec), etc... (Vectors are from LwJGL)
As a consequence each instance means like 5 or 6 data types. Now my question is:
Is there a way of making this better, so that not every instance has 5 new vectors? (And I know, that there are many other better ways of creating a particle system, but this one I choose was easy and I can practice "performance boosting"..

Ok, so, I will refer to this code where you probably get inspired by.
I also suppose you have at least GL 3.3 profile.
In theory, to optimaze at best you should move Map<ParticleTexture, List<Particle>> particles (using a texture atlas) on the gpu and upload only the changing data per-frame, like camera.
But this is not easy to do in one step, so I suggest you to modify your current algorithm step by step by moving one thing at time on the gpu.
Some observations:
in prepare() and finishRendering(), the enabling of the i-th VertexAttribArray is part of the vao, if you bind/unbind the vao, it's enough. glEnableVertexAttribArray and glDisableVertexAttribArray can be removed
use uniform buffer, don't have all those single uniforms alone.
loader.updateVbo() is quite expensive, it creates a FloatBuffer every render and clear the buffer before copying the data.
You should allocate a float [] or a FloatBuffer just once, reuse it and call simply glBufferSubData, avoiding glBufferData

Related

How do work with varying number of vertices in OpenGL gl3?

I am learning JOGL on my own. I have just switched from GL2 to GL3. I found that there are very few tutorials on the GL3. Also, I found that GL3 is completely different from GL2. As far as I know, many ppl used buffer to hold all the vertices and bind them to OpenGL. But, when they were initialising the buffers, they used arrays, which are fixed in length. How am I going to work on varying number of vertices or objects, if the number of vertices was fixed from the beginning? Are there any simple examples? In general, how can I make my program more "dynamic"? (i.e. render a user-defined 3D world)
The best i can think of is creating a large buffer at the initializing stage and modify the data with glBufferSubData(). Other way is recreate the buffer with glBufferData() though this one is not preferable because of how expensive it is to recreate the buffer every time a new entity/object is created to/removed from the world (Probably fine once in a while).

Is it better to use the deprecated glTranslatef or update coordinates using glBufferSubData?

I want to make my VBO move and I was wondering if I should update the entire VBO with updated values using glBufferSubData or just use the deprecated glTranslatef to move my thing.
And if I were to just update the values in the VBO, should I use a separate VBO for the vertices, normals, and texture coordinates or should I put them all in one?
Thanks.
1: Usually you should always try to reduce the amount of data transferred between CPU and GPU to a minimum to keep the performance at the maximum.
So, updating the entire vertex buffer using glBufferSubData() should be avoided and as long as possible and transformations such as glTranslate() and glLoadMatrix() (which are deprecated) or shaders should be used.
But since you are already working with VBOs I would recommend to use shaders to do the transformation using a shader uniform variable and glUniformMatrix().
2: Separating the vertices, normals, and texture coordinates or combining them in one VBO is up to you. In most cases I combine them because it produces only one handle and I need only one glBufferData() call. But if there is a situation when only one part like the texture coordinates is updated and the rest stays as it is, then separating would be better as you could also update them separately.
Even more advanced:
If you are using buffer interlacing than you obviously have to combine them.
Sometimes using buffer interlacing can be faster than without because the data needed for a single vertex is kept together and the caches can be used. But you have to try out what impact that has on the performance (if any) as it strongly depends on the hardware you are using.

Modern method of transforming modelview matrix in OpenGL?

I've recently began learning OpenGL, starting with immediate mode, glPush/PopMatrix, and the glTranslate/Rotate/Scale functions. I've switched over to vertex buffer objects for storing geometry, but I'm still using the push/pop matrix and transform functions. Is there a newer, more efficient method of performing these operations?
I've heard of glMultMatrix, but some sources have said this is less efficient.
If at all relevant, I am using LWJGL with Java for rendering.
edit: Does anyone know about the performance impact of calling glViewport and gluPerspective, as well as other standard initialization functions? I have been told that it is often good practice to call these init functions along with the rendering code every update.
For modern OpenGL you want to write a vertex shader and multiply each vertex by the appropriate transform matrix in there. You'll want to pass in the matrices you need (probably model, view, and projection). You can calculate those matrices on the CPU on each render pass as needed. This means you won't need gluPerspective. You probably only need to call glViewport once unless you're trying to divide up the window and draw different things in each section. But I wouldn't expect it to cause any performance issues. You can always profile to see for sure.

How to reduce time to render large surface data in OpenGL

I am currently working on a project that renders large oil-wells and sub-surface data on to the android tablet using OpenGL ES 2.0.
The data comes in from a restful call made by the client (Tablet) to the server. I need to render two types of data. One being a set of vertices where I just join all the vertices (Well rendering) and the other is the subsurface rendering where each surface has huge triangle-data associated with them.
I was able to reduce the size of the well by approximating the next point and constructing the data that is to be sent to the client. But this cannot be done to the surface data as each and every triangle is important to get the triangles joined and form the surface.
I would appreciate if you guys suggest an approach to either reduce the data from the server or to reduce the time taken to render such a huge data effectively.
the way you can handle such complex mesh really depends on the scope of your project. Unfortunately there is no much we can say based on the provided inputs and the activity itself is not an easy task.
Usually when the mesh is very complex a typical approach to make the rendering process fast is to adopt dynamic Level Of Details (in programming terminology LOD).
The idea is to render "distant" meshes with a very low LOD (and therefore having a much lower number of vertices to be rendered) and there replace the mesh with an higher resolution every time the camera approaches the mesh's details.
This is a technique very used in computer games, for instance when a terrain needs to be rendered. When the player is in a particular sector of the MAP, the mesh of that sector is in High level of detail, the others are in low detail. As soon as the player moves, the different sectors become in "high resolution" (allow me the term).
It is not an easy way to do it but it works in many many situations.
In this gamasutra article, there are plenty of information on how this technique works:
http://www.gamasutra.com/view/feature/131596/realtime_dynamic_level_of_detail_.php?print=1
The idea, in your case, would be to take the mesh provided by the web service and handle it as the HD version of the mesh. Then (particularly if the mesh is composed by different objects), apply a triangular mesh simplification algorithm to create LD meshes of the same objects. An example on the way you could proceed is well described here:
http://herakles.zcu.cz/~skala/PUBL/PUBL_2002/2002_Mesh-Simplification-ICCS2002.pdf
I hope to have helped in some way.
Cheers
Maurizio

Efficiently looking up array element based on x/y coordinates

I've written a java top-down 2d game that uses generated tiles for the map. Each tile is described by a Tile class that contains its x/y coordinate.
I need to be able to get the tile a player is "on" as they move around the map. The player class knows its current x/y, and the Tile class knows the x/y it was assigned to.
Currently, all of the tiles that need to be rendered are stored in a Tile[][]. I'm fairly new to java but it doesn't seem like it's a good idea (if even possible) to simply use the x/y coordinates I want for the array indices - mainly because the tiles I'm currently rendering may not always start at 0,0. Say the player loads a saved-game when they were at 1000,1000 - I certainly wouldn't load tiles from 0,0 when I don't need them.
So, what would be the best way for me to store those coordinates?
In PHP it could be done since I know arrays don't care about indexes starting at 0:
$tiles[1000][1000] = new Tile()
But I'm not sure what the recommended method in Java is. It feels highly inefficient to have to iterate through every single tile and check the x/y for matches.
Honestly, what you're asking is a quite advanced topic. This sort of project that involves such large maps really can't be accomplished with a simple array. Some people will suggest using a simple offset and dynamic array, but this is extremely inefficient.
I can give you a suggestion, however. You can load the tiles in chunks. Say, each chunk is a 2D array of 32 by 32, for instance. Instead of generically loading tiles that surround the player's location, you can load the current chunk and surrounding chunks. For instance, let's say that the position 1000, 1000 falls in chunk C. You then load chunk C and all of the surrounding chunks. When you move from chunk C into chunk D, you offload the chunks that surround C, and instead load the chunks that surround chunk D
A chunk class might look something like this:
class Chunk {
private Tile tiles[32][32];
private Coordinate origin; // (0, 0) on this chunk's array is actually equal to origin on the map
// Example: if the chunk started at (128, 128), then origin would be (128,128)
...
public static Chunk loadChunk(...) { ... }
...
}
And you would need Map class to assist with locating and loading chunks:
class Map {
public Chunk currentChunk;
public ArrayList<Chunk> loadedChunks;
...
public ArrayList<Chunk> getSurroundingChunks( Chunk ch ) {...}
...
}
Loading by chunks is the way that almost all games with large maps do it (minecraft is a notable example, though that game is pretty poorly programmed in general).
Of course, it is algorithmically complex, and you'll need to research it further than just reading this post. But it should give you a robust system that works for any size of map, and has been proven to work in the real world.
One of the weaknesses of this system is that unloading can be hard to predict in java, due to garbage collection. However, I'm not aware of a robust loading system that isn't at least slightly hurt by Java's garbage collector.
NOTE
This type of technique is also called lazy loading. It means that you only load what you really need into memory. It's the best technique to use for loading large amounts of predictable data because it allows you to minimize both loading time and memory consumption. Chunk-based loading is not the only kind of lazy loading, but I would go so far as to say that it is probably the best kind.
Another alternative is to use a Dictionary to store the tiles. It isn't necessarily the most efficient, but it would work:
java.awt.Point p = new java.awt.Point(1000,1000);
Tile t = // however you get your tiles
java.util.Dictionary<java.awt.Point, Tiles> theDictionary = new java.util.Dictionary<>();
theDictionary.put(p, t);
You could use a Map to hold the data, and as key a Coordiate object. The Coordinate object should implement equals and hashCode. That ought to work pretty fast and simple.
You add an item to the map:
map.put(new Coordinate(1000,1000), new Title(...));
And you recover it by doing:
Title title = map.get(new Coordinate(1000,1000));

Categories