Shaders are very important for a 3D rendering library as they allow for customisation and flexibility by the user application. In traditional libraries, shaders are created in a special language and then compiled and sent to the graphics hardware. WebRender is purely a software renderer so we don't need to have to build a complex language and instead can simply pass a function reference to act as a shader. Since a 'shader' is actually made up of a vertex and pixel shader, along with attributes and helper functions, we package them all into a 'shader program' that can be easily loaded and unloaded from the rendering pipeline.
Creating a shader program involves multiple complex function calls. First space must be allocated for it using getSBOId, which returns a reference id for that shader program. Following this, a vertex and pixel shader function must be assigned to this program, using assignSBOVertexShader and assignSBOPixelShader. Next the program must be told how many vertex attributes each shader is working with, addSBOVertexAttribute is used for this. Adding the attributes is one of the more complex parts of setting up the shaders, therefore for more information look at the function page and Tutorial 2. Lastly loadSBO is called, which takes all the information we provided and compiles the shader program. Once compiled, the sahder can then be set to be used using bindSBO.
The vertex shader for WebRender has 3 inputs, the WebRender instance that is calling the function, an array reference representing the incoming vertex, and an array reference representing the outgoing vertex. The reason we use two different arrays is to allow for there to be more or less vertex attributes after the vertex shader. In a 3D application your object, world, camera and perspective transformations will be in the vertex shader. The only requirement to take note of is that your outgoing vertex must have XYZW coordinates, these would have be defined using addSBOVertexAttribute when you created the shader program.
The pixel shader, also known as fragment shader is other libraries, is where the colour of pixels is determined. The inputs for your pixel shader will are determined by your vertex attributes. First we again have the WebRender instance, but it is then followed by each vertex attribute that you defined when creating the shader and in the order you defined them. Due to the requirement of your vertex attributes having XYZW coordinates, these will be somewhere in the inputs. The pixel shader then outputs a 32-bit colour value, that will be used to colour a pixel on the screen. If the value 0 is returned, then the pixel will not be coloured and the Z-Buffer (if being used) will not be updated either. This is similar to calling 'discard' in the OpenGL fragment shader.
In to allow texture sampling, the function getTexturePixelColour can be called on the provided WebRender instance. This then returns the 32-bit colour sampled from the bound texture at the coordinates given. Along with that, two vertex/matrix multiplcation functions, vecByMatrixCol and vecByMatrixRow are provided for use in the vertex shader. Though these aren't required, it can save you having to create them at first. The reason these functions are different from all the others that your application uses when communicating with WebRender, is that these are provided from within WR_Core, which is the main internal class where the rendering pipeline is.
In other graphics libraries, you can pass uniform values to your shaders that stay consistent. In WebRender these 'shader variables' are simply variables defined in the global scope that both your application and the shaders can have access to. In order to support these in multi-threaded mode, these variables must be defined in the same file/s as the shader functions. In order to update these variables, in a non-threaded enviroment you could just change them directly, but in order to support multi-threading, it is advised you use the special setShaderVariable function.
The shader architecture is by far the most complex part of WebRender, mainly due to the amount of customisability it provides. To gain a full understand of how everything works, read the tutorials and look at the API pages for each function. There should be very few restrictions on the types of shaders you can build within WebRender.
A shader program in WebRender contains a vertex shader, pixel/fragment shader, lists of vertex attributes and generated helper functions.
WebRender compiles shaders based on the input given during their creation.
The vertex shader is responsible for all the vertex transformations, except viewport transformation.
The pixel/fragment shader is used to assign colour values for each pixel being drawn.
To fully understand how the shader programs work, read the tutorials.