Shader Built-in Variables
In Orillusion
engine, in order to write complex shader scripts (such as PBR material shading logic) in a more standardized and efficient manner, we have split and encapsulated the shader code. This article will introduce some commonly used built-in shader scripts, such as variable, struct definition, function implementation, etc.
Common Variables
The initial data comes from the vertex stream VertexAttributes
in the pipeline, the Uniform
data defined in the constant register - globalUniform
,, and some mathematical constants defined in the script header, such as PI=3.14
, etc. After parsing these data, we can get the following built-in variables:
globalUniform
The data collected by the engine before rendering is bound to the rendering pipeline in the form of Uniform
, which can be regarded as read-only global data. The built-in variables that can be obtained by parsing globalUniform
are as follows:
//x: current frame data of the engine; y: current time of the engine; z: time span between current frame and the previous frame.
var<private> TIME: vec4<f32>;
//x: current mouse position x; y: current mouse position y.
var<private> MOUSE: vec4<f32>;
//x: pixel size of the canvas on which the engine is running.
var<private> SCREEN: vec4<f32>;
//x: distance to the near clipping plane of the projection; y: distance to the far clipping plane of the projection; z: 1.0 + 1.0 / globalUniform.far.
var<private> ProjectionParams: vec4<f32>;
//projection matrix
var<private> ORI_MATRIX_P: mat4x4<f32>;
//view matrix
var<private> ORI_MATRIX_V: mat4x4<f32>;
//model matrix
var<private> ORI_MATRIX_M: mat4x4<f32>;
//ORI_MATRIX_P * ORI_MATRIX_V
var<private> ORI_MATRIX_PV: mat4x4<f32>;
//inverse matrix of ORI_MATRIX_PV
var<private> ORI_MATRIX_PVInv: mat4x4<f32>;
//???
var<private> ORI_MATRIX_World: mat4x4<f32>;
//camera matrix
var<private> ORI_CAMERAMATRIX: mat4x4<f32>;
//matrix used to transform normal to world coordinates
var<private> ORI_NORMALMATRIX: mat3x3<f32>;
ORI_VertexOut
This is the structure obtained by parsing vertex data VertexAttributes
in the common vertex stream processing process Common_vert.wgsl
.
//Define the structure of vertex data
struct VertexOutput {
//The first UV
@location(0) varying_UV0: vec2<f32>,
//The second UV, generally used for shadow mapping, can also be used for other purposes
@location(1) varying_UV1: vec2<f32>,
//Coordinates in view space
@location(2) varying_ViewPos: vec4<f32>,
//Coordinates in NDC space
@location(3) varying_Clip: vec4<f32>,
//World coordinates
@location(4) varying_WPos: vec4<f32>,
//Normal direction in world space
@location(5) varying_WNormal: vec3<f32>,
//Vertex color
@location(6) varying_Color: vec4<f32>,
#if USE_SHADOWMAPING
//To be explained
@location(7) varying_ShadowPos: vec4<f32>,
#endif
#if USE_TANGENT
//Tangent direction in world space
@location(8) varying_Tangent: vec4<f32>,
#endif
//Position after projection transformation
@builtin(position) member: vec4<f32>
};
var<private> ORI_VertexOut: VertexOutput ;
ORI_VertexVarying
This is the input data interpolated by weights from the vertex shader to the fragment shader. By comparing it with VertexOutput
, it is easy to see that they correspond one-to-one, except for the face
attribute.
struct FragmentVarying {
@location(0) fragUV0: vec2<f32>,
@location(1) fragUV1: vec2<f32>,
@location(2) viewPosition: vec4<f32>,
@location(3) fragPosition: vec4<f32>,
@location(4) vWorldPos: vec4<f32>,
@location(5) vWorldNormal: vec3<f32>,
@location(6) vColor: vec4<f32>,
#if USE_SHADOWMAPING
@location(7) vShadowPos: vec4<f32>,
#endif
#if USE_TANGENT
@location(8) TANGENT: vec4<f32>,
#endif
//Whether it is front-facing or back-facing
@builtin(front_facing) face: bool,
@builtin(position) fragCoord : vec4<f32>
};
var<private> ORI_VertexVarying: FragmentVarying;
ORI_ShadingInput
The variable ORI_ShadingInput is customized for PBR material, which includes various parameters required for PBR shading. It is convenient to get them when using it later. After shading, users can append custom effects and extract the required data from this variable.
struct ShadingInput{
//Base color, usually the default white
BaseColor:vec4<f32>,
//Roughness
Roughness:f32,
//Metallic
Metallic:f32,
//Specular coefficient
Specular:f32,
//Emissive color
EmissiveColor:vec4<f32>,
//Surface color
SurfaceColor:vec4<f32>,
//Normal vector
Normal:vec3<f32>,
//Tangent vector
Tangent:vec4<f32>,
//To be explained
WorldPositionOffset:vec3<f32>,
//Ambient occlusion coefficient
AmbientOcclusion:f32,
//To be explained
PixelDepthOffset:f32,
//Opacity
Opacity:f32,
//Opacity mask coefficient
OpacityMask:f32,
//Refraction coefficient
Refraction:f32,
}
var<private> ORI_ShadingInput: ShadingInput;
ORI_FragmentOutput
The ORI_FragmentOutput variable stores the result of fragment shading, and by default, only color data needs to be output in fragment shading. If there are some post-effects that need to be processed, more content needs to be output to the GBuffer
for easy calculation. Generally, the parameters that need to be involved in post-processing include world coordinates worldPos
, normal vectors worldNormal
, and some material information material
(smoothness/roughness/whether to emit light, etc.).
struct FragmentOutput {
//Color
@location(0) color: vec4<f32>,
#if USE_WORLDPOS
//World coordinates
@location(1) worldPos: vec4<f32>,
#endif
#if USEGBUFFER
//Normal vector
@location(2) worldNormal: vec4<f32>,
//Material data
@location(3) material: vec4<f32>
#endif
var<private> ORI_FragmentOutput: FragmentOutput;
}
materialUniform
The materialUniform
is defined in the material and is associated with the specific material. The variable carries the variables required to draw the material. The data structure definitions of materialUniform
for different materials should be different. Taking LitMaterial
as an example, we will briefly introduce some variables in materialUniform
.
The
LitMaterial
used thematerialUniform
structure, which is currently encapsulated intoPhysicMaterialUniform_frag
。
struct MaterialUniform{
#if USE_BRDF
//physical shading, material data description content
#include "PhysicMaterialUniform_frag"
#endif
#if USE_ColorLit
#endif
#if USE_UnLit
#endif
}
Continue to check more content in
PhysicMaterialUniform_frag
.
//Structure defined in the PhysicMaterialUniform_frag file
//Defines the BRDF model shading, material ball parameters
struct MaterialUniform {
//First UV offset data x:U direction offset y:V direction offset z:U direction scale w:V direction scale
transformUV1:vec4<f32>,
//Second UV x:U direction offset y:V direction offset z:U direction scale w:V direction scale
transformUV2:vec4<f32>,
//Base color (reference to other named tintColor)
baseColor: vec4<f32>,
//Emissive color
emissiveColor: vec4<f32>,
//f0 reflectivity
materialF0: vec4<f32>,
//Ambient light addition coefficient
envIntensity: f32,
//Normal vector scaling factor
normalScale: f32,
//Roughness
roughness: f32,
//Metallic
metallic: f32,
//Ambient occlusion intensity
ao: f32,
//Minimum roughness
roughness_min: f32,
//Maximum roughness
roughness_max: f32,
//Minimum metallicity
metallic_min: f32,
//Maximum metallicity
metallic_max: f32,
//Emissive intensity
emissiveIntensity: f32,
//Transparency cutoff threshold
alphaCutoff: f32,
//Index of refraction
ior: f32,
//Clearcoat layer color
clearcoatColor: vec4<f32>,
//Clearcoat layer weight
clearcoatWeight: f32,
//Clearcoat layer intensity
clearcoatFactor: f32,
//Clearcoat layer roughness
clearcoatRoughnessFactor: f32,
};
Common files
Just as in regular program writing, defining functions is important in shader scripts to enable function reuse and facilitate maintenance. The following are some commonly used functions:
LightingFunction_frag
: Functions required for lighting calculations.NormalMap_frag
: Encapsulates various functions related to normal calculation.IESProfiles_frag
: Functions for parsing light source description files.BRDF_frag
: Functions required for BRDF model shading.FastMath_shader
: Fast square root calculation and fast vector length calculation.
Summary
As the engine version iterates, built-in functions will become more and more abundant. You can also extract commonly used functions into libraries for reuse.