Description
Describe the project you are working on
Shaders for use in exports with different renderers (Forward+, Mobile or Compatibility for web)
Describe the problem or limitation you are having in your project
Different renderers support different sets of features. For example the new instance uniforms aren't supported in the Compatiblity renderer and textureLod is not supported on Mobile. If you use an unsupported feature in a shader, this will fail to compile and the material will not render.
Currently this means that either you need to settle for the lowest common supported features for your platforms, or make different shaders for different renderers and assign them using some mechanism on load based on the renderer to use the more advanced versions when supported.
Describe the feature / enhancement and how it helps to overcome the problem or limitation
The recently added shader preprocessor could I think have the potential to make this process much smoother by adding symbols available to the preprocessor describing features available on the current renderer:
For example a RENDERER_FEATURE_INSTANCE_UNIFORMS
that is defined when the renderer is Forward+ or Mobile and not on Compatibility renderer.
Using these symbols you could then write your shaders with fallbacks like:
#if defined(RENDERER_FEATURE_X)
<code that uses feature X>
#else
<fallback code>
#endif
Meaning this shader could compile and be used on any renderer, but only include feature X when it's supported.
Describe how your proposal will work, with code, pseudo-code, mock-ups, and/or diagrams
I'm not familiar with how the preprocessor is set up, but I imagine this could be done by the preprocessor asking the current renderer for a list of available supported features and then adding those as hidden #defines
in some scope that is available to the shader preprocessor.
Another benefit to this approach is that as support for advanced features is added to renderers they can simply add these features to their list of supported features, and any shaders using these preprocessor symbols will compile using the now supported features automatically. Instead of the more clumsy approach of for example checking if we're using the mobile renderer and then applying the mobile version of the shader, which will not automatically update if the mobile renderer starts supporting more features.
Finally, since the visual shader system is as I understand it basically a shader code generator, this system could also use this preprocessor functionality to add fallbacks for features that are not supported on all renderers. For example making instance uniforms fall back to constants or shader uniforms if instance uniforms aren't supported instead of failing to compile.
If this enhancement will not be used often, can it be worked around with a few lines of script?
As discussed above you can work around this by making multiple shader versions for different renderers, but it has drawbacks as noted above.
Is there a reason why this should be core and not an add-on in the asset library?
I think both the shader preprocessor and renderer functionality that would be needed are part of the core.