Creating a Custom Shader for Post-Processing
Unigine engine allows you to create your own post-effects by writing custom shaders. To write post-effect shaders, you should use the same workflow as for deferred and forward rendering passes: create the material, write vertex and fragment shaders.
This tutorial explains how to create a post-effect material, write shaders for it (both vertex and fragment), add a parameter to the material to be able to specify the value from the UnigineEditor.
See Also
- The article on Material Settings
- The article on Custom Materials
Create a Material
As in all other shaders tutorials, you should create the material first. Let's add a new base material to your project.
To create post-effect material, you should specify the post pass for shaders and textures.
The material will have the following structure:
<?xml version="1.0" encoding="utf-8"?>
<base_material version="2.0" name="custom_post" editable="0" parameters_prefix="m">
<!-- Post-effect shaders -->
<shader pass="post"
defines="BASE_POST"
vertex="shaders/vertex/post.vert"
fragment="shaders/fragment/post.frag"/>
<!-- Textures -->
<texture name="color" pass="post" unit="0" type="procedural"/>
<!-- Parameters -->
<parameter name="grayscale_power" type="slider" shared="1" min="0.0" max="1.0"
flags="max_expand">0.5</parameter>
</base_material>
The key features of the post material are:
- Added a post pass shaders and textures.
- Added the shared grayscale_power parameter.
Save the new material as custom_post.basemat file to the assets/Materials folder.
Create Vertex Shader
Since we write a simple shader example, let's write a simple shader like the vertex shader for the deferred rendering pass.
- Write the shader code in the plain text editor:
// Include the UUSL header #include <core/shaders/common/common.h> // Input data struct STRUCT(VERTEX_IN) INIT_ATTRIBUTE(float4,0,POSITION) // Vertex position INIT_ATTRIBUTE(float4,1,TEXCOORD0) // Vertex texcoords INIT_ATTRIBUTE(float4,2,COLOR0) // Vertex color END // Output data struct STRUCT(VERTEX_OUT) INIT_POSITION // Output projected position INIT_OUT(float2,0) // Texcoords (x and y only) END MAIN_BEGIN(VERTEX_OUT,VERTEX_IN) // Set output position OUT_POSITION = getPosition(IN_ATTRIBUTE(0)); OUT_DATA(0).xy = IN_ATTRIBUTE(1).xy; MAIN_END // end
You should add a new line (press Enter) after closing the instruction (after MAIN_END command). - Save the shader file as post.vert to the assets/shaders/vertex folder.
The code of the vertex shader is so simple since we don't need to work with the geometry.
Create Fragment Shader
This section contains instruction how to create a fragment shader (also known as pixel shader).
To create the fragment shader for post-process pass, perform the following:
- Open a plain text editor, and write the following:
// Include the UUSL fragment shader header #include <core/shaders/common/fragment.h> // Define the texture of the scene INIT_TEXTURE(0,TEX_SCENE) // Input values STRUCT(FRAGMENT_IN) INIT_POSITION // Projected position INIT_IN(float2,0) // Texcoords END // Define the grayscale_power parameter CBUFFER(parameters) UNIFORM float grayscale_power; END MAIN_BEGIN(FRAGMENT_OUT,FRAGMENT_IN) // Get the UV float2 uv = IN_DATA(0); // Get the scene color float4 scene_color = TEXTURE_BIAS_ZERO(TEX_SCENE,uv); // Calculate the grayscale float3 gray_scene_color = FLOAT3(dot(float3(0.3f, 0.59f, 0.11f), scene_color.rgb)); scene_color.rgb = lerp(scene_color.rgb,gray_scene_color,FLOAT3(grayscale_power)); OUT_COLOR = scene_color; MAIN_END // end
You should add a new line (press Enter) after closing the instruction (after MAIN_END command). - Save the shader file as post.frag to the assets/shaders/fragment folder.
Well, let's clarify what is under the hood of this fragment shader:
- We get the texture which was specified in the post-effect material.
- By applying a standard grayscale equation, we change the color of the scene.
- By using lerp function (which performs a linear interpolation), we add the custom parameter to adjust the grayscale power.
See Also
- Grayscale article on Wikipedia.
Editing the Material
Material has been created, shaders have been written, it's time to use it in the project!
- Open UnigineEditor and launch your project.
- Create a new material by inheriting from the recently created one in the Materials Hierarchy window.
- Open the Settings window by choosing Windows -> Settings from the main menu
- In the Settings window choose Runtime -> Render and specify the name of the child post material in the Post Materials field.
The grayscale post-effect will be applied.
- Select your material in the Materials window. Then in the Parameters window select Parameters tab.
The final scene.