- RenderStep - a single step in the pipeline, such as running the 3D render, changing state or applying a shader.
Each step has a source and a target
- RenderSource - a source for the step, a set of textures that are used in the step
- RenderTarget - a target for the step, a framebuffer with one or more attached textures / renderbuffers.
- Pipeline - a sequence of steps and associated objects such as TextBuffers.
- TextureBuffer - an indexed set of textures that you need, you can create up to 254 textures if the driver permits.
- TextureBuffer is also a RenderSource and a RenderTarget.
- Normally you have a single texture buffer that all the steps write to and read from
- PostProcessingStep : RenderStep - draws a full-screen quad with given shader, RenderSource and RenderTarget.
The pipeline is located in secondstage.cpp.
In order to add a post-processing step:
- If you need extra textures, add them to the buffer:
- Declare TEXTURE_XXX constant
- Add
buffer->setTexture(TEXTURE_XXX, scale, "<some meaningful name>", video::ECF_A8R8G8B8);
to register a texture
- Create shader code in GLSL:
- In
client/shaders
at the project root, create folder for your shader, for example,depth_of_field
. - Add vertex and fragment shader code to the
depth_of_field
folder:opengl_vertex.glsl
- use code fromsecond_stage/opengl_vertex.glsl
opengl_fragment.glsl
- start with code fromsecond_stage/opengl_fragment.glsl
- Set up the postprocessing step:
- Request a shader with the following code:
IWritableShaderSource *s = client->getShaderSource();
u32 shader_index = s->getShader(
"depth_of_field", // name of the folder with the shader code
TILE_MATERIAL_BASIC, // material parameter
NDT_NORMAL); // node draw type parameter
video::E_MATERIAL_TYPE shader = s->getShaderInfo(shader_index).material;
- Add the step
RenderStep *effect = pipeline->addStep<PostProcessingStep>(
shader, // ID of the shader renderer
std::vector<u8> { TEXTURE_XXX, ... }); // IDs of the textures in the buffer to map to samplers 0, 1, 2 ...
effect->setRenderSource(buffer);
effect->setRenderTarget(pipeline->createOwned<TextureBufferOutput>(buffer, TEXTURE_YYY)
Note: Make sure all steps are wired to the correct textures. Note: Make sure that the final step is returned from the method, so it's output is routed to the screen later.