Best solution to render several objects without overlapping - opengl

I just can’t figure out how to do it better. On the 3D scene there are several objects in one plane, and I need to render them in such a way that when they actually intersect, one object is displayed completely on top of another object.
To make it clearer, for example, I have such 3d scene:
and I need to do this for all objects:
The only thing that comes to my mind is to clear the Z-buffer every time after each drawing of the object:
1) Render object1.
2) Clear Z-buffer.
3) Render object2.
3) Clear Z-buffer.
......
N) Render objectN.
N+1) Clear Z-buffer.
But as I understand it, such solution will be extremely costly in performance. Is there any way to repeat this effect somehow with the help of a stencil buffer or in some other way?

Assuming you have knowledge about the number of potentially overlapping objects beforehand, you can make use of glDepthRange. Sort the objects by depth, then for object i (in ascending order, i.e. smallest i is the closest object) issue glDepthRange((float)i/N, (float)(i+1)/N), where N is the number of objects.
Note that the order in which you draw the objects doesn't matter, as depth testing is preserved and layering is explicit by the depth range.

Use the Painter's Algorithm: For each new camera viewpoint sort the (convex) models by distance from centroid to the camera position, disable the depth testing and render all of them from back to front.
To avoid sorting the objects by centroid every time you can use a spatial Tree: it could be an Oct-tree, Quad-tree, BSP-tree, AABB-tree or others. The leaves of the tree point to your objects and internal nodes subdivide the space that separate them. You can traverse those trees in back-to-front order from any camera position at rendering time.
The BSP-tree is the most flexible one since you can choose the planes that best separate your objects from each other at will. Even if the objects overlapp you just define a plane splitting them and classify them to be entirely at one side of the plane and it will work as you want.

Related

Using OpenGL instancing for rendering 2D scene with object depths and alpha blending

Here's what I'm trying to do: I want to render a 2D scene, consisting of a number of objects (quads), using instancing. Objects with a lower y value (towards the bottom of the screen) need to be rendered in front of the ones with higher y values. And alpha blending also needs to work.
So my first idea was to use the Z value for depth, but I soon realized alpha blending will not work unless the objects are drawn in the right order. But I'm not issuing one call for each quad, but use a single instanced call to render the whole scene. Putting the instance data in the correct sorted order seems to work for me, but I doubt this is something I can rely on, since the GPU is supposed to run those computations in parallel as much as possible.
So the question is, is there a way to make this work? The best thing I can think of right now is to issue an instanced call for each separate y value (and issue those in order, back to front). Is there a better way to do this?
Instancing is best used for cases where each instance is medium-sized: hundreds or maybe thousands of triangles. Quads are not a good candidate for instancing.
Just build and render a sequence of triangles. There are even ways to efficiently get around the lack of a GL_QUADS primitive type in modern OpenGL.
Putting the instance data in the correct sorted order seems to work for me, but I doubt this is something I can rely on, since the GPU is supposed to run those computations in parallel as much as possible.
That's not how GPUs work.
When you issue a rendering command, what you (eventually) get is a sequence of primitives. Because the vertices that were given to that command are ordered (first to last), and the instances in that command are ordered, and even the draws within a single draw command are ordered, an order can be assigned to every primitive in the draw call with respect to every other primitive based on the order of vertices, instances, and draws.
This defines the primitive order for a drawing command. GPUs guarantee that blending (and logical operations and other visible post-fragment shader operations) will respect the primitive order of a rendering command and between rendering commands. That is, if you draw 2 triangles in a single call, and the first is behind the second (with depth testing turned off), then blending for the second triangle will respect the data written by the first.
Basically, if you give primitives to the GPU in an order, the GPU will respect that order with regard to blending and such.
So again, just build a ordered stream of triangles to represent your quads and render them.

In OpenGL, how to clear drawn primitives in a 3D region

Let us say, I draw 3 points with glVertex3f at (0,0,0), (9,0,0) and (10,0,0)
I would like to clear all Vertex3f points in the bounding box region (2,-1,-1) to (15, 1, 1) which should include the last two points.
How does one do this in OpenGL?
Manage your point drawing outside of OpenGL. IE Don't use OpenGL to accomplish this. OpenGL is used for drawing data, not keeping track of it. If you want to get rid of certain objects, don't tell OpenGL to draw them. There are various space-partitioning data structures at your disposal for efficiently finding intersections.
The naive way is to check to see that all the points in your scene are outside that region before you draw them.
A better way is to use a kd-tree or an octree to exponentially narrow down the number of comparisons you must do.

OpenGL 3.2+ Drawing Cubes around existing vertices

So I have a cool program that renders a pretty cube in the centre of the screen.
I'm trying to now create a tiny cube on each corner of the existing cube (so 8 tiny cubes), centred on each of the existing cubes corners (or vertices).
I'm assuming an efficient way to implement this would be with a loop of some kind, to minimise the amount of code.
My query is, how does this affect the VAO/VBO's? Even in a loop, would each one need it's own buffer or could they all be sent at the same time...
Secondly, if it can be done, what would the structure of this loop be like, in terms of focusing on separate vertices given that each vertex has different coordinates...
As Vaughn Cato said, each object (using the same VBOs) can simply be drawn at different locations in world space, so you do not need to define separate VBO's for each object.
To complete this task, you simply need a loop to modify the given matrix before each one is rendered to the screen to change the origins of where each cube is drawn.

Disable writing in depth buffer from glsl

All geometry is storing in one VBO (Transparent + Not transparent). I can not sort geometry. How I can disable writing in depth buffer from glsl without loss the data colors?
If I understand right, you want to disable depth writes because you draw both opaque and transparent objects. Apart from the fact that it doesn't work that way from within GLSL, it would not produce what you want, if it did.
If you just disabled depth writes ad hoc, the opaque objects coming after a transparent object would overwrite it, regardless of the z order.
What you really want to do is this:
Enable depth writes and depth test
Draw all opaque geometry. If you can, in a roughly sorted (roughly is good enough!) order, closest objects first.
Disable depth writes, keep depth test enabled
Enable blending
Draw transparent objects, sorted in the opposite direction, that is farthest away first. This occludes transparent objects with opaque geometry and makes blending work correctly.
If, for some reason, you can't sort the opaque geometry (though there is really no reason why you can't do that?), never mind -- it will be slightly slower because it does not cull fragments, but it will produce the same image.
If, for some reason, you can't sort the transparent geometry, you will have to expect incorrect results where several transparent objects overlap. This may or may not be noticeable (especially if the order is "random", i.e. changes frame by frame, it will be very noticeable -- otherwise you might in fact get away with it although it's incorrect).
Note that as datenwolf has pointed out already, the fact that several objects are in one VBO does not mean you can't draw a subset of them, or several subsets in any order you want. After all, a VBO only holds some vertices, it is up to you which groups of them you draw in which order.
You can't.
I can not sort geometry.
Why? You think because it's all in one VBO? Then I've got good news: It's perfectly possible to draw from just a subset of a buffer object.

Mesh deformation and VBOs

In my current project I render a series of basically cubic 3D models arranged in a grid. These 3D tiles form the walls of a dungeon level in a game, so they're not perfectly cubic, but I pay special attention to be certain all the edges line up and everything tiles correctly.
I'm interested in implementing a height-map deformation, which seems like it'd require me to manually deform the vertices of the 3D tiles, first by raising or lowering a corner, then by calculating a line between two corners and shifting all the vertices based on the height of that line. Seems pretty straightforward.
My current issue is this: I'm using OpenGL, which provides an optimization called VBOs, which basically are (to my understanding) static copies of the mesh kept in GPU memory for speed. I render using VBOs because I only use three basic models (L-corner, straight-wall, and a cap to join walls when they don't meet in an L). If I have to manually fiddle with the vertices of my models, it seems like I'd have to replace the content of the VBO every tile, which pretty much negates the point of using them.
It seems to me that I might be able to use simple rotation and translation transforms to achieve a similar effect, but I can't figure out how to do it without leaving gaps between the tiles. Any thoughts?
You may be able to use a vertex program on your GPU. The main difficulty (if I understand your problem correctly) is that vertex programs must rely on either global or per-vertex parameters, and there is a strictly limited amount of space available for each.
Without more details, I can only suggest being clever about how you set up the parameters...