![]() |
We have a new example examples/viewport_and_scenes/mesh_update that may be quite useful to many developers. It shows two approaches to update a mesh at runtime. This has a lot applications — e.g. you may want to animate / deform the mesh following some algorithm or allow for some user interactions or game events to change the mesh.
Quoting from the example README:
This example demonstrates how to dynamically (as often as possible, to reflect e.g. time passing by) update the mesh of a 3D object, while still being efficient. There are 2 approaches:
- Call
TCoordinateNode.SetPointas often as you want, e.g. from view’sUpdatemethod.In this example, every
TViewMain.UpdateincreasesTimeand then callsTViewMain.UpdateCoordinateNode. TheTViewMain.UpdateCoordinateNodeupdates the coordinates of the 3D object, theTimeaffects the waves shape.The point here is that
TCoordinateNode.SetPointis very efficient. It only updates the necessary rendering resource (VBO contents in OpenGL) and doesn’t do any unnecessary work (doesn’t rebuild anything, doesn’t recreate any resource from scratch). -
Use shaders. You can use our shader effects to add a vertex shader that changes the position of each vertex right when it’s supposed to be displayed.
The advantage is that this is even faster because the Pascal code does almost nothing — we just pass the new
Timevalue to the shader. The per-vertex calculation is done by GPU, and GPUs are ridiculously fast at this.On one test system:
- The first approach (TCoordinateNode.SetPoint) was able to handle 100 x 100 grid with 60 FPS. But once grid size increased to 200 x 200 it dropped to 18 FPS (in debug) or 38 FPS (in release).
Note that changing the height calculation (to avoid
Sinin Pascal) does not significantly change these measurements. TheSin, and in general how theHis calculated in Pascal, is not a bottleneck. -
And the shader approach could handle 1000 x 1000 grid with 60 FPS. At 2000 x 2000 grid it dropped to 20 FPS. So, it’s 100x more performant, if you look at the number of triangles it can handle while still maintaining 60 FPS!
Note that changing the height calculation (to avoid
sinin GLSL) does not significantly change this. Neither does debug vs release build (which makes sense, since the speed of Pascal code cannot be the bottleneck here).
Note: For stress-testing, consider setting initial
CheckboxShader.Checkedin design totrue, to start with more performing version immediately.The disadvantage is that Castle Game Engine is not aware of the calculated vertex positions (they remain only on GPU). So e.g. any raycasts or other collision queries will treat this mesh as if it was in the original position (flat plane in this example).
An additional potential disadvantage is that you need to learn shading language, more specifically OpenGL Shading Language (GLSL). There’s a small piece of GLSL code in data/animate_mesh.vs.
- The first approach (TCoordinateNode.SetPoint) was able to handle 100 x 100 grid with 60 FPS. But once grid size increased to 200 x 200 it dropped to 18 FPS (in debug) or 38 FPS (in release).
I encourage you to experiment with this example and try to stress-test it. It should handle very large values of GridWidth and GridHeight.

Start the discussion at Castle Game Engine Forum