You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
A multi-platform game using instance uniform shaders.
Describe the problem or limitation you are having in your project
Instance shader uniforms/parameters are very useful and a great recent addition in Godot 4. Designing systems around this functionality makes it much easier in my mind to implement a lot of shader based graphical effects on game objects, since it allows you to set and vary the properties on the objects while reusing the same shader, instead of having to maintain separate shaders with their own shader properties per object.
The limitation I'm encountering here is that instance shader uniforms currently aren't supported in the Compatibility renderer, and it's currently not tracked as a planned feature to support in the future.
There may be good technical reasons for this, but it's a problem since it means that if you design your code around using instance uniforms for effects this becomes very hard to adapt to also work on the Compatibility renderer. And currently the Compatibility renderer is the only option for web exports and may also be used as a fallback (automatically?) on other platforms if hardware doesn't support the Vulkan-based renderers. This means that to ensure broad compatibility you either can't use instance uniforms, or you need to set up a parallell set of shaders and code handling to use in compatibility mode.
Describe the feature / enhancement and how it helps to overcome the problem or limitation
The best solution here would be to add actual support for instance shader uniforms in the Compatibility renderer. However, I assume that there are good reasons for why this has not been done, and may not be possible.
So I propose instead to add an automatic conversion/translation feature, where instance shader uniforms can still be used in game projects but when run in the Compatibiliity renderer these are translated to regular shader uniforms on separate shader instances instead. So the same shaders and script code can be used across all renderers without modification, with the same effects (but without the performance benefits on Compatibility).
Describe how your proposal will work, with code, pseudo-code, mock-ups, and/or diagrams
To support instance uniform use in the Compatibility renderer I imagine something like this could be done in compatibility mode:
Detect in each shader if they use instance uniforms at shader compile time. If they do, translate the instance uniforms to regular shader uniforms and mark the shader with a "instance_uniforms" flag.
When a shader material is applied to a geometry check for this "instance_uniforms" flag on the shader, and if it is present, automatically use a separate instance of the shader material for each geometry.
Modify set_instance_shader_parameter() and get_instance_shader_parameter() on GeometryInstance3D to instead access the assigned shader material and use set_shader_parameter() and get_shader_parameter() to set/get the shader instance converted uniforms.
This way a shader could be defined with an instance uniform, but on compile this would be converted to a regular supported shader uniform in Compatibility mode. By ensuring all geometries automatically get individual instances of the shader it would retain the "per instance" functionality. And finally by forwarding set_instance_shader_parameter() to set_shader_parameter() on the shader the same code can be used without modification to get the same result.
If this enhancement will not be used often, can it be worked around with a few lines of script?
It can be worked around, but it requires a lot of work. Basically you need to set up a separate "Compatibility"-version of each shader where the instance uniforms are replaced with regular uniforms. And for each object you then need to detect if the game is in compatibility mode and then assign the correct shader, make sure it's instanced for each object and use the correct shader uniform type get/set methods.
This is also extra tricky since there's no direct exposed as far as I know of detecting if the game is running in compatibility mode or if the current renderer supports instance uniforms (see #6207).
Is there a reason why this should be core and not an add-on in the asset library?
If this conversion was done in the engine the same code for both shaders and scripts could be used for all renderers and getting the game to work in the Compatibility renderer would be much less of a hassle.
The text was updated successfully, but these errors were encountered:
I agree with this. Instance uniforms are a great addition to Godot 4, and they'd be very useful in compatibility. For my own project, I'd like to have compatibility mode as a fallback for players who don't have up to date hardware. It takes a lot of extra work to make two versions of every shader.
Calinou
changed the title
Instance shader uniforms support/fallback in Compatibility renderer
Add instance shader uniforms support/fallback in Compatibility renderer
Aug 9, 2023
+1 here, not only for the fallback for older hardware but considering compatibility mode to be much better performant when using XR/VR, it would be great to have that feature supported in the compatibility mode. For now I've just been avoiding the feature but it certainly makes a lot of things easier/more efficient.
I'm sure this is something that can be added to Compatibility Renderer, blender 3.3 also uses Opengl 3.x and it can do something similar to instance shader uniform/parameter in the shader editor using the "Object info" "Random" output socket, it also also do it using Custom attribute passed through geometry Nodes
Describe the project you are working on
A multi-platform game using instance uniform shaders.
Describe the problem or limitation you are having in your project
Instance shader uniforms/parameters are very useful and a great recent addition in Godot 4. Designing systems around this functionality makes it much easier in my mind to implement a lot of shader based graphical effects on game objects, since it allows you to set and vary the properties on the objects while reusing the same shader, instead of having to maintain separate shaders with their own shader properties per object.
The limitation I'm encountering here is that instance shader uniforms currently aren't supported in the Compatibility renderer, and it's currently not tracked as a planned feature to support in the future.
There may be good technical reasons for this, but it's a problem since it means that if you design your code around using instance uniforms for effects this becomes very hard to adapt to also work on the Compatibility renderer. And currently the Compatibility renderer is the only option for web exports and may also be used as a fallback (automatically?) on other platforms if hardware doesn't support the Vulkan-based renderers. This means that to ensure broad compatibility you either can't use instance uniforms, or you need to set up a parallell set of shaders and code handling to use in compatibility mode.
Describe the feature / enhancement and how it helps to overcome the problem or limitation
The best solution here would be to add actual support for instance shader uniforms in the Compatibility renderer. However, I assume that there are good reasons for why this has not been done, and may not be possible.
So I propose instead to add an automatic conversion/translation feature, where instance shader uniforms can still be used in game projects but when run in the Compatibiliity renderer these are translated to regular shader uniforms on separate shader instances instead. So the same shaders and script code can be used across all renderers without modification, with the same effects (but without the performance benefits on Compatibility).
Describe how your proposal will work, with code, pseudo-code, mock-ups, and/or diagrams
To support instance uniform use in the Compatibility renderer I imagine something like this could be done in compatibility mode:
set_instance_shader_parameter()
andget_instance_shader_parameter()
on GeometryInstance3D to instead access the assigned shader material and useset_shader_parameter()
andget_shader_parameter()
to set/get the shader instance converted uniforms.This way a shader could be defined with an instance uniform, but on compile this would be converted to a regular supported shader uniform in Compatibility mode. By ensuring all geometries automatically get individual instances of the shader it would retain the "per instance" functionality. And finally by forwarding set_instance_shader_parameter() to set_shader_parameter() on the shader the same code can be used without modification to get the same result.
If this enhancement will not be used often, can it be worked around with a few lines of script?
It can be worked around, but it requires a lot of work. Basically you need to set up a separate "Compatibility"-version of each shader where the instance uniforms are replaced with regular uniforms. And for each object you then need to detect if the game is in compatibility mode and then assign the correct shader, make sure it's instanced for each object and use the correct shader uniform type get/set methods.
This is also extra tricky since there's no direct exposed as far as I know of detecting if the game is running in compatibility mode or if the current renderer supports instance uniforms (see #6207).
Is there a reason why this should be core and not an add-on in the asset library?
If this conversion was done in the engine the same code for both shaders and scripts could be used for all renderers and getting the game to work in the Compatibility renderer would be much less of a hassle.
The text was updated successfully, but these errors were encountered: