-
-
Notifications
You must be signed in to change notification settings - Fork 97
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Implement tessellation as an alternative to parallax occlusion mapping #5995
Comments
Note I am by no means a graphics programmer, but researching this a bit more, it seems it is possible to implement into the core of Godot 4.0's Vulkan renderer without geometry shaders by implementing tessellation stages. https://registry.khronos.org/vulkan/specs/1.3-khr-extensions/html/chap22.html |
In a way similar to geometry shaders, tesselation has lost a lot of traction over the years. These days, it's more common to use actual geometry to represent bumps in surfaces where it matters (plus a LOD system or virtualized geometry). Modern GPUs can handle a lot of triangles as long as they're not smaller than a pixel (which causes those triangles to be rasterized through a slow path). On the other hand, a lot of GPUs1 implement tesselation in a slow manner, making the added implementation complexity not worth it in most cases.
See #1942. I've tested godotengine/godot#65307 and it doesn't resolve the issue with POM shadowing, but that could be done with further changes.
This can be implemented in a shader, but it's very expensive due to the high number of texture fetches required. To my knowledge, using tesselation won't resolve this issue, as you still need to perform those texture reads to modify the underlying geometry. Footnotes
|
@Calinou do you have any details on the performance thing with NVidia? Wouldn't that be when using geometry shaders? There are modern examples of tessellation made for consoles only, which are AMD chips. Like the Demon's Souls remaster. |
Tessellation being slow on non-nvidia GPUs is a valid concern, but I think there are cases in which this is the most sane approach: one of them is having a large geometry with fine details in which both close-up and far away elements may be visible at the same time (prime examples of this would be terrain, large bodies of water etc.). In those cases other methods I know either don't work or are rather hacky:
So unless tessellation performance makes it unusable, I think it'd be better then all of the solutions above in cases like terrain and water. @myaaaaaaaaa you propose to run tessellate() before vertex(). In both vulkan and opengl tessallation seems to be a step after vertex shader. So the pipeline probably has to be done more like in those apis:
Tessellation evaluation coule be named something like There's a quite nice sample of tessellation shaders in https://github.com/KhronosGroup/Vulkan-Samples in case someone tries to implement this: |
I would like to add support for seeing tessellation implemented in Godot 🌐 In my use case, it would be a major fidelity boost for curved model silhouettes in XR content (see PN-Triangles for reference), where it is not predictable how close the camera will ever be to any object, and where tessellation would save an otherwise unreasonable amount of LOD file size to achieve a similar result. Additionally, as suggested here, using realtime tessellation for a large amount of models would save significantly on memory usage. A use case of tessellation shaders for skewed viewing angles of large meshes such as terrain can be found in #6279 (comment) and #445 (comment). Silhouette tessellation may also relate to the implementation of OpenSubdiv proposed in #784, but as it operates realtime on the CPU it is my understanding that GPU realtime tessellation would be more performant (and potentially more flexible for non-uniform tessellation). I would also like to ask for clarification if there is a possibility to achieve tessellation-like behaviour using compute shaders, as suggested by @fire in #2075 (comment), and adjacently suggested in this comment? It appears that @painfulexistence is experimenting with adding tessellation, as mentioned in #6121 (comment). While I am not graphics engine programmer, I am willing to learn if it can help contribute the feature of tessellation to core Godot. |
https://github.com/v-sekai/godot-subdiv needs a implementation of vulkan compute shaders. See also PixarAnimationStudios/OpenSubdiv#1153 Friendly note. The currently implementation of opensubdiv requires a gdscript plugin. I wasn't able to find effort to port it to C++. It should be in c++ though. Edit: Ported to godot engine c++ modules. |
This comment was marked as off-topic.
This comment was marked as off-topic.
Yes, It could be a compute shader implementation but the current way they work requires a sync read back to CPU which invalidates their usage for anything happening each frame. My scenario I managed to get the compute shader part working, but no hopes in making the result go to the normal render pipeline like a normal Mesh would go, without actually reading the data back to CPU and creating the ArrayMesh. This basically turns compute shaders not useful for this kinds of tasks since the CPU syncs eats up any performance gains that we would otherwise gain. In conclusion... If compute shaders were allowed to
Then they would be game-changing useful and allow things that truly harness the power of GPU's, like implementing compute shader based tesselation and virtual geometry. |
Hi Erick, I am LITERALLY doing exactly the same thing right now, and I've been chasing the problem for several days without any luck. Like you, I can get vertices onto the GPU in a compute shader, but I can't figure out how to get it to actually draw it without going through the CPU. If you figure it out please tell me! |
Well, the 'solution' I ended up isn't ideal, I figured out how to bind textures generated by the compute shader into a normar custom shader material, then my custom shader does texel fetches on the texture to get the vertex data. The only problem is the memory overhead because for it to work I needed a dummy vertex array and indices so that the vertex counts worked correctly, otherwise the shader wouldn't know how many vertices and what triangles to draw, since there is no way to do a drawProceduralIndirect like Unity does, obtaining indices info from buffers. So my half baked solution leaves a lot of memory unused since I need to allocate the maximum size I could get in the generating phase and in the shader drop the vertices that overflow the actually generated count. Also idk but I think reading from textures aren't as efficient as from structured buffers (if they were supported) You can see it in my github: https://github.com/erickweil/GodotTests |
Cool! I was recommended by a friend that it might be possible to use an atomic counter to "append" stuff to the buffer. IIRC, each tetrahedron can get sliced into... 0, 16, 24, or 32 triangles? I don't remember. Point being, it might be able to save some space by using an atomic counter and banking on how every tetrahedron probably isn't going to require the maximum number of output triangles. If one tetrahedron outputs 0 triangles, that leaves space for another tetrahedron to output many triangles. EDIT: oh look at that you're already using it. sick |
See also https://github.com/AIFanatic/three-nanite.
Like for example you take a mesh, use a subdivision library like https://github.com/tefusion/godot-subdiv and present tesselation backwards as lod. |
@erickweil Maybe you write a proposal on adding to the Godot Engine api to obtain indices info from buffers for the dummy vertex array and indices problem? |
https://github.com/gamma-delta/HelloComputeGeometry Here's my implementation of Erick's idea, if someone wants another perspective |
Describe the project you are working on
Various 3D projects, including the Waterways add-on
Describe the problem or limitation you are having in your project
It's difficult or impossible to manage high density details in Godot at the moment. Especially with non-static meshes such as water, hair, deforming snow.
While POM can help with adding fine detail it has a lot of limitations:
While Godot 4 can handle a lot more geometry than Godot 3.x, I don't think it's feasible to add all this detail into the meshes for most users. Even if Godot eventually gets some kind of virtualised geometry solution similar to "Nanite", it is often much easier to add details with tiling textures than using dense meshes, both from an asset creation point of view and dealing with the asset import / storage.
Describe the feature / enhancement and how it helps to overcome the problem or limitation
An option to enable dynamic tessellation on a material or mesh.
Describe how your proposal will work, with code, pseudo-code, mock-ups, and/or diagrams
I am aware that geometry shaders are getting deprecated, so this would have to be a custom compute shader implementation, but I do not know the details on how this would be done.
If this enhancement will not be used often, can it be worked around with a few lines of script?
This would be used often and cannot be done easily with a few lines of script.
Is there a reason why this should be core and not an add-on in the asset library?
This has to be done in core.
The text was updated successfully, but these errors were encountered: