I'm drawing large amount of cubes (100 000+) using glDrawElementsInstanced(). Due the performance reasons I'd like to implement frustum culling, but I'm not quite sure how to do that when I'm using instancing.
From what I know, the only way to access individual instance of object is in shaders, so I assume I have to do the culling there. I'm not quite sure how to do so.
Can anyone point me to any tutorials?
Trying to do culling in the vertex shader is way too late in the process. You have to feed the cube's transforms to the shaders somehow, just take that data and set up a Bounding Volume Hierarchy. Then only draw the instances that pass the frustum culling.
Related
I am working on a project where I have to implement voxel cone tracing for indirect light in C++/OpenGL. I already have a deferred renderer setup but most of the VCT examples I could find usually draw the scene once for voxelization and once with cone tracing shaders. Is it possible to run cone tracing shaders over a fullscreen quad and sample vertex data from the GBuffer or is that generally a stupid idea? Do I lose accuracy because I only have per pixel vertex data?
Is it possible to run cone tracing shaders over a fullscreen quad and sample vertex data from the GBuffer or is that generally a stupid idea?
Yes, however that's not voxel cone tracing anymore. That's Screen-Space Global Illumination (SSGI) instead. You can think of the voxelized scene in VCT as a 3D GBuffer, which makes all the difference between "screen space" and "full scene".
Do I lose accuracy because I only have per pixel vertex data?
Absolutely. All screen space approximations suffer from the same set of artifacts. They do not account for surfaces that aren't directly visible on the screen (either out of frame or occluded by visible geometry). Most noticeably, when the camera moves and objects enter or exit the frame, the reflections on visible surfaces would also change unrealistically.
A question is perhaps, what's your motivation for trying doing both.
When you do Voxel Cone tracing you are trying to solve the exact same problem you would be trying to solve with deferred rendering and now have the overhead of both techniques, if you are already willing to deal with the overhead of Voxel Cone tracing then it's better to fully commit to that technique.
The reason is simple, if you are doing voxel cone tracing then you have a 3D texture of some sort (could be voxel oct tree, and actual 3D texture or some other structure). That is essentially a 3D Gbuffer.
If your idea is simply to eliminate the need for such a structure and use the existing planar GBuffer instead, then you are introducing artifacts that do not appear with traditional SSRT techniques.
In essence trying both at the same time is likely to give you the worst of both worlds rather than the best.
To draw a sphere, one does not need to know anything else but it's position and radius. Thus, rendering a sphere by passing a triangle mesh sounds very inefficient unless you need per-vertex colors or other such features. Despite googling, searching D3D11 documentation and reading Introduction to 3D Programming with DirectX 11, I failed to understand
Is it possible to draw a sphere by passing only the position and radius of it to the GPU?
If not, what is the main principle I have misunderstood?
If yes, how to do it?
My ultimate goal is to pass more parameters later on which will be used by a shader effect.
You will need to implement Geometry Shader. This shader should take Sphere center and radius as input and emit a banch of vertices for rasterization. In general this is called point sprites.
One option would be to use tessellation.
https://en.wikipedia.org/wiki/Tessellation_(computer_graphics)
Most of the mess will be generated on the gpu side.
Note:
In the end you still have more parameters sent to the shaders because the sphere will be split into triangles that will be each rendered individually on the screen.
But the split is done on the gpu side.
While you can create a sphere from a point & vertex on the GPU, it's generally not very efficient. With higher-end GPUs you could use Hardware Tessellation, but even that would be better done a different way.
The better solution is to use instancing and render lots of the same VB/IB of sphere geometry scaled to different positions and sizes.
I'm trying to develop a high level understanding of the graphics pipeline. One thing that doesn't make much sense to me is why the Geometry shader exists. Both the Tessellation and Geometry shaders seem to do the same thing to me. Can someone explain to me what does the Geometry shader do different from the tessellation shader that justifies its existence?
The tessellation shader is for variable subdivision. An important part is adjacency information so you can do smoothing correctly and not wind up with gaps. You could do some limited subdivision with a geometry shader, but that's not really what its for.
Geometry shaders operate per-primitive. For example, if you need to do stuff for each triangle (such as this), do it in a geometry shader. I've heard of shadow volume extrusion being done. There's also "conservative rasterization" where you might extend triangle borders so every intersected pixel gets a fragment. Examples are pretty application specific.
Yes, they can also generate more geometry than the input but they do not scale well. They work great if you want to draw particles and turn points into very simple geometry. I've implemented marching cubes a number of times using geometry shaders too. Works great with transform feedback to save the resulting mesh.
Transform feedback has also been used with the geometry shader to do more compute operations. One particularly useful mechanism is that it does stream compaction for you (packs its varying amount of output tightly so there are no gaps in the resulting array).
The other very important thing a geometry shader provides is routing to layered render targets (texture arrays, faces of a cube, multiple viewports), something which must be done per-primitive. For example you can render cube shadow maps for point lights in a single pass by duplicating and projecting geometry 6 times to each of the cube's faces.
Not exactly a complete answer but hopefully gives the gist of the differences.
See Also:
http://rastergrid.com/blog/2010/09/history-of-hardware-tessellation/
I am planning on writing a 3D game that will be using VBOs for rendering. Let's say, for example, that the terrain is a set of tiles and their vertices are all in the same VBO. The player should be able to scroll through the tiles, and at all times would see only a part of them.
I would like to perform frustum culling on those tiles. I already have found some sources on the maths part of frustum culling, but I am not sure how I would go about implementing this with a VBO - do people do that somehow in the vertex shader, or do they just call the rendering function to draw a subset of the VBO.
Given that your camera acts like in Diablo (wherever Isometric or with Perspective):
If you have a fixed map size, you can use 1 VBO for the base geometry of your map, Assuming you will use a heightmap based solution. The Quads not visible will be discarded by your graphics card after the vertex shader, not affecting your pixel fillrate. They are not worth the overhead of culling on your side. Details like Rocks, Houses etc will have their own VBO anyways.
If you aim for a streaming content engine with a huge seamless world, create chunks, the size of a chunk depends on your game. Divide your terrain into those chunks and test the camera frustum against their bounding boxes before drawing.
About drawing chunks:
The simplest way, which is enough for most games, is to make each chunk its own geometry, VBO, and so on. But you can optimize later and your terrain implementation should not drive your engine API designs (you will have to implement many different ways to draw things in your engine, for instance particles, post processing effects, etc..).
One way you can optimize is with only one VBO for the geometry and the usage of instanced drawing, just like in particle systems you then take some other source for some of your data, like your global transformation, the height of each vertex and so on.
But keep in mind, most games dont really need that much optimization in just the terrain. There will come other systems across your path more worthy of optimizations.
I just started learning opengl and writing a first person shooter but I'm getting horrible framerates when I draw 5000 cubes. So now I'm attempting to perform occlusion and culling using an octree. What I'm confused about is where to cast the rays from. Do I only cast them from the fustrum near plane? It seems like I would miss part of the fustrum that expands. Any help is appreciated.
If 5000 cubes already gives bad framerates, you should consider changing the way you render your cubes.
It's very unclear to us what you are drawing the cubes for. If they are static (ie. don't move), then its best to pack them all into a single vertex buffer. If the cubes are supposed to move, then you should go for instancing. If you're going for a landscape made of cubes like minecraft, then you should create vertex buffers but only put in the faces of cubes that are actually visible.
I'd like to help more, but I'm unsure what you're doing.