UUSL and Shaders Migration
Important Notes#
In 2.15 we have simplified the process of creating custom user materials or extending the functionality of existing ones. Up to 2.15 in order to tweak the mesh_base material a little bit (e.g., add some UV animation or an additional texture, or otherwise use any custom shader) you had to make a copy of the whole mesh_base and add your custom code to it (which actually is a fork!). In this case, any changes made to this material in each subsequent SDK release associated with adding new functionality or some internal refactoring would require you to track these changes and update your custom material manually.
Creation of custom user materials is now available in the following ways:
- Using the Material Graph: by assembling what you need in the visual editor
- Using Abstract Materials: by inheriting a base material from an existing abstract prototype (or your own custom prototype) and adding the desired functions to it.
We have separated the Engine's internal shader functionality from shaders API available to customers, restructuring and moving all the related code to separate header files (like constants.h, gbuffer.h, matrix.h, etc.) putting them for you to data/core/materials/shaders/api. This fact enables us to prevent shaders API from changing each release and ensure that all functions will be timely and properly documented.
It should also be noted that we plan to move away from the old-style xml-based materials format and it shall be declared deprecated in the future (although it is not yet clear in which release exactly).
The guidelines given below will simplify manual migration of UUSL shaders for materials.
Unnecessary Defines#
The following defines are obsolete and should be removed:
- UNDEF_FRAGMENT_OUT
- BASE_DEFERRED
- BASE_SHADOW
- BASE_WIREFRAME
- BASE_POST
- USE_RW_TEXTURES
- USE_STORAGE_BUFFERS
- METALNESS
- AMBIENT
Includes and Paths#
Make sure to use full paths to shader files instead of just file names.
Core shaders are now stored together with the corresponding .basemat files, either in the same folder next to them or in shaders/ folder.
To work with the default GBuffer you have to add the following include:
#include <core/materials/shaders/render/gbuffer.h>
The setGBuffer(...) function have migrated to this file.
Be sure to make the following replacements in your includes:
OLD | UNIGINE 2.15 |
---|---|
|
|
|
|
|
|
|
|
|
|
Main Function Declarations#
Make sure that you use the new shader's body declarations:
// Vertex shaders only
MAIN_BEGIN(VERTEX_IN, FRAGMENT_IN)
// ...
MAIN_END
// Fragment shaders
MAIN_FRAG_BEGIN(FRAGMENT_IN)
// ...
MAIN_FRAG_END
// Compute shaders
MAIN_COMPUTE_BEGIN(x, y, z)
// ...
MAIN_COMPUTE_END
// Tessellation evaluate shaders
MAIN_EVALUATE_BEGIN(EVALUATE_OUT, EVALUATE_IN)
// ...
MAIN_EVALUATE_END
// Tessellation control shaders
MAIN_CONTROL_BEGIN(CONTROL_OUT, CONTROL_IN)
// ...
MAIN_CONTROL_END
// Patch constant shaders
MAIN_PATCH_CONSTANT_BEGIN(CONTROL_IN)
// ...
MAIN_PATCH_CONSTANT_END
Data Types and Structures#
Be sure to make the following changes to data types:
OLD | UNIGINE 2.15 |
---|---|
TYPE_R | float |
TYPE_RG | float2 |
TYPE_RGB | float3 |
TYPE_RGBA | float4 |
TYPE_INT | int |
TYPE_UINT | uint |
And structure definitions:
OLD | UNIGINE 2.15 |
---|---|
|
|
UUSL Functions#
Here is the list of the most frequently used functions that were changed:
OLD | UNIGINE 2.15 |
---|---|
getPosition(x) | mul4(s_projection, x) |
to_float(...), to_int(...), to_uint(...), and so on... |
toFloat(...), toInt(...), toUInt(...), and so on... |
halton8[...] halton16[...] |
halton8(...) halton16(...) |
getBlueNoise(...) | blueNoise(...) |
getBlueNoiseTemporal(...) | blueNoiseTemporal(...) |
getBlueNoiseTAA(...) | blueNoiseTAA(...) |
getBayerNoise(...) | bayerNoise(...) |
getDepthToPosition(...) | nativeDepthToPositionVS(...) |
getLinearizedDepth(...) | nativeDepthToLinearDepth(...) |
getPositionToViewDirection(...) | positionToViewDirection(...) |
getViewDirection(...) | screenUVToViewDirection(...) |
getPositionToViewUV(...) | positionToScreenUV(...) |
getNormalZ(...) | normalReconstructZ(...) |
setDeferredNormal(...) | packGBufferNormal(...) |
getDeferredNormal(...) | unpackGBufferNormal(...) |
getNormalToTBN(...) | normalToTBN(...) |
getOverlapNormal(...) | overlapNormal(...) |
pack_rgba8_to_uint32(...) | pack8888To32(...) |
unpack_uint32_to_rgba8(...) | pack32To8888(...) |
pack_rg16_to_uint32(...) | pack1616To32(...) |
unpack_uint32_to_rg16(...) | pack32To1616(...) |
getBasisX(...) | basisX(...) |
getBasisY(...) | basisY(...) |
getBasisZ(...) | basisZ(...) |
GET_TEXSIZE(...) |
textureResolution(...) - texture resolution textureIResolution(...) - 1 / texture resolution |
New col(...) and row(...) functions replace both set and get functionality while keeping same semantic as before, meaning that:
row(my_matrix, my_row, my_value); // will set row "my_row" in matrix "my_matrix" to "my_value"
row(my_matrix, my_row); // will return value from row "my_row" from matrix "my_matrix"
OLD | UNIGINE 2.15 |
---|---|
getColumn(...), setColumn(...), getColumn3(...), setColumn3(...) |
col(...) |
getRow(...), setRow(...), getRow3(...), setRow3(...) |
row(...) |