# Rendering system

# Rendering system

The rendering system is responsible for the driving of the entire rendering pipeline, global configuration management, etc. It can be considered that it connects all the resources required for rendering in series, converts them into a series of rendering instructions to the rendering hardware interface (RHI), and then gives them to different graphics APIs. Perform real drawing.

From the perspective of the small game framework, the rendering system mainly includes two singletons of game.renderSystem and engine.renderEnv, as well as the Render Graph in the subsequent chapters.

# renderSystem

renderSystem is a singleton under the game game, which serves as the entrance to the entire rendering system driver. Because it is an entrance, its function is relatively simple, mainly to manage some configuration information, and most of the work is taken care of by the modules it manages.

The functions related to renderSystem that developers need to care about are as follows:

  1. screen: The main screen, which can be set to the camera.
  2. setting: global rendering configuration.
  3. RenderGraph: The rendering pipeline currently in use, which will be discussed later.

Of course there are some methods:

// Obtain the corresponding `MeshRenderer` through the `id` in a specific culling result list
renderSystem.getMeshById(id);

// enable a rendering pipeline
renderSystem.useRenderGraph(rg);

# renderEnv

In addition to the game-level renderSystem, there is also an engine-level singleton renderEnv for developers to adjust and obtain some global information. Some of the interfaces can even allow developers to completely customize their own rendering without the framework. Pipeline**, see Deep Rendering Pipeline for details, but here we only need to understand some of the functions:

The first is the acquisition of some information:

  1. version: Get the version of the rendering Backend, such as 1.2, 1.3.
  2. backendType: Get the type of rendering Backend, such as WebGL.
  3. canvasWidth: the width of the canvas.
  4. canvasHeight: the height of the canvas.
  5. supportCompressTextures: Supported compression texture types.
  6. features: a list of currently supported rendering features, such as dynamicBatch3D.

In addition to this information, developers can also customize some global configurations for some reasons.

The first is the effect Effect. In the actual rendering process, we will use a certain lightMode to render a batch, but in this batch of rendering, it is very likely that some Material has an Effect that does not have a Pass with this lightMode. Need a default material for this lightMode:

// Register a default degraded material for a certain `lightMode`
renderEnv.registerFallbackEffect(lightMode, effect);

// Unregister downgrade material
renderEnv.unregisterFallbackEffect(lightMode);

In addition, before Effects and Materials, we also mentioned that macros and UniformBlock have global parts, and this global part is actually set here.

# Full library macro

The first is the global macro. Global macros, like Material macros, also control the switch of macros defined in Effect, except that the dimension of their influence is all effects in the world.

There are two forms of global macros, one is direct macros:

// Set up a batch of global macros in the form of {key: value}
renderEnv.changeMacros(macros);

// Get a global macro
renderEnv.getMarco(key);

Direct macros are simple to understand and have lower overhead, but there is a problem-cannot conflict with Material macros.

In order to solve this problem, the mini game framework also provides another method to slightly increase the overhead but is more flexible, namely global virtual macro:

// Set up a batch of global virtual macros in the form of {key: value}
renderEnv.changeVirtualMacros(macros);

// Get a global virtual macro
renderEnv.getVirtualMacro(key);

Virtual macros are different from ordinary macros. They are equivalent to the master switch of a macro, which sacrifices a small amount of CPU overhead to ensure maximum compatibility.

If there is no special need, it is recommended to always use virtual macros.

# Global Uniform

The global Uniform is finally set in renderEnv, but in order to facilitate management, the small game framework has created a separate system for developers to easily build and manage their own global Uniform.

In order to create their own global Uniform, developers first need to add in the globalSetting field of project.config.json:

{
  "globalSetting": {
    "shaderGlobalProperties": [
{
"key": "_GlobalMainLightDir",
"type": "Vector4",
"default": [
0,
0,
0,
0
]
},
{
"key": "_GlobalMainLightColor",
"type": "Vector4",
"default": [
0,
0,
0,
0
]
}
]
  }
}

Afterwards, you can use the following methods to modify and obtain the global Uniform:

engine.setGlobalFloat(key, value);
engine.getGlobalFloat(key);
engine.setGlobalVector(key, vector);
engine.getGlobalVector(key);

Note that currently only Float and Vector types of Uniform are supported.

After setting up at runtime, it still needs to be used in the definition of the shader. If it does not correspond to it, it will not take effect.