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

Proposal for shader functions #602

Closed
deprilula28 opened this issue Sep 29, 2020 · 6 comments
Closed

Proposal for shader functions #602

deprilula28 opened this issue Sep 29, 2020 · 6 comments
Labels
A-Rendering Drawing game state to the screen C-Feature A new feature, making something new possible

Comments

@deprilula28
Copy link
Contributor

Take as a reference the you create a shader in Blender:
image

Essentially, instead of always having one shader you'd use for all materials, binding the different textures in a single UV (diffuse, specular, normals, etc), you should be able to make your own shaders calling shader functions.
In the Blender example, "Principled BSDF" is a function that would take in the diffuse, ambient occlusion, etc. values for a single pixel and use it to create a color.

You could conceive of many other functions, maybe dividing sub surface and other features that aren't used for everything into different shaders you can use depending on the mesh.

When writing your own shaders, you might use different samplers, or might use some other method to call the pre-made shader functions.

This relates to the following issues:
#185
#179

@Moxinilian Moxinilian added C-Feature A new feature, making something new possible A-Rendering Drawing game state to the screen labels Sep 29, 2020
@cart
Copy link
Member

cart commented Sep 29, 2020

Agreed. Shader logic should be modular. Ideally it would be possible to make a "custom pbr shader" by just pulling in the relevant functions.

@FuriouZz
Copy link
Contributor

FuriouZz commented Nov 9, 2020

To answer to the modularity purpose, at my studio we used to create our shader from a collection of chunks with nanogl-pbr. Each material is defined by a collection of inputs. An input is basically a number of arguments (1, 2, 3, 4...?), then anything can be linked to that input (an attribute, an uniform, a constant, an enum, a texture, etc...). An input can me mixed by multiple sources for example for an input of three arguments, one can be set by a texture red channel, the other by a constant, and the other by a uniform.
In some case, we were confronted to some difficulty to maintain our shaders or we feel more easy to create another material from scratch, but it can be an interesting approach to investigate and to improve.

@CptPotato
Copy link
Contributor

One approach I see here is to provide some kind of framework shader(s) where the user code is "injected" (basically #included/copy-pasted) and accessed through a single function call. In my own PBR code I liked to use structs to express sets of parameters for different stages of the shading process. In combination it could look something like this:

Framework code (not accessed by the user):

struct Material { // user input parameters
	vec3 albedo;
	float opacity;
	vec3 normal; // tangent space [-1, 1]
	float roughness; // perceptual roughness [0, 1]
	float metallic; // [0, 1]
	vec3 emissive; // [0, ...]
	float reflectance; // [0, 1]
	float clearcoat; // clearcoat blend factor [0, 1]
	float clearcoat_roughness; // [0, 1]
};

void main() {
	// ...

	Material mat = get_material(uv); // get_material is defined in the user's code

	// ... shading based on the material properties goes here
}

User defined material function:

uniform vec3 tint;
uniform sampler2D sAlbedo;

Material get_material(vec2 uv) {
	Material mat;
	mat.albedo = texture(sAlbedo, uv).rgb * tint;
	mat.normal = vec3(0.0, 0.0, 1.0);
	// ...

	return mat;
}

Difficulties I see with this approach:

  • providing ways to customize textures, samplers and uniforms
  • toggling optional features of the "framework" code. this will either require lots of code duplication or #ifdef/#endif branches, resulting in ugly to read code
  • naming conflicts between user functions/globals and things from the provided framework shader
    • if I understood correctly SPIRV will support linking binary modules at some point which might help in this situation and make the whole process cleaner

Another way is to turn the concept upside down and provide function libraries that the user can #include. This would mean more code to write for the user but it might give a better understanding at what's going on (less hidden code).
Not sure if there are more elegant approaches. I'm personally not a fan of the node-based visual programming style as seen in Blender or Unreal but I don't think that was the proposal here.

@Vrixyz
Copy link
Member

Vrixyz commented Jun 7, 2022

Related: #3615

@nicopap
Copy link
Contributor

nicopap commented Jul 31, 2023

This can be safely closed right? The PBR shader has been split in many functions. While it's not (yet) extensible, it allows picking and composing your own shader based on the smaller functions.

@cart
Copy link
Member

cart commented Aug 1, 2023

Yup this can be closed!

@cart cart closed this as completed Aug 1, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-Rendering Drawing game state to the screen C-Feature A new feature, making something new possible
Projects
None yet
Development

No branches or pull requests

7 participants