Efficient 3D block rendering with Libgdx - java

To start with,I am pretty new to 3D programming and libgdx.
I looked at a few tutorials and I already render the scene I want. I have some 1x1x1 blocks, created with ModelBuilder.createRect() for every visible face, so if another block covers a face of this block, there is no rect created for this block. Also the top and bottom rect is not needed, as I can never see them (except for the floor). So I thought, that this is pretty efficient. I also have Backface culling enabled and I do Viewfrustum culling. However, if I look in a direction, where many blocks are in my viewfrustum the FPS go down to 15-20. This is still okay for me, as my laptop is over 5 years old and its performance is not the best, but this answer made me think.
"ModelBuilder is used for debug only". Okay, but how should i then create my boxes? Why should i create a Model in a Modeling app (like Blender), for simple squares? By doing this i couldn't even cull the faces, which are occupied by other blocks.
So my question is:
How can i create and render those boxes the most efficient way?

ModelBuilder#createRect will create a new model for each rectangle. When rendering a (part of a) model instance, it implies a draw call. Therefor ModelBuilder#createRect is extremely inefficient. It is better to combine multiple rectangle into a single (part of a) Model. This can be done using:
modelBuilder.begin();
MeshPartBuilder mpb = modelBuilder.part(....);
mpb.rect(...); // first rect.
mpb.rect(...); // second rect.
// etc.
Model model = modelBuilder.end();
Note that this is still not efficient enough for e.g. a voxel engine. If you are aiming to optimize for voxels, you'll probably want to build the mesh (after frustum culling and depth sorting) in a custom RenderableProvider. Here's an example: https://github.com/libgdx/libgdx/tree/master/tests/gdx-tests/src/com/badlogic/gdx/tests/g3d/voxel

Related

Creating 2D Angled Top Down Terrain Instead of Fully Flat

Similar to the game Factorio im trying to create "3D" terrain but of course in 2D Factorio seems to do this very well, creating terrain that looks like this
Where you can see edges of terrain and its very clearly curved. In my own 2D game Ive been trying to think of how to do the same thing, but all the ways I can think of seem to be slow or CPU intensive. Currently my terrain looks like this:
Simply 2D quads textured and drawn on screen, each quad is 16x16 (except the water thats technically a background but its not important now), How could I even begin to change my terrain to look more like a Factorio or other "2.5D" games, do they simply use different textures and check where the tile would be relative to other tiles? Or do they take a different approach?
Thanks in advance for your help!
I am a Factorio dev but I have not done this, so I can only tell you what I know generally.
There is a basic way to do it and then there are optional improvements.
Either way you will need two things
Set of textures for every situation you want to handle
Set of rules "local topology -> texture"
So you have your 2d tile map, and you move a window across it and whenever it matches a pattern, you apply an appropriate texture.
You probably wouldn't want to do that on the run in every tick, but rather calculate it all when you generate the map (or map segment - Factorio generates new areas when needed).
I will be using your picture and my imba ms paint skills to demonstrate.
This is an example of such rule. Green is land, blue is water, grey is "I don't care".
In reality you will need a lot of such rules to cover all cases (100+ I believe).
In your case, this rule would apply at the two highlighted spots.
This is all you need to have a working generator.
There is one decision that you need to make here. As you can see, the shoreline runs inside the tile, not between tiles. So you need to chose whether it will run through the last land tile, or the last water tile. The picture can therefore be a result of these two maps (my template example would be from the left one):
Both choices are ok. In fact, Factorio switched from the "shoreline on land" on the left to the "shoreline on water" on the right quite recently. Just keep in mind that you will need to adjust the walking/pathfinding to account for this.
Now note that the two areas matched by the one pattern in the example look different. This can be a result of two possible improvements that make the result nicer.
First is that for one case you can have more different textures and pick a random one. You will need to keep that choice in the game save so that it looks the same after load.
Another one is more advanced. While the basic algorithm can already give you pretty good results, there are things it can't do.
You can use larger templates and larger textures that span over several tiles. That way you can draw larger compact pieces of the terrain without being limited by the fact that all the tiles need to be connectable to all (valid) others.
The example you provided are still 2D textures (technically). But since the textures themselves are 'fancy 3D', they appear to be 3D/2D angled.
So your best bet would be to upgrade your textures. (and add shadow to entities for extra depth).
Edit:
The edges you asked about are probably layed-out by checking if a 'tile' is an edge, and if so it adds an edge-texture on top the background. While the actual tile itself is also a flat image (just like the water). Add some shadow afterwards and the 3D illusion is complete.
I hope this answers your question, otherwise feel free to ask clarification.

How do I improve LibGDX 3D rendering performance?

I'm working on rendering a tiled sphere with LibGDX, aimed at producing a game for desktop. Here are some images of what I've got so far: http://imgur.com/GoYvEYZ,xf52D6I#0. I'm rendering 10,000 or so ModelInstances, all of which are generated from code using their own ModelBuilders. They each contain 3 or 4 trianglular parts, and every ModelInstance corresponds to its own Model. Here's the exact rendering code I'm using to do so:
modelBatch.begin(cam);
// Render all visible tiles
visibleCount = 0;
for (Tile t : tiles) {
if (isVisible(cam, t)) {
// t.rendered is a ModelInstance produced earlier by code.
// the Model corresponding to the instance is unique to this tile.
modelBatch.render(t.rendered, environment);
visibleCount++;
}
}
modelBatch.end();
The ModelInstances are not produced from code each frame, just drawn. I only update them when I need to. The "isVisible" check is just some very simple frustum culling, which I followed from this tutorial https://xoppa.github.io/blog/3d-frustum-culling-with-libgdx/. As you can tell from my diagnostic information, my FPS is terrible. I'm aiming for at least 60 FPS rendering what I hope is a fairly-simple scene of tons of polygons. I just know I'm doing this in a very inefficient way.
I've done some research on how people might typically solve this issue, but am stuck trying to apply the solutions to my project. For example, dividing the scene into chunks is recommended, but I don't know how I could make use of that when the player is able to rotate the sphere and view all sides. I read about occlusion culling, so that I might only render ModelInstances on the side of the sphere facing the camera, but am at a loss as to how to implement that in LibGDX.
Additionally, how bad is it that every ModelInstance uses its own Model? Would speed be improved if only one shared Model object was used? If anyone could point me to more resources or give me any good recommendations on how I can improve the performance here, I'd be thankful.
If the tiles are eventually intended to be solid, one improvement you can make is to turn on back-face culling. This will cause any faces not facing the camera to not be rendered (i.e. one side of each face becomes invisible). For a sphere that means the GPU would only need to render about half the faces.
Combining the object into a single Model may also have a large impact. It may be the difference between 10,000 draw calls and 1 (it depends on how smart that modelBatch object is, as it might do the combining behind the scenes). If the user will sometimes be zoomed pretty close a chunking approach might help so that you can continue doing frustum culling.

Android OpenGL ES 1.1 Combine Multiple Textures

I'm developing an Android game using Java, and I am currently on trying to figure out an efficient way of rendering the necessary textures. Suppose you have a Grid, similar to a Checkers board layout, and Tiles to fill that grid, as in each square on the board. That is the concept of what will be displayed. Currently, I am drawing each tile one by one. All of the texture loading is done upon creation and is only done once, not upon drawing. Now, for what I want to do. I've noticed that drawing all one by one, although fast for what I'm doing, it can be glitchy. In my game, the user has the ability to drag the "board" to view different areas. As of right now, I'm only allowing the necessary tiles to be drawn depending on the location of the top left visible tile. As I said, it works quite fast, but, once the user starts interacting more or dragging faster, the rendering starts to have difficulties and isn't as fast as it should be. This causes little separation in between the tiles. It's not large, just large enough to be noticeable. What I want to do is to basically place each texture in a certain location as defined by the grid, thus creating a new texture containing the viewable area, and then render that entire area as opposed to render each tile separately. I've done a lot of research and already looked at many questions, but I still have not found something that will help my cause. I've read that rendering to texture using a framebuffer may help, but I haven't found any easy-to-follow tutorials or examples, just a lot "here's the code, no explanation" or "here's something similar to what you want, but it's using different things." So, if someone could point me towards a good tutorial/example, or post a valuable answer, I would be very grateful. I'm avoiding OpenGL ES 2.0 because I want my game to be compatible with many devices, and for what I'm doing, 2.0 is not necessary.
For a quick summary of what my code does for further explanation:
for(go through visible rows){
for(go through visible columns){
drawTile(); //Does the texture binding and drawing for each tile
}
}
What I want:
for(go through visible rows){
for(go through visible columns){
loadTileTextureIntoGridTexture();
//I want it to combine the textures into one texture
}
}
drawGridTexture();
Doing it the second way will only have one whole texture to render as opposed to visibleRows*visibleColumns textures to render.

3D Shadow implementation idea

Lets assume your eye is in the surface point P1 on an object A and there is a target object B and there is a point-light source behind object B.
Question: am i right if i look to the light source and say "i am in a shadow" if i cannot see the light because of object B ?. Then i flag that point of object A as "one of the shadow points of B on A" .
If this is true, then can we build a "shadow geometry"(black-colored) object on the surface of A then change it constantly because of motion of light,B,A, etc... in realtime ? Lets say a sphere(A) has 1000 vertices and other sphere (B)has 1000 vertices too, so does this mean 1 milion comparations? (is shadowing, O(N^2) (time) complexity?). I am not sure about the complexity becuse the changing the P1(eye) also changes the seen point of B (between P1 and light source point). What about the second-order shadows and higher (such as lights being reflecting between two objects many times) ?
I am using java-3D now but it doesnt have shadow capabilities so i think of moving to other java-compatible libraries.
Thanks.
Edit: i need to disable the "camera" when moving the camera to build that shadow. How can i do this? Does this decrease the performance badly?
New idea: java3D has built-in collision detection. I will create lines(invisible) from light to target polygon-vertex then check for a collision from another object. If collision occurs, add that vertex corrd. to the shadow list but this would work only for point-lights :( .
Anyone who supplys with a real shade library for java3d, will be much helpful.
Very small sample Geomlib shadow/raytracing in java3D would be the best
Ray-tracing example maybe?
I know this is a little hard but could have been tried by at least a hundred people.
Thanks.
Shadows is probably the most complex topic in 3D graphics programming, and there are many approaches, but the best option should be identified according to the task requirements. The algorithm you are talking about is the simplest way to implement shadows from a spot light source onto the plane. It should not be done on the CPU, as you already use GPU for 3D rendering.
Basically the approach is to render the same object twice: once from the camera view point, and once from the light source point. You will need to prepare model view matrices to convert between these two views. Once you render the object from the light point, you get the depth map, in which each point lies closest to the light source. Then, for each pixel of the normal rendering, you should convert its 3D coordinates into the previous view, and check against the corresponding depth value. This essentially gives you a way to tell which pixels are covered by shadow.
The performance impact comes from rendering the same object twice. If your task doesn't assume high scalability of shadow casting solution, then it might be a way to go.
A number of relevant questions:
How Do I Create Cheap Shadows In OpenGL?
Is there an easy way to get shadows in OpenGL?
What is the simplest method for rendering shadows on a scene in OpenGL?
Your approach can be summarised like this:
foreach (point p to be shaded) {
foreach (light) {
if (light is visible from p)
// p is lit by that light
else
// p is in shadow
}
}
The funny fact is that's how real-time shadows are done today on the GPU.
However it's not trivial for this to work efficiently. Rendering the scene is a streamlined process, triangle-by-triangle. It would be very cumbersome if for every single point (pixel, fragment) in every single triangle you'd need to consider all other triangles in other to check for ray intersection.
So how to do that efficiently? Answer: Reverse the process.
There's a lot fewer lights than pixels on the scene, usually. Let's take advantage of this fact and do some preprocessing:
// preprocess
foreach (light) {
// find all pixels p on the scene reachable from the light
}
// then render the whole scene...
foreach (point p to be shaded) {
foreach (light) {
// simply look up into what was calculated before...
if (p is visible by the light)
// p is lit
else
// p is in shadow
}
}
That seems a lot faster... But two problems remain:
how to find all pixels visible by the light?
how to make them accessible quickly for lookup during rendering?
There's the tricky part:
In order to find all points visible by a light, place a camera there and render the whole scene! Depth test will reject the invisible points.
To make this result accessible later, save it as a texture and use that texture for lookup during the actual rendering stage.
This technique is called Shadow Mapping, and the texture with pixels visible from a light is called a Shadow Map. For a more detailed explanation, see for example the Wikipedia article.
Basically yes, your approach will produce shadows. But doing it point by point is not feasible performance wise (for realtime), unless its done at the GPU. I'm not familiar with what the API's offer today, but I'm sure any recent engine will offer some shadow out of the box.
Your 'New idea' is how shadows were implemented back in the days when rendering was still done with the CPU. If the number of polygons isn't too big (or you can efficently reject entire bunches by having grouping volumes etc.) it can be done with fairly little CPU power.
3D shadow rendering on vanilla Java is never going to be efficient. You best use graphical libraries written to utilize the full capabilities range of the graphical card, such as OpenGL or DirectX. As you are using Canvas (from the screenshot you provided), you can even paint that Canvas from native code using JNI. So you could use all the technology from graphial libraries, do just a little fiddling and paint your Canvas directly from the native code. There would be very little work involved to make it work, compared to writing your own 3D engine.
Wiki link about AWT native access: http://en.wikipedia.org/wiki/Java_AWT_Native_Interface
Documentation: http://docs.oracle.com/javase/7/docs/technotes/guides/awt/AWT_Native_Interface.html

Collidable color Java/Android game

I'm trying to develop side scrolling game for android involving many many textures so I was thinking if I could create a separate layer, all a single unique color (very similar to a green screen effect) make a collidable and make it invisible to the player.
(foreground layer) visual Image
(2nd layer)collidable copy of foreground layer with main character
(3rd layer)Background image
I not sure if this is possible or how to implement it efficiently, the idea just came to me randomly one day.
Future regards, Thanks
I assume your game is entirely 2D, using either bit-blits or quads (two 3D triangles always screen-aligned) as sprites. Over the years there have been lots of schemes for doing collision detection using the actual image data, whether from the background or the sprite definition itself. If you have direct access to video RAM, reading one pixel position can quickly tell if you've collided or not, giving pixel-wise accuracy not possible with something like bounding boxes. However, there are issues greatly complicating this: figuring out what you've collided with, or if your speed lands you many pixels into a graphical object, or if it is thin and you pass through it, or how to determine an angle of deflection, etc.
Using 3D graphics hardware and quads, you could potentially change render states, rendering in monochrome to an off-screen texture, yielding the 2nd collidable layer you described. Yet that texture is then resident in graphics memory, which isn't freely/easily accessible like your system memory is. And getting that data back/forth over the bus is slow. It's also costly, requiring an entire additional render pass (worst case, halving your frame rate) plus you have all that extra graphics RAM used up... all just to do something like collision-detect. Much better schemes exist, especially using data structures.
It's better to use bounding boxes, or even a hierarchy of sub-bounding boxes. After that, you can determine if you've landed on the other side of, say, a sloped line, requiring only division/addition operations. Your game already manages all the sprites you're moving, so integrate some data structures to help your collision detection. For instance, I just suggested in another thread the use of linked lists to limit the objects you must collision-detect against one another.
Ideas like yours might not always work, but your continual creative thinking will lead to ones that do. Sometimes you just have to try coding them to find out!

Categories