Unity based layout algorithm of 3d force oriented graph (ComputeShader)

Before topology layout and flow display, I studied two algorithms, one of which is force oriented graph layout algorithm. Let me briefly talk about the idea of force oriented graph and why ComputeShader should be used.

Principle demonstration

I use a cube to represent nodes. The following is the layout preview of the two algorithms. This article only discusses the latter.

1. Domain based layout (not discussed in this article)

2. 3D force guidance layout (in layout, the optimal position has not been reached yet)

If the Y axis is ignored in the calculation, it is a normal 2D force guidance diagram.

Principle of force guidance diagram

The algorithm I used is very simple. Two sentences are enough:

  • Each unit is a positively charged particle, and there will be a Coulomb force between every two of them. The force is inversely proportional to the square of the distance.
  • There is a spring between the connected units, with a fixed length of L, and objects with a distance of more than L attract each other, and vice versa.

According to the final force result, calculate its displacement (or the force exerted by the rigid body), and then sort it. After a period of sequencing, the force gradually reaches equilibrium, and the state of each particle tends to be stable.

How to calculate

The force F1 is calculated according to the Coulomb force formula, and the force F2 is calculated according to the spring deformation formula. F equals F1+F2.

  • To calculate the coulomb force, it is necessary to traverse all particles (a, b,c,d…),F1 = Fa + Fb + …。
  • When calculating the elastic force, we need to find the parent and child objects according to the relationship between the edges in the graph.

Finally, the displacement can be calculated according to the resultant force.

Why use ComputeShader

The CPU is not suitable for simple and large number of repeated operations. The parallel computing capability of the CPU is very poor, and its branch prediction unit and storage unit are useless for large number of repeated operations. On the other hand, GPUs can easily have hundreds or thousands of stream processors, and can perform a large number of repetitive and simple tasks at the same time.

Taking 1000 points as an example, in the case of no optimization, 1000 * 1000 operations are required for each calculation of coulomb force, and each operation at least includes two basic operations, namely, distance calculation of 3D vector and division. If you put these into the Unity main thread for calculation, you will find the light 3D vector Vector3 The calculation of takes up most of the CPU time, and the frame rate will be terrible.

For the irrelevant and huge number of calculations, we can completely throw it to the GPU for calculation. The CPU just needs to assign a value and wait for the value. Because GPU parallel task processing is extremely fast, its running speed is almost real-time.

The above "irrelevant" means that the calculation of one thread does not depend on the calculation results of another thread. Each time we calculate, all nodes are fixed, so the calculation process does not depend on the calculation results of other threads.

When the calculation is fast enough

In order to reduce the amount of CPU code execution when using CPU computing, I have done some optimization work. For example, after calculating the coulomb force F (ab) between A and B, I will not repeat the calculation of the coulomb force between B and A, but directly use - F (ab). But even in this case, in the scenario with more than 700 points, the CPU calculation will also directly GG.

After using ComputeShader, I found it unnecessary to use the optimization above, because it not only increases the complexity of thread code, but also does not bring much benefit. I have tested the two methods, and the calculation speed is no different. A single calculation is done in seconds.

epilogue

After migration to the GPU for calculation, for more than 5000 points, one calculation per frame is basically not stuck. For the case below 5000 points, the calculation times can be increased for each frame as appropriate.

After the number of points increases, the amount of data transmission between the CPU and the GPU will also increase. To maintain efficiency, the Shader and ComputeShader can share the Buffer Graphics.DrawProceduralIndirectNow Directly notify GPU to draw. The direct drawing method can keep the frame rate above 1000 when drawing 1 million CUBE.

The direct GPU drawing method is not applicable to my scene, because these points need to click, hover, drag and other interactive logic.

Zimiao haunting blog (azimiao. com) All rights reserved. Please note the link when reprinting: https://www.azimiao.com/7662.html
Welcome to the Zimiao haunting blog exchange group: three hundred and thirteen million seven hundred and thirty-two thousand

Comment

*

*

Comment area

  1. Boss, can you get a code? Unity leads the layout