To buffergeometry or not to bufferGeometry - three.js

I am rendering voxel data based on the approach described here. Unfortunately he uses face4 quads which was deprecated a long time ago (r60). I am reimplementing it to use tris and while I was initially going to go for a bufferGeometry as there is a huge amount of triangles (500,000), there are also a large amount of overlapping vertices in the data.
It is my understanding that geometries can reuse verts but bufferGeoms cannot, so calling mergeVertices wont work. Will I get more of a speed advantage from bufferGeometry or the geometry class?

Just to let anyone who may be interested know, I first created a geometry object and called mergeVertices. It worked well be started crawling for larger scenes. I converted it to bufferGeometry using bufferVol = new THREE.BufferGeometry().fromGeometry(vol); and managed to get a performance improvement.

Related

What is Buffer Geometry of three.js?

The explanation presented in the three.js documentation about the command BufferGeometry is quite hard to understand to me.
It says..
BufferGeometry is a representation of mesh, line, or point geometry.
Includes vertex positions, face indices, normals, colors, UVs, and
custom attributes within buffers, reducing the cost of passing all
this data to the GPU.
I didn't quite understand what those sentences meant.
What is the purpose of BufferGeometry? How do you visualize BufferGeometry in real life?
Thank you!
An instance of this class holds the geometry data intended for rendering.
If you want to visualize these data, you have to define a material and the type of 3D object (mesh, lines or points). The code example of the documentation page shows the respective JavaScript statements.

difference between InstancedMesh and Object3D.clone() in three.js

i've been learning how to improve the performance of my 3d apps, i've been told that i can use Object3D.clone() to duplicate identical objects, and i can use InstancedMesh when rendering numbers of objects with same geometry and material to improve performance. Could someone please tell me what's the difference between them.
Using Object3D.clone() means each cloned 3D object is rendered with an individual draw call. However, this approach might downgrade the performance of your app since the number of draw calls is an an important performance metric of 3D applications. It should be as low as possible.
Using InstancedMesh can help to decrease the number of draw calls since all its instances are render with a single draw call.
So instead of cloning objects, you should use instanced rendering whenever possible.

three.js mesh rendering too slow

I have three layers (Object3D) each has about 20K sphere geometries. The rendering is making the whole browser stuck. Is there any way for faster rendering of these objects? As few other answers on SO, I am using same geometry and re-using three materials created only once. Also, these are dynamic objects and cannot use pre-generated json. Thanks in advance!
It’s slowing down because of the overhead involved when drawing each sphere.
Instancing here helps by reducing both the drawcall overhead and potentially removing nodes for the matrix updates.
Thee.js has a low level interface that does not work on the scene level.
You can try this 3rd part module https://www.npmjs.com/package/three-instanced-mesh

InstancedBufferGeometry intersection not happening

I tried the Instancedbuffergeometry, it works awesome,
Intersection is not happening in InstancedBufferGeometry, i checked in the threejs(r85) library, checkBufferGeometryIntersection function have the position value only, I think the offset and orientation value need to use with the position.
I have another doubt in it, i have used one rawshadermaterial only, then how i can highlight the selected geometry.
Can anyone guide in it.
Thanks in advance.
As far as the cpu is concerned (where you do the raycasting) those instances do not exist. You do however have your master geometry available. What you can do is, create another instance of BufferGeometry then create the same number of Mesh objects using that one instance of geometry. Use the same logic for instancing to place this into a scene. You don't render them, thus saving the overhead from multiple draw calls. You do have them available for intersection though as if it were normal geometry, because it is (you're just not rendering it).
As #pailhead already wrote, raycasting with instanced-geometries cannot work.
An alternative approach to achieve the same goal is to use so-called GPU picking. For this you render the scene into a framebuffer, using a special shader that will just output a unique color-value for every instance.
You can then sample the point under the cursor from that framebuffer and compute the instance-id from the color-value.
You can see an example for this technique here or here.

What is the most efficient way in three.js to update a face color independently across many meshes that all share the same geometry?

In a three.js project (viewable here) I have 500 cubes, all of the same size and all statically positioned. On each of these cubes, five of the faces always remain the same color; however, the color of the sixth face can be dynamically updated, and this modification occurs across many of the cubes in a single frame and also occurs across most frames.
I've been able to implement this scene several different ways, but I have not been completely satisfied with the performance of anything I've tried. I know I must not have hit upon the right technique yet or maybe I'm not implementing one quite right. From a performance standpoint, what is the best way to change the color of these cube faces while maintaining independence across each of the cubes?
Here is what I have tried so far:
Create 500 individual CubeGeometry and Mesh instances. Change the color of a geometry face as described in the answer here: Change the colors of a cube's faces. So far this method has performed the best for me, but 500 identical geometries seems less than ideal, especially because I'm not able to achieve a regular 60fps with a good GPU. Rendering takes about 11-20ms here.
Create one CubeGeometry and use it across 500 Mesh instances. Create an array of MeshBasicMaterials to create a MeshFaceMaterial for each Mesh. Five of the MeshBasicMaterial instances are the same, representing the five statically colored sides of each cube. Create a unique MeshBasicMaterial to add to the MeshFaceMaterial for each Mesh. Update the color of this unique material with thisMesh.material.materials[3].uniforms.diffuse.value.copy(newColor). This method renders quite slower than the first method, 90-110ms, which seems surprising to me. Maybe it's because 500 cubes with 6 materials each = 3000 materials to process???
Any advice you can offer would be much appreciated!
I discovered that three.js performs a WebGL draw for each mesh in your scene, and this is what was really hurting my performance. I looked into yaku's suggestion of using BufferGeometry, which I'm sure would be a great route, but using BufferGeometry appears to be relatively difficult unless you have a good amount of experience with WebGL/OpenGL.
However, I came across an alternative solution that was incredibly effective. I still created individual meshes for each of my 500 cubes, but then I used GeometryUtils.merge() to merge each of those meshes into a generic geometry to represent the entire group of cubes. I then used that group geometry to create a group mesh. An explanation of GeometryUtils.merge() is here.
What's especially nice about this tactic is that you still have access to all the faces that were part of the underlying geometries/meshes that you merge. In my project, this allowed me to still have full control over the face colors that I wanted control over:
// For 500 merged cubes, there will be 3000 faces in the geometry.
// This code will get the fourth face (index 3) of any cube.
_mergedCubesMesh.geometry.faces[(cubeIdx * 6) + 3].color

Resources