As I have said users are able to make their own shaders. To do that, you have to extend IVertexShader interface for Vertex Shader, or IFragmentShader interface for fragment shaders. Both of them are extension of IShader interface, that contains method execute that takes ShaderFunctions object, that help you for instance with texture loading on your shaders.
To understand custom shaders, you must first understand how render pipeline works.
In my renderer I did not try to reinvent the wheel. If you have understanding of openGL pipeline,
it does not differ at all.
First it runs vertex shader on all vertices. Then, it rasterises the triangle according to frame buffer,
and interpolates values using barycentric coordinates to each fragment. It then runs each fragment and draws pixel
to framebuffer.
Here is an image how it works:
Values that are gotten from the previous step in the pipeline.
- In Vertex Shader, they are the vertex data from vertex buffers.
- In Fragment Shader, they are interpolated data gotten from the vertex shaders.
These are the rules of the Input variables:
They must have attribute InputAttribute set.
They must be declared public and be of value type
InputAttribute must have declared name.
- In Vertex Shaders, the name is basicaly pointless,
but serves as a good way to separate your variables.
- In Fragment Shaders, it must be the same as the name of the OutputAttribute
of the VertexShader output variable
Position is important to set in VertexShaders only.
If set, it will sort variables according to their values.
Every other attribute without set position will go after set ones.
Note: The position is just relative to other set ones.
If you have attributes with positions (a: 5, b: 10, c: 2), their real position will be set (a: 2, b: 3, c: 1).
Values that are outputed from shaders to process in the next step in the pipeline.
These are the rules of the Output variables:
They must have attribute OutputAttribute set.
They must be declared public and be of value type
In Vertex Shader, their name must match the name of InputAttribute in Fragment Shader.
In Fragment Shader it is possible to have only one Output Variable. (Otherwise the linking process will fail)
Values that are uniform accross whole render pipeline.
They can be set from outside of render pipeline though ShaderProgram variable.
Though possible, it is highly recomended to not set them in shaders, since it could lead to
racing conditions and data missmatch.
These variables are useful when setting textures samplers, but also for other static data.
These are the rules for Uniform Variables:
They must have attribute UniformAttribute set.
They must be static
They must be declared public and be of value type
The name of the attribute is the name users set these variables through ShaderProgram.