|
Oxygen Engine
Modern C++ 3D Engine using OpenGL
|
Readers are assumed to have at least read the chapter about shaders (to grasp general informations about how to use shaders in Oxygen Engine)
A minimal knowledge about the GLSL language is recommended
While you can use oe::render::Shader to write and generate shaders in a more standard way (Vertex + Fragment shaders), it can become complex as you need to duplicate the shaders for each new pass type
In this chapter, we will use a simpler tool available in the engine 🙂
Here, we will explain what are surface shaders and then how they are used to customize a material
The surface shaders can be seen as simple fragment shaders where it is only required to implement one function to "describe" how the surface should react to light (by setting physical properties) depending on the input properties
Then, vertex and fragment shaders will be generated from this function
The entry point prototype will be this one:
It can be the only function in the content of the shader and might be empty.
Of course, you are free to declare/call any additional functions if you want
main() function should not be implemented (you will get an error if it is present)You can use uniforms like the standard shaders, see the shaders chapter about those available
The SurfaceInput provides the following inputs:
Texture coordinates
The coordinates are already rotated and tiled based on material data
| Type | Name | Description |
|---|---|---|
vec2 | tex_coords_0 | First set of coordinates of the surface |
vec2 | tex_coords_1 | Second set of texture coordinates of the surface |
vec3 | color | Vertex color |
More inputs to come
Colors
| Type | Name | Default | Description |
|---|---|---|---|
vec4 | albedo | white | Base color + alpha value |
vec3 | emissive | dark | Light emitted by the surface |
Physical properties
| Type | Name | Default | Description |
|---|---|---|---|
float | roughness | 1.0f | Surface roughness between 0.0f (reflective) and 1.0f (fully rough) |
float | metalness | 0.0f | Surface metalness between 0.0f (dielectric) and 1.0f (metallic) |
float | ao | 1.0f | Ambient occlusion of the surface between 0.0f and 1.0f |
Additional properties for transparent surfaces (Forward rendering)
| Type | Name | Default | Description |
|---|---|---|---|
float | ior | 1.5f | Index of refraction of the surface |
float | transmission | 1.0f | Percentage of light transmitted through the surface between 0.0f (opaque) and 1.0f (transparent) |
float | thickness | 0.0f | Thickness of tghe surface between 0.0f (thin) and infinity (thick glass) |
Miscellaneous
| Type | Name | Default | Description |
|---|---|---|---|
vec3 | normal | {0.0f, 0.0f, 1.0f} | Perturbated normal direction of the surface |
bool | use_pbr | true | Physically Based Rendering mode |
About use_pbr :
false, PBR will be disabled.albedo outputOE_UNPACK_NORMAL_MAP(sampler2D normal_map, vec2 textures_coords)normal_map at textures_coords coordinatesOE_CONVERT_SRGB_TO_LINEAR(vec3 color)color into linearTo apply the shader on a material it is exactly the same as a standard shader, the only change is to use the oe::render::SurfaceShader class
You may have noticed that the surface shaders does not not need compilation
This is due to the fact that many shaders might be getting generated depending of the pass and vertex type
At runtime, only the needed ones are compiled at the first required bind
Default values
This is the minimal content of a working (but not interesting) surface shader using all defaults values
Usage in application:
This default shader will generate the following material:
Textured example
This sample will demonstrate how to fill surface data using input data and textures
Shader code:
Usage in application:
This sample shader will take 3 uniforms textures and will generate the following material: