This page has been translated automatically.
Video Tutorials
Interface
Essentials
Advanced
How To
UnigineEditor
Interface Overview
Assets Workflow
Settings and Preferences
Working With Projects
Adjusting Node Parameters
Setting Up Materials
Setting Up Properties
Lighting
Landscape Tool
Sandworm
Using Editor Tools for Specific Tasks
Extending Editor Functionality
Built-in Node Types
Nodes
Objects
Effects
Decals
Light Sources
Geodetics
World Objects
Sound Objects
Pathfinding Objects
Players
Programming
Fundamentals
Setting Up Development Environment
Usage Examples
UnigineScript
C++
C#
File Formats
Rebuilding the Engine Tools
GUI
Double Precision Coordinates
API
Containers
Common Functionality
Controls-Related Classes
Engine-Related Classes
Filesystem Functionality
GUI-Related Classes
Math Functionality
Node-Related Classes
Objects-Related Classes
Networking Functionality
Pathfinding-Related Classes
Physics-Related Classes
Plugins-Related Classes
IG Plugin
CIGIConnector Plugin
Rendering-Related Classes
Content Creation
Content Optimization
Materials
Art Samples
Tutorials
Warning! This version of documentation is OUTDATED, as it describes an older SDK version! Please switch to the documentation for the latest SDK version.
Warning! This version of documentation describes an old SDK version which is no longer supported! Please upgrade to the latest SDK version.

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#

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:

Source code (XML)
<?xml version="1.0" encoding="utf-8"?>
<base_material version="2.0" name="custom_post" editable="0">

	<!-- 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"/>
	<texture name="dirt" pass="post" unit="1" anisotropy="1" workflow="0" tooltip="Dirt color texture">core/textures/water_global/foam_d.dds</texture>
	
	<!-- Parameters -->
	<slider name="grayscale_power" shared="1" min="0.0" max="1.0" flags="max_expand">0.5</slider>
	<slider name="dirt_power" shared="1" min="-1.0" max="1.0" flags="max_expand">0.5</slider>
	
</base_material>

The key features of this post material are:

  • Added shaders and textures for post pass.
  • Added the shared grayscale_power and dirt_power parameters.

Save the new material as custom_post.basemat file to the data 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.

  1. Write the shader code in the plain text editor:
    Source code (UUSL)
    // 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
    Warning
    You should add a new line (press Enter) after closing the instruction (after MAIN_END command).
  2. Save the shader file as post.vert to the data/shaders/vertex folder.

The code of the vertex shader is simple since we don't need to work with the geometry.

Notice
Use the materials_reload command to reload shaders whilst the engine is running.

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:

  1. Open a plain text editor, and write the following:
    Source code (UUSL)
    // Include the UUSL fragment shader header
    #include <core/shaders/common/fragment.h>
    
    // Define the texture of the scene
    INIT_TEXTURE(0,TEX_SCENE)
    INIT_TEXTURE(1,TEX_DIRT)
    
    // 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;
    	UNIFORM float dirt_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);
    	
    	// Get the dirt color
    	float4 dirt_color = TEXTURE_BIAS_ZERO(TEX_DIRT,uv);
    	
    	// Calculate the grayscale
    	float3 gray_scene_color = dot(float3(0.3f, 0.59f, 0.11f), scene_color.rgb);
    	scene_color.rgb = lerp(scene_color.rgb,gray_scene_color,grayscale_power);
    
    	// add some dirt
    	OUT_COLOR = scene_color+dirt_color*dirt_power;
    	
    MAIN_END
    
    // end
    Warning
    You should add a new line (press Enter) after closing the instruction (after MAIN_END command).
  2. Save the shader file as post.frag to the data/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 grayscale_power parameter to adjust the grayscale power.
  • We also get the dirt texture and apply it to the final scene color to simulate dirn on camera lens (can also be used for vignette effect etc.)
  • A custom dirt_power parameter to adjust intensity of the dirt texture (its impact on the final image).
Notice
Use the materials_reload console command to reload shaders whilst the engine is running.

See Also#

Editing the Material#

Material has been created, shaders have been written, it's time to use it in the project!

  1. Open UnigineEditor and launch your project.
  2. Create a new material by inheriting from the recently created one in the Materials Hierarchy window.
  3. Open the Settings window by choosing Windows -> Settings from the main menu
  4. In the Settings window choose Runtime -> World -> Render -> Screen Space Materials and specify the name of the child post material in the Post field.

    The grayscale post-effect will be applied.

  5. Select your material in the Materials window. Then in the Parameters window select Parameters tab.

    Configure your post-effect by adjusting the Grayscale Power and Dirt Power parameters.

    The final scene.
Last update: 2021-04-09
Build: ()