Question about Culling (if this is even the correct term)

Ok, so I have a large grass object made from merged BufferGeometries. Everything looks great (well…almost), but I have one issue.

Slower computers are going to struggle. Of course I can reduce the amount of geometry in the object, and I will make that an adjustable setting, however I would also like to be able to set a “max view distance” setting as well.

I’m curious how to go about it. Since it’s technically one large object, I can’t really do what I normally do and toggle mesh visibility by distance from the camera.

Can I limit view distance in the shader itself? That would be awesome (I did figure out how to apply fog in a custom shader, yay me lol).

If not, what? Create a second render pass with maybe a different camera far/near setting or something?

Clipping Planes?

Any nudge in the right direction would be most appreciated =]

You could use the far plane of the perspective camera: https://threejs.org/docs/index.html#api/cameras/PerspectiveCamera.far

This will cull everything beyond the distance set. It will cause a hard edge at the point where it cuts off which is where you can use fog to soften it.

Yes, but this would cut everything in the scene off, not just the grass object.

However, I was thinking of doing something like this in a second scene using a second render pass and a separate perspective camera.

Not sure if that is the best way to go though.

I’m using a custom shader material, and am curious if this culling could be done in the shader code.

Ah right, so you want to use the distance culling on only the grass model, and not the rest of your scene?

I’m not too sure of how to solve this, but could possibly use a second camera with your changed far plane, and pass it’s projectionMatrix to your custom shader?
So when gl_Position = projectionMatrix * modelViewMatrix * vec4(position,1.0); is run by the shader, use your custom projectionMatrix instead?

You can’t do anymore at this point. i’m currently implementing a vegetation module for my engine to render massive forests and fast grass generated on the fly. In order to cull i use a spatial chunked approach in a octree. Depending on your wanted result or how you deal with the terrain, you could share the geometry with multiple meshes and do the rest in the shader (adapting height of a heightmap for example).

If the scene is very large spatial management should be considered anyway, as well as using instances or a static “bunch of grass” geometry to use in a tiled manner or as i mentioned, performing the placement in the shader.

For a simple quick solution you could split your grass-field into a chunked raster clustering all grass-blades for example by a 8x8 grid of BufferGeometries, depending on the density and size of your scene to get a well balanced draw-call / triangle count.

I’m using a custom shader material, and am curious if this culling could be done in the shader code.

For better performance, you definitively want to sort out objects on CPU side. If you have all your entities in a single geometry, you have to split things up and manage them separately. Think of it like having different areas of detail.

Just google for open-world approaches in videogames. You should be able to find many resources about this topic.

Wow, thought this would be the easy part lol. Wrong again =]

So it sounds like the solution, if I am understanding correctly, is to split the large single object into smaller mesh’s and handle them accordingly.

From here I suppose I could just toggle each individual mesh’s visibility parameter based on distance from the camera. However you guys are mentioning octrees and spatial indexes, so apparently there is a much cooler way to do this than my simple approach.

Need to study up apparently.

I’m assuming this is related to the following suggestion on github?

Ok so did a little research on octrees and spatial indexing. Learned some things.

This looks great:
https://threejs.org/examples/webgl_octree.html

Super cool stuff. I am definitely going to implement this if for anything, collision detection.

Question…

Ok so I build my octree, determine which meshes are nearby. Do I just toggle the meshes visibility based on results? I was hoping the clipping/plane/2nd render pass idea would work so that the grass would sort of ehhh… fade in (or draw in or w/e). With the visibility parameter toggle, things will sort of just popup/popout (at a distance).

If this is the best option, so be it, just want to make sure I am doing this as correct as possible.

The most pleasant solution is to implement a shader for it, but you can also just extend a Lambert one for example to fade opacity and maybe scale by a given radius to the camera.

Hardcoded it could be in the vertex shader something like

vOpacity = 1.0 - min(length(worldPosition.xyz - cameraPosition) / 2000.0, 1.0);

What would linear fadeout to a distance of 2000 units around the camera, so you would need to ensure that your grass chunks are visible in this range, then there won’t be any popping.

Notice linear - you can take the code of the fog for example to go with a near/far or exp to not start fading too early.

Oh, awesome idea! Thank you. Thank all of you guys for your help =]

Would for terrain a quad tree make more sense than an octree?