Skip to content
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

Add an option for custom shader functions to materials #1779

Open
Lexpartizan opened this issue Nov 5, 2020 · 6 comments
Open

Add an option for custom shader functions to materials #1779

Lexpartizan opened this issue Nov 5, 2020 · 6 comments

Comments

@Lexpartizan
Copy link

Describe the project you are working on:
I'm working on a rain shader.
https://github.com/Lexpartizan/Godot_rain_shader

Describe the problem or limitation you are having in your project:
I have a lot of standard materials that should get wet in the rain.
And now I need to manually alter all these environment materials to fit my shader. And this can be quite complex materials, painstakingly customized by artists.
I think this problem will arise wherever you need to have some kind of shader effects for many game entities with different materials.

Describe the feature / enhancement and how it helps to overcome the problem or limitation:
I think the material in the engine is still converted to a shader. At least I think so. I suggest adding the "additive shader" option to the material settings, where you can specify a resource containing custom Shader code. It should look like this: when adding such a resource, its variables are added after the existing list of variables main shader. Commands from the vertex resource function to the end of the vertex function of the main shader, and so on.
This will allow you to access ALBEDO to get the albedo value, perform calculations, and write the new value to ALBEDO. And thus make a darkening for a wet surface, for example.

Describe how your proposal will work, with code, pseudocode, mockups, and/or diagrams:
This could be implemented using the #include preprocessor directives.
This could work with the existing next_pass option, but unfortunately it is not possible to get the values of ALBEDO, ROUGHNESS, etc from previous pass. So these are slightly different concepts.
I have no experience with other game engines and I do not know how this problem is solved there.
There may be a better way.
If this enhancement will not be used often, can it be worked around with a few lines of script?:
You can simply replace dozens or hundreds of materials with shaders, but this is not as convenient as standard materials.

There is a similar proposal #944 , but mine is a little different. I would like to keep the standard appearance of the material (it is more familiar and easier to configure), just by specifying a link to the code with additional features, such as exposure to rain, burning, and so on..

Is there a reason why this should be core and not an add-on in the asset library?:
I think this is a growth problem that the engine will face sooner or later, as a lot of users will want to use different effects on a lot of different objects with different materials.

@Calinou Calinou changed the title Add an option for custom shader functions to materials. Add an option for custom shader functions to materials Nov 5, 2020
@Dimev
Copy link

Dimev commented Apr 26, 2021

Maybe a way to override the default shader could work, with something like a before and after rendering function, which would automatically be added to generated shader code, and would allow changing values before or after the regular (shader)material has written to every value it needs for rendering.

Maybe some new render mode like use_default can also be added if things being overridden by the extra function is undesirable

@Calinou
Copy link
Member

Calinou commented Dec 30, 2021

See also #2595.

@dkaste
Copy link

dkaste commented Apr 23, 2023

I found some prior art related to this in the Heaps game engine. See the Shader Pipeline section here.

Unlike other shader models (GLSL, HLSL, etc.), HXSL allows several shaders to be linked together at runtime, allowing you to split your shader into several distinct effects that can be enabled/disabled easily, without having to maintain a single "Uber Shader" with all the possible combinations.

Each material "pass" has a list of shader fragments, which are combined into a single shader program based on priority numbers. I am not a huge fan of magic priority numbers, but this seems to work well enough in practice for Motion Twin and Shiro Games (the main users of Heaps).

@Calinou
Copy link
Member

Calinou commented Jun 26, 2023

We could implement this in BaseMaterial3D without adding too much complexity by letting users set custom prefix and suffix codes to the vertex(), fragment() and light() functions. There's already a hint for multiline expressions in the inspector so that basic syntax highlighting is provided (no autocompletion or in-editor error checking, though).

I assume that we need both prefix and suffix blocks for each function, as you sometimes want to call your own code before the built-in shader code, and sometimes after. Correct me if I'm wrong.

However, this is best suited for quick tweaks as you wouldn't be able to use external shader files (the shader source would be embedded in the BaseMaterial3D resource).

CanvasItemMaterial could also gain similar functionality for its vertex(), fragment() and light() functions.

@unfa
Copy link

unfa commented Apr 19, 2024

I am looking for a way to implement phenomena like iridescence or just tined specular - that's something that the legacy Diffuse/Specular workflow allowed for, but it's not possible to do in Godot's current PBR shader without straight up rewriting the light() function which is a bit problematic. It'd also not affect IBL sources like enviro and ref probes properly I am afraid.

@albertok
Copy link

albertok commented Jun 10, 2024

This is a great idea. I'm currently working around this problem with a really bad @tool script that auto converts Standard Materials to shaders and then runs a sed command to inject the extra shader code.

I'm making most things in Material Maker. I banged my head against this all weekend trying to see if I could automate it in either Godot or MM.

Next Pass or ShaderIncludes were also not capable of doing this cleanly.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

6 participants