mirror of
https://github.com/galacean/engine.git
synced 2026-05-31 15:51:33 +08:00
docs: add post-processing related
This commit is contained in:
@@ -19,7 +19,7 @@ Right-click in the **[Assets Panel](/en/docs/assets/interface)** (or the + sign
|
||||
|
||||
### Properties Panel
|
||||
|
||||
<img src="https://gw.alipayobjects.com/zos/OasisHub/2eaad4b1-d3e3-4c17-ae7f-58b488cd3606/image-20240718190944508.png" alt="image-20240718190944508" style="zoom:50%;" />
|
||||
<img src="https://gw.alipayobjects.com/zos/OasisHub/d3f073e5-dbd3-4345-a1ca-d4f3adf6000a/image-20250114194404516.png" alt="image-20240718190944508" style="zoom:50%;" />
|
||||
|
||||
### Ambient Light
|
||||
|
||||
@@ -33,29 +33,24 @@ For details, please refer to the [Background Tutorial](/en/docs/graphics/backgro
|
||||
|
||||
For details, please refer to the [Shadow Tutorial](/en/docs/graphics/light/shadow/).
|
||||
|
||||
### Post-Processing
|
||||
|
||||
For details, please refer to the [Post-Processing Tutorial](/en/docs/graphics/postProcess/postProcess/).
|
||||
|
||||
### Fog
|
||||
|
||||
You can add **linear, exponential, exponential squared** 3 types of fog to the entire scene:
|
||||
|
||||

|
||||
|
||||
|
||||
## Script Usage
|
||||
|
||||
| Property Name | Description |
|
||||
| :-------------------------------------------- | :---------- |
|
||||
| [scenes](/apis/core/#SceneManager-scenes) | Scene list |
|
||||
| Property Name | Description |
|
||||
| :---------------------------------------- | :---------- |
|
||||
| [scenes](/apis/core/#SceneManager-scenes) | Scene list |
|
||||
|
||||
| Method Name | Description |
|
||||
| :--------------------------------------------------- | :---------- |
|
||||
| [addScene](/apis/core/#SceneManager-addScene) | Add scene |
|
||||
| [removeScene](/apis/core/#SceneManager-removeScene) | Remove scene|
|
||||
| [mergeScenes](/apis/core/#SceneManager-mergeScenes) | Merge scenes|
|
||||
| [loadScene](/apis/core/#SceneManager-loadScene) | Load scene |
|
||||
| Method Name | Description |
|
||||
| :-------------------------------------------------- | :----------- |
|
||||
| [addScene](/apis/core/#SceneManager-addScene) | Add scene |
|
||||
| [removeScene](/apis/core/#SceneManager-removeScene) | Remove scene |
|
||||
| [mergeScenes](/apis/core/#SceneManager-mergeScenes) | Merge scenes |
|
||||
| [loadScene](/apis/core/#SceneManager-loadScene) | Load scene |
|
||||
|
||||
### Loading a Scene
|
||||
|
||||
@@ -64,11 +59,9 @@ If you want to load a **Scene** asset as a scene in the application, you can use
|
||||
```typescript
|
||||
const sceneUrl = "...";
|
||||
|
||||
engine.resourceManager
|
||||
.load({ type: AssetType.Scene, url: "..." })
|
||||
.then((scene) => {
|
||||
engine.sceneManager.addScene(scene);
|
||||
});
|
||||
engine.resourceManager.load({ type: AssetType.Scene, url: "..." }).then((scene) => {
|
||||
engine.sceneManager.addScene(scene);
|
||||
});
|
||||
```
|
||||
|
||||
### Getting Scene Objects
|
||||
@@ -126,12 +119,12 @@ Call `scene.destroy()` to destroy a scene. The destroyed scene will also be auto
|
||||
|
||||
### Entity Tree Management
|
||||
|
||||
| Method Name | Description |
|
||||
| :------------------------------------------------------- | :---------------------------------------------------------------------------------------------------------- |
|
||||
| [createRootEntity](/apis/core/#Scene-createRootEntity) | The newly created _scene_ does not have a root entity by default and needs to be created manually |
|
||||
| [addRootEntity](/apis/core/#Scene-addRootEntity) | You can directly create a new entity or add an existing entity |
|
||||
| [removeRootEntity](/apis/core/#Scene-removeRootEntity) | Remove the root entity |
|
||||
| [getRootEntity](/apis/core/#Scene-getRootEntity) | Find the root entity, you can get all root entities or a single entity object. Note that all entities are read-only arrays and cannot change length or order |
|
||||
| Method Name | Description |
|
||||
| :-- | :-- |
|
||||
| [createRootEntity](/apis/core/#Scene-createRootEntity) | The newly created _scene_ does not have a root entity by default and needs to be created manually |
|
||||
| [addRootEntity](/apis/core/#Scene-addRootEntity) | You can directly create a new entity or add an existing entity |
|
||||
| [removeRootEntity](/apis/core/#Scene-removeRootEntity) | Remove the root entity |
|
||||
| [getRootEntity](/apis/core/#Scene-getRootEntity) | Find the root entity, you can get all root entities or a single entity object. Note that all entities are read-only arrays and cannot change length or order |
|
||||
|
||||
```typescript
|
||||
const engine = await WebGLEngine.create({ canvas: "demo" });
|
||||
@@ -161,4 +154,7 @@ const cameraEntity = rootEntity.createChild("camera");
|
||||
|
||||
cameraEntity.addComponent(Camera);
|
||||
```
|
||||
|
||||
```
|
||||
|
||||
```
|
||||
|
||||
@@ -81,6 +81,7 @@ The functionality corresponding to each property is as follows:
|
||||
| | [msaaSamples](/apis/core/#Camera-msaaSamples) | Number of samples for multi-sample anti-aliasing, effective only when the standalone canvas is enabled, such as `enableHDR`, `enablePostProcess`, `opaqueTextureEnabled`. |
|
||||
| | [enableHDR](/apis/core/#Camera-enableHDR) | Whether to enable HDR rendering, allowing the shader's output color to be stored using floating-point numbers, providing a wider range of values for post-processing and other scenarios. |
|
||||
| | [enablePostProcess](/apis/core/#Camera-enablePostProcess) | Whether to enable post-processing. For post-processing configuration, see [Post-Processing Tutorial](/en/docs/graphics/postProcess/postProcess). |
|
||||
| | [postProcessMask](/apis/core/#Camera-postProcessMask) | Post-processing mask, which determines the effective post-processing components. For post-processing configuration, [Post-Processing Tutorial](/en/docs/graphics/postProcess/postProcess). |
|
||||
|
||||
### Culling Mask
|
||||
|
||||
|
||||
149
docs/en/graphics/postProcess/customPostProcess.mdx
Normal file
149
docs/en/graphics/postProcess/customPostProcess.mdx
Normal file
@@ -0,0 +1,149 @@
|
||||
---
|
||||
order: 2
|
||||
title: Custom Post-Processing
|
||||
---
|
||||
|
||||
In the post-processing system, the effect ([Effect](/apis/core/#PostProcessEffect)) is responsible for maintaining the data layer, and the pipeline ([Pass](/apis/core/#PostProcessPass)) is responsible for writing the rendering logic. In the pipeline, calling the [getBlendEffect](/apis/core/#PostProcessManager-getBlendEffect) method can get the final post-processing data after **global/local** mixing.
|
||||
|
||||
<Image src="https://gw.alipayobjects.com/zos/OasisHub/d8b0e2e8-76d7-49d5-ae61-3889cdba011d/image-20250115155920429.png" />
|
||||
|
||||
The engine has built-in [PostProcessUberPass](/apis/core/#PostProcessUberPass), which is used with [BloomEffect](/apis/core/#BloomEffect) and [TonemappingEffect](/apis/core/#TonemappingEffect) data. If you want to customize post-processing effects, we need to create a new Pass and then create an Effect based on whether the data needs to be fused.
|
||||
|
||||
## A Demo
|
||||
|
||||
Here we will simply implement a grayscale image post-processing effect~
|
||||
|
||||
<Comparison
|
||||
leftSrc="https://gw.alipayobjects.com/zos/OasisHub/f5d3ea3d-47a4-4618-b3d6-0ea46321e786/image-20250115162952605.png"
|
||||
leftText="Uber Pass"
|
||||
rightSrc="https://gw.alipayobjects.com/zos/OasisHub/75ccba72-b70b-49f6-812a-e00305e89201/image-20250115163026345.png"
|
||||
rightText="Uber Pass + Custom Pass"
|
||||
/>
|
||||
|
||||
### 1. Shader Writing
|
||||
|
||||
The algorithm is not special, but you need to pay attention to `renderer_BlitTexture` This built-in variable is the post-processing rendering result of the previous Pass. Here it is the result after Bloom and Tonemapping. We display this result in grayscale.
|
||||
|
||||
```ts showLineNumbers {14}
|
||||
const customShader = Shader.create(
|
||||
"Gray Scale Shader",
|
||||
`
|
||||
attribute vec4 POSITION_UV;
|
||||
varying vec2 v_uv;
|
||||
|
||||
void main() {
|
||||
gl_Position = vec4(POSITION_UV.xy, 0.0, 1.0);
|
||||
v_uv = POSITION_UV.zw;
|
||||
}
|
||||
`,
|
||||
`
|
||||
varying vec2 v_uv;
|
||||
uniform sampler2D renderer_BlitTexture;
|
||||
|
||||
void main(){
|
||||
vec4 color = texture2D(renderer_BlitTexture, v_uv);
|
||||
float grayScale = 0.299 * color.r + 0.587 * color.g + 0.114 * color.b;
|
||||
gl_FragColor = vec4(vec3(grayScale), 1.0);
|
||||
}
|
||||
`
|
||||
);
|
||||
```
|
||||
|
||||
### 2. Create a new Pass
|
||||
|
||||
We create a new Pass, directly [Blitter](/apis/core/#Blitter) to the screen in the [onRender hook](/apis/core/#PostProcessUberPass-onRender), and then add this Pass to the engine.
|
||||
|
||||
```ts showLineNumbers {10,15}
|
||||
class CustomPass extends PostProcessPass {
|
||||
private _blitMaterial: Material;
|
||||
|
||||
constructor(engine: Engine) {
|
||||
super(engine);
|
||||
this._blitMaterial = new Material(this.engine, customShader);
|
||||
}
|
||||
|
||||
onRender(_, srcTexture: Texture2D, dst: RenderTarget): void {
|
||||
Blitter.blitTexture(this.engine, srcTexture, dst, undefined, undefined, this._blitMaterial, 0);
|
||||
}
|
||||
}
|
||||
|
||||
const customPass = new CustomPass(engine);
|
||||
engine.addPostProcessPass(customPass);
|
||||
```
|
||||
|
||||
The execution order of Pass is executed after Uber Pass by default, that is [`PostProcessPassEvent.AfterUber`](/apis/core/#PostProcessPassEvent-AfterUber), we can also manually modify the execution order of the pipeline:
|
||||
|
||||
```ts
|
||||
customPass.event = PostProcessPassEvent.BeforeUber;
|
||||
```
|
||||
|
||||
Whether the Pass is effective is determined by the Pass's [isActive](/apis/core/#PostProcessUberPass-isActive) by default. We can also modify the effectiveness logic, such as whether the intensity is greater than 0:
|
||||
|
||||
```ts showLineNumbers {2-9}
|
||||
class CustomPass extends PostProcessPass {
|
||||
override isValid(postProcessManager: PostProcessManager): boolean {
|
||||
if (!this.isActive) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const customEffectBlend = postProcessManager.getBlendEffect(CustomEffect);
|
||||
return customEffectBlend?.intensity > 0;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 3. Blend data
|
||||
|
||||
The above steps 1 and 2 can already customize the post-processing effect. Here is an advanced version of Blend data.
|
||||
|
||||
Take `intensity` as an example. We define a `CustomEffect`, which is specifically used to fuse intensity. The data to be fused is also very simple. The engine has encapsulated a series of post-processing parameters, such as [floating point type parameters](/apis/core/#PostProcessEffectFloatParameter).
|
||||
|
||||
```ts showLineNumbers {2,7}
|
||||
class CustomEffect extends PostProcessEffect {
|
||||
intensity = new PostProcessEffectFloatParameter(0.8);
|
||||
}
|
||||
|
||||
// Add this effect to the post-processing component. postProcess can be created separately,
|
||||
// or it can be the same as Bloom and other effects. It depends on the Blend requirements~
|
||||
postProcess.addEffect(CustomEffect);
|
||||
```
|
||||
|
||||
After defining the data, you need to change the `onRender` hook of the custom Pass to get the Blend data:
|
||||
|
||||
```ts showLineNumbers {3-6}
|
||||
class CustomPass extends PostProcessPass {
|
||||
onRender(camera: Camera, srcTexture: Texture2D, dst: RenderTarget): void {
|
||||
const postProcessManager = camera.scene.postProcessManager;
|
||||
const customEffectBlend = postProcessManager.getBlendEffect(CustomEffect);
|
||||
if (customEffectBlend) {
|
||||
this._blitMaterial.shaderData.setFloat("u_intensity", customEffectBlend.intensity.value);
|
||||
}
|
||||
|
||||
Blitter.blitTexture(this.engine, srcTexture, dst, undefined, undefined, this._blitMaterial, 0);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
As you can see, we continuously set the fused intensity in the `onRender` hook of the custom pipeline, and then consume this data in the shader:
|
||||
|
||||
```ts showLineNumbers {8,12}
|
||||
const customShader = Shader.create(
|
||||
"Gray Scale Shader",
|
||||
`
|
||||
......
|
||||
`,
|
||||
`
|
||||
......
|
||||
uniform float u_intensity;
|
||||
|
||||
void main(){
|
||||
......
|
||||
gl_FragColor = vec4(mix(color.rgb, vec3(grayScale), u_intensity), 1.0);
|
||||
}
|
||||
`
|
||||
);
|
||||
```
|
||||
|
||||
If your post-processing component is in local mode, we can also use [Blend Distance](/apis/core/#PostProcess-blendDistance) to set the distance at which the camera is close to the collision body to start blending:
|
||||
|
||||
<Image src="https://gw.alipayobjects.com/zos/OasisHub/76b084c1-f517-47d7-8067-7f838db002f8/2025-01-15%25252017.38.30.gif" />
|
||||
@@ -3,95 +3,77 @@ order: 0
|
||||
title: Post Process Overview
|
||||
---
|
||||
|
||||
The post-processing system can "process" the results of scene rendering.
|
||||
The post-processing system can "process" the results rendered by the camera.
|
||||
|
||||
<Image
|
||||
src="https://gw.alipayobjects.com/zos/OasisHub/3a50ed18-c2d4-4b33-a4e6-af79f2c273f8/2024-07-18%25252018.08.30.gif"
|
||||
figcaption="Close post-processing"
|
||||
<Comparison
|
||||
leftSrc="https://gw.alipayobjects.com/zos/OasisHub/3a50ed18-c2d4-4b33-a4e6-af79f2c273f8/2024-07-18%25252018.08.30.gif"
|
||||
leftText="OFF"
|
||||
rightSrc="https://gw.alipayobjects.com/zos/OasisHub/4bd5f985-1b82-4aca-b6fa-fd521aab8f57/2024-07-18%25252018.15.30.gif"
|
||||
rightText="ON"
|
||||
/>
|
||||
|
||||
<Image
|
||||
src="https://gw.alipayobjects.com/zos/OasisHub/4bd5f985-1b82-4aca-b6fa-fd521aab8f57/2024-07-18%25252018.15.30.gif"
|
||||
figcaption="Open post-processing"
|
||||
/>
|
||||
## Post-Processing Configuration
|
||||
|
||||
## Use post-processing
|
||||
There are two modes for post-processing:
|
||||
|
||||
### 1. Post-processing configuration
|
||||
- Global Mode: Affects all cameras in the current scene.
|
||||
- Local Mode: Only effective when the camera is within the collision range of the post-processing entity.
|
||||
|
||||
Post-processing configuration is uniformly placed in [scene](/en/docs/core/scene) panel, in order to prevent performance waste, the default **turn off**, users only need to turn on the main switch to activate all post-processing effects:
|
||||
The post-processing component has the following properties to control effects, modes, blending distances, etc.:
|
||||
|
||||
<Image src="https://gw.alipayobjects.com/zos/OasisHub/50f6a2aa-0463-4b66-b54e-edff71187077/image-20240718193530098.png" />
|
||||
| Property | Description |
|
||||
| :-- | :-- |
|
||||
| [isGlobal](/apis/core/#PostProcess-isGlobal) | Controls whether this post-processing component is in global or local mode. |
|
||||
| [Blend Distance](/apis/core/#PostProcess-blendDistance) | In local mode, controls how close the camera must be to the collider before blending effects begins. |
|
||||
| [Priority](/apis/core/#PostProcess-priority) | When there are multiple post-processing components in the scene, a higher priority means blending/overriding starts later. |
|
||||
| [Layer](/apis/core/#PostProcess-layer) | Used with the camera's [post-processing mask](/apis/core/#Camera-postProcessMask) to determine which post-processing components are effective. |
|
||||
| [Add Effect](/apis/core/#PostProcess-addEffect) | Adds post-processing effects. |
|
||||
|
||||
## Using Post-Processing
|
||||
|
||||
### 1. Adding a Post-Processing Component
|
||||
|
||||
In the hierarchy panel, several modes for global and local post-processing are preset; simply select and add to use.
|
||||
|
||||
<Image src="https://gw.alipayobjects.com/zos/OasisHub/a6e9a327-1823-4dde-94a8-89bb4bf02e3a/2025-01-15%25252011.59.50.gif" />
|
||||
|
||||
Of course, you can also manually add post-processing components. Local mode needs to be used with colliders:
|
||||
|
||||
<Image src="https://gw.alipayobjects.com/zos/OasisHub/6eb3b8d5-27d1-419d-8bf6-65371861fb97/2025-01-15%25252014.51.12.gif" />
|
||||
|
||||
<Callout type="info">
|
||||
For specific post-processing effect configuration, please refer to [Post-processing Effect
|
||||
For specific post-processing effects configuration, please refer to the [Post-Processing Effects
|
||||
List](/en/docs/graphics/postProcess/effects)
|
||||
</Callout>
|
||||
|
||||
<Callout type="warning">
|
||||
As of version 1.3, the engine does not expose public APIs (because after supporting post-processing extensions, the
|
||||
APIs may change). We recommend that users perform post-processing operations in the editor. If you want to use the
|
||||
internal experimental interface, you can call the following code:
|
||||
</Callout>
|
||||
### 2. Camera Switch
|
||||
|
||||
```typescript
|
||||
// Get the post-processing manager
|
||||
// @ts-ignore
|
||||
const postProcessManager = scene._postProcessManager;
|
||||
// Get BloomEffect
|
||||
const bloomEffect = postProcessManager._bloomEffect as BloomEffect;
|
||||
// Get TonemappingEffect
|
||||
const tonemappingEffect = postProcessManager._tonemappingEffect as TonemappingEffect;
|
||||
The camera preview area is controlled by the **Camera Component**. In the camera component, the following properties will also affect the post-processing effects:
|
||||
|
||||
// Activate the main switch
|
||||
postProcessManager.isActive = true;
|
||||
|
||||
// Adjust BloomEffect properties
|
||||
bloomEffect.enabled = true;
|
||||
bloomEffect.downScale = BloomDownScaleMode.Half;
|
||||
bloomEffect.threshold = 0.9;
|
||||
bloomEffect.scatter = 0.7;
|
||||
bloomEffect.intensity = 1;
|
||||
bloomEffect.tint.set(1, 1, 1, 1);
|
||||
|
||||
// Adjust TonemappingEffect properties
|
||||
tonemappingEffect.enabled = true;
|
||||
tonemappingEffect.mode = TonemappingMode.ACES;
|
||||
```
|
||||
|
||||
### 2. Camera switch
|
||||
|
||||
The camera preview area is controlled by the **camera component**. In the camera component, the following properties will affect the post-processing effect:
|
||||
|
||||
- **Post-processing switch**: You can turn on or off the camera's post-processing effect. The overall switch and specific configuration of post-processing are in the [scene](/en/docs/core/scene) panel.
|
||||
|
||||
- **HDR switch**: In HDR mode, the output color is allowed to be stored using floating point numbers, which can obtain a wider range of values for scenes such as [bloom effects](/en/docs/graphics/postProcess/effects).
|
||||
|
||||
- **MSAA configuration**: You can adjust the settings of multi-sampling anti-aliasing to improve the quality of the picture such as aliasing.
|
||||
|
||||
<Image src="https://gw.alipayobjects.com/zos/OasisHub/3232935d-a765-4da4-b08e-021aac61458e/image-20240718210947199.png" />
|
||||
| Property | Description |
|
||||
| :-- | :-- |
|
||||
| [Post-Processing Switch](/apis/core/#Camera-enablePostProcess) | Enables or disables the post-processing effects of the camera. |
|
||||
| [HDR Switch](/apis/core/#Camera-enableHDR) | In HDR mode, allows output colors to be stored using floating-point numbers, providing a broader range of values for [bloom effects](/en/docs/graphics/postProcess/effects) and other scenarios. |
|
||||
| [MSAA Configuration](/apis/core/#Camera-msaaSamples) | Adjusts the multi-sampling anti-aliasing settings to improve image quality, such as reducing jagged edges. |
|
||||
| [Post-Processing Mask](/apis/core/#Camera-postProcessMask) | Works with the post-processing component's [layer](/apis/core/#PostProcess-layer) to determine which post-processing components are effective. |
|
||||
|
||||
<Callout type="info">
|
||||
For more camera configurations, refer to [Camera Component](/en/docs/graphics/camera/component)
|
||||
For more camera configurations, refer to the [Camera Component](/en/docs/graphics/camera/component)
|
||||
</Callout>
|
||||
|
||||
### 3. Viewport Switch
|
||||
|
||||
In addition to the camera preview area, the viewport can also see the post-processing effect. The camera in the viewport is independent, but it also has post-processing switches like the camera component (same as above, also pay attention to the switches in the post-processing configuration); the switches in the viewport only affect the view window and do not affect the actual effect of the project export:
|
||||
In addition to the camera preview area, the viewport can also display post-processing effects. The camera in the viewport is independent but has post-processing configurations similar to the camera component.
|
||||
|
||||
<Image src="https://gw.alipayobjects.com/zos/OasisHub/f9f13d02-931f-4638-af91-4a007007c99f/image-20240718193359413.png" />
|
||||
<Callout type="warning">
|
||||
The switch in the viewport only affects the view window and does not impact the actual effect exported in the project.
|
||||
</Callout>
|
||||
|
||||
## Recommended configuration for mobile
|
||||
<Image src="https://gw.alipayobjects.com/zos/OasisHub/e3c55184-f51c-4a7a-9a12-ad490774dc26/image-20250115151324628-20250115151336116.png" />
|
||||
|
||||
Generally speaking, some post-processing configurations in the red box in the figure below will affect performance:
|
||||
## Best Practices
|
||||
|
||||
<Image src="https://gw.alipayobjects.com/zos/OasisHub/7e5e272c-fc1e-45cd-92b0-a687c58826c7/image-20240719104328198.png" />
|
||||
|
||||
And some camera configurations:
|
||||
|
||||
<Image src="https://gw.alipayobjects.com/zos/OasisHub/5d96cd31-2e12-43eb-8493-f8751e40eb82/image-20240719112101652.png" />
|
||||
|
||||
- Regarding the `HDR` switch in the camera, if most of the pixel calculations in the scene do not exceed 1 (for example, HDR maps are not used), try not to turn on HDR. After turning it on, the engine will first render to `R11G11B10_UFloat` format In RenderTarget, rendering to the screen again has performance overhead.
|
||||
- Regarding the `MSAA` option in the camera, it is recommended to adjust this value only when post-processing is turned on and the anti-aliasing performance is strictly required. The larger the value, the greater the performance overhead.
|
||||
- In the bloom effect, `Down Scale` defaults to `Half`, that is, the initial downsampling resolution is half of the canvas. If the accuracy requirement is not so high, you can switch to `Quarter` and save 1/4 of the canvas.
|
||||
- In the tone mapping effect, although `ACES` has better color contrast and saturation, the calculation is more complicated, which may cause serious frame drops on low-end models. You can try to use `Neutral` as an alternative.
|
||||
- Regarding the `HDR` switch in the camera, if the majority of pixels in the scene do not exceed 1 (e.g., no HDR textures used), avoid enabling HDR. When enabled, the engine first renders to a `R11G11B10_UFloat` format RenderTarget before rendering to the screen, incurring performance overhead.
|
||||
- Regarding the `MSAA` option in the camera, only adjust this value when post-processing is enabled and strict on anti-aliasing performance. The higher the value, the greater the performance overhead.
|
||||
- In bloom effects, `Down Scale` defaults to `Half`, meaning the initial downsampled resolution is half that of the canvas. If high precision is not required, switch to `Quarter`, saving to a quarter of the canvas.
|
||||
- In tone mapping effects, while `ACES` offers better color contrast and saturation, it is computationally complex and may cause significant frame drops on low-end devices. Consider using `Neutral` as an alternative.
|
||||
|
||||
@@ -19,7 +19,7 @@ Scene 作为场景单元,可以方便的进行实体树管理,尤其是大
|
||||
|
||||
### 属性面板
|
||||
|
||||
<img src="https://gw.alipayobjects.com/zos/OasisHub/2eaad4b1-d3e3-4c17-ae7f-58b488cd3606/image-20240718190944508.png" alt="image-20240718190944508" style="zoom:50%;" />
|
||||
<img src="https://gw.alipayobjects.com/zos/OasisHub/e263593a-5b63-43a7-93ec-26c571939b5b/image-20250114194300836.png" alt="image-20240718190944508" style="zoom:50%;" />
|
||||
|
||||
### 环境光
|
||||
|
||||
@@ -33,25 +33,20 @@ Scene 作为场景单元,可以方便的进行实体树管理,尤其是大
|
||||
|
||||
详情请参照[阴影教程](/docs/graphics/light/shadow/)。
|
||||
|
||||
### 后处理
|
||||
|
||||
详情请参照[后处理教程](/docs/graphics/postProcess/postProcess/)。
|
||||
|
||||
### 雾化
|
||||
|
||||
可以给整个场景增加 **线性、指数、指数平方** 3 种雾化:
|
||||
|
||||

|
||||
|
||||
|
||||
## 脚本使用
|
||||
|
||||
| 属性名称 | 解释 |
|
||||
| :--------------------------------------- | :------- |
|
||||
| 属性名称 | 解释 |
|
||||
| :---------------------------------------- | :------- |
|
||||
| [scenes](/apis/core/#SceneManager-scenes) | 场景列表 |
|
||||
|
||||
| 方法名称 | 解释 |
|
||||
| :------------------------------------------------- | :------- |
|
||||
| 方法名称 | 解释 |
|
||||
| :-------------------------------------------------- | :------- |
|
||||
| [addScene](/apis/core/#SceneManager-addScene) | 添加场景 |
|
||||
| [removeScene](/apis/core/#SceneManager-removeScene) | 移除场景 |
|
||||
| [mergeScenes](/apis/core/#SceneManager-mergeScenes) | 合并场景 |
|
||||
@@ -64,11 +59,9 @@ Scene 作为场景单元,可以方便的进行实体树管理,尤其是大
|
||||
```typescript
|
||||
const sceneUrl = "...";
|
||||
|
||||
engine.resourceManager
|
||||
.load({ type: AssetType.Scene, url: "..." })
|
||||
.then((scene) => {
|
||||
engine.sceneManager.addScene(scene);
|
||||
});
|
||||
engine.resourceManager.load({ type: AssetType.Scene, url: "..." }).then((scene) => {
|
||||
engine.sceneManager.addScene(scene);
|
||||
});
|
||||
```
|
||||
|
||||
### 获取场景对象
|
||||
@@ -126,12 +119,12 @@ engine.sceneManager.addScene(destScene);
|
||||
|
||||
### 实体树管理
|
||||
|
||||
| 方法名称 | 解释 |
|
||||
| :---------------------------------------------------- | :--------------------------------------------------------------------------------------------------- |
|
||||
| [createRootEntity](/apis/core/#Scene-createRootEntity) | 新创建的 _scene_ 默认没有根实体,需要手动创建 |
|
||||
| [addRootEntity](/apis/core/#Scene-addRootEntity) | 可以直接新建实体,或者添加已经存在的实体 |
|
||||
| [removeRootEntity](/apis/core/#Scene-removeRootEntity) | 删除根实体 |
|
||||
| [getRootEntity](/apis/core/#Scene-getRootEntity) | 查找根实体,可以拿到全部根实体,或者单独的某个实体对象。注意,全部实体是只读数组,不能改变长度和顺序 |
|
||||
| 方法名称 | 解释 |
|
||||
| :-- | :-- |
|
||||
| [createRootEntity](/apis/core/#Scene-createRootEntity) | 新创建的 _scene_ 默认没有根实体,需要手动创建 |
|
||||
| [addRootEntity](/apis/core/#Scene-addRootEntity) | 可以直接新建实体,或者添加已经存在的实体 |
|
||||
| [removeRootEntity](/apis/core/#Scene-removeRootEntity) | 删除根实体 |
|
||||
| [getRootEntity](/apis/core/#Scene-getRootEntity) | 查找根实体,可以拿到全部根实体,或者单独的某个实体对象。注意,全部实体是只读数组,不能改变长度和顺序 |
|
||||
|
||||
```typescript
|
||||
const engine = await WebGLEngine.create({ canvas: "demo" });
|
||||
|
||||
@@ -81,6 +81,7 @@ camera.enableHDR = true;
|
||||
| | [msaaSamples](/apis/core/#Camera-msaaSamples) | 多样本抗锯齿采样样本数量,仅当独立画布开启时才能生效,如 `enableHDR`、`enablePostProcess`、`opaqueTextureEnabled`。 |
|
||||
| | [enableHDR](/apis/core/#Camera-enableHDR) | 是否启用 HDR 渲染,允许 shader 输出的颜色使用浮点数进行存储,可以得到更大范围的值,用于后处理等场景。 |
|
||||
| | [enablePostProcess](/apis/core/#Camera-enablePostProcess) | 是否启用后处理,后处理配置详见[后处理教程](/docs/graphics/postProcess/postProcess)。 |
|
||||
| | [postProcessMask](/apis/core/#Camera-postProcessMask) | 后处理遮罩,决定生效的后处理组件,后处理配置详见[后处理教程](/docs/graphics/postProcess/postProcess)。 |
|
||||
|
||||
### 裁剪遮罩
|
||||
|
||||
|
||||
149
docs/zh/graphics/postProcess/customPostProcess.mdx
Normal file
149
docs/zh/graphics/postProcess/customPostProcess.mdx
Normal file
@@ -0,0 +1,149 @@
|
||||
---
|
||||
order: 2
|
||||
title: 自定义后处理
|
||||
---
|
||||
|
||||
在后处理系统中,特效([Effect](/apis/core/#PostProcessEffect)) 负责数据层的维护,管线([Pass](/apis/core/#PostProcessPass))负责渲染逻辑的编写,在管线中调用 [getBlendEffect](/apis/core/#PostProcessManager-getBlendEffect) 方法可以拿到经过 **全局/局部** 混合后的最终后处理数据。
|
||||
|
||||
<Image src="https://gw.alipayobjects.com/zos/OasisHub/d8b0e2e8-76d7-49d5-ae61-3889cdba011d/image-20250115155920429.png" />
|
||||
|
||||
引擎内置了 [PostProcessUberPass](/apis/core/#PostProcessUberPass),搭配 [BloomEffect](/apis/core/#BloomEffect) 和 [TonemappingEffect](/apis/core/#TonemappingEffect) 的数据使用,如果想要自定义后处理特效,我们需要新建一个 Pass,然后根据是否需要融合数据来创建 Effect。
|
||||
|
||||
## 一个 Demo
|
||||
|
||||
这里就简单地实现一个灰度图的后处理效果吧~
|
||||
|
||||
<Comparison
|
||||
leftSrc="https://gw.alipayobjects.com/zos/OasisHub/f5d3ea3d-47a4-4618-b3d6-0ea46321e786/image-20250115162952605.png"
|
||||
leftText="Uber Pass"
|
||||
rightSrc="https://gw.alipayobjects.com/zos/OasisHub/75ccba72-b70b-49f6-812a-e00305e89201/image-20250115163026345.png"
|
||||
rightText="Uber Pass + Custom Pass"
|
||||
/>
|
||||
|
||||
### 1. Shader 编写
|
||||
|
||||
算法没有特殊的, 需要注意 `renderer_BlitTexture` 这个内置变量就是上一个 Pass 的后处理渲染结果,在此处就是 Bloom 和 Tonemapping 后的结果,我们针对这个结果进行了灰度显示。
|
||||
|
||||
```ts showLineNumbers {14}
|
||||
const customShader = Shader.create(
|
||||
"Gray Scale Shader",
|
||||
`
|
||||
attribute vec4 POSITION_UV;
|
||||
varying vec2 v_uv;
|
||||
|
||||
void main() {
|
||||
gl_Position = vec4(POSITION_UV.xy, 0.0, 1.0);
|
||||
v_uv = POSITION_UV.zw;
|
||||
}
|
||||
`,
|
||||
`
|
||||
varying vec2 v_uv;
|
||||
uniform sampler2D renderer_BlitTexture;
|
||||
|
||||
void main(){
|
||||
vec4 color = texture2D(renderer_BlitTexture, v_uv);
|
||||
float grayScale = 0.299 * color.r + 0.587 * color.g + 0.114 * color.b;
|
||||
gl_FragColor = vec4(vec3(grayScale), 1.0);
|
||||
}
|
||||
`
|
||||
);
|
||||
```
|
||||
|
||||
### 2. 新建 Pass
|
||||
|
||||
我们新建一个 Pass,在 [onRender 钩子](/apis/core/#PostProcessUberPass-onRender) 里面直接 [Blitter](/apis/core/#Blitter) 到屏幕,然后将这个 Pass 添加到引擎中。
|
||||
|
||||
```ts showLineNumbers {10,15}
|
||||
class CustomPass extends PostProcessPass {
|
||||
private _blitMaterial: Material;
|
||||
|
||||
constructor(engine: Engine) {
|
||||
super(engine);
|
||||
this._blitMaterial = new Material(this.engine, customShader);
|
||||
}
|
||||
|
||||
onRender(_, srcTexture: Texture2D, dst: RenderTarget): void {
|
||||
Blitter.blitTexture(this.engine, srcTexture, dst, undefined, undefined, this._blitMaterial, 0);
|
||||
}
|
||||
}
|
||||
|
||||
const customPass = new CustomPass(engine);
|
||||
engine.addPostProcessPass(customPass);
|
||||
```
|
||||
|
||||
Pass 的执行顺序默认在 Uber Pass 的后面执行,即 [`PostProcessPassEvent.AfterUber`](/apis/core/#PostProcessPassEvent-AfterUber),我们也可以手动修改管线的执行顺序:
|
||||
|
||||
```ts
|
||||
customPass.event = PostProcessPassEvent.BeforeUber;
|
||||
```
|
||||
|
||||
Pass 是否生效默认是根据 Pass 的 [isActive](/apis/core/#PostProcessUberPass-isActive) 来决定的,我们也可以修改生效逻辑,比如强度是否大于 0 :
|
||||
|
||||
```ts showLineNumbers {2-9}
|
||||
class CustomPass extends PostProcessPass {
|
||||
override isValid(postProcessManager: PostProcessManager): boolean {
|
||||
if (!this.isActive) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const customEffectBlend = postProcessManager.getBlendEffect(CustomEffect);
|
||||
return customEffectBlend?.intensity > 0;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 3. 融合数据
|
||||
|
||||
上述 1、2 步骤已经能够自定义后处理效果,这里再来一个进阶版的融合数据。
|
||||
|
||||
拿 `intensity` 举例,我们定义一个 `CustomEffect`,专门用来融合强度,需要融合的数据也很简单,引擎已经封装了一系列后处理参数,如[浮点类型参数](/apis/core/#PostProcessEffectFloatParameter)。
|
||||
|
||||
```ts showLineNumbers {2,7}
|
||||
class CustomEffect extends PostProcessEffect {
|
||||
intensity = new PostProcessEffectFloatParameter(0.8);
|
||||
}
|
||||
|
||||
// 将这个 effect 添加到后处理组件中,postProcess 可以是单独新建的,
|
||||
// 也可以是跟 Bloom 等 effect 同一个,具体看融合的需求~
|
||||
postProcess.addEffect(CustomEffect);
|
||||
```
|
||||
|
||||
定义好数据后,需要在自定义 Pass 的 `onRender` 钩子中,改成获取融合数据:
|
||||
|
||||
```ts showLineNumbers {3-6}
|
||||
class CustomPass extends PostProcessPass {
|
||||
onRender(camera: Camera, srcTexture: Texture2D, dst: RenderTarget): void {
|
||||
const postProcessManager = camera.scene.postProcessManager;
|
||||
const customEffectBlend = postProcessManager.getBlendEffect(CustomEffect);
|
||||
if (customEffectBlend) {
|
||||
this._blitMaterial.shaderData.setFloat("u_intensity", customEffectBlend.intensity.value);
|
||||
}
|
||||
|
||||
Blitter.blitTexture(this.engine, srcTexture, dst, undefined, undefined, this._blitMaterial, 0);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
可以看到,我们在自定义管线的 `onRender` 钩子中,不断设置融合后的强度,然后在 shader 中消费这个数据即可:
|
||||
|
||||
```ts showLineNumbers {8,12}
|
||||
const customShader = Shader.create(
|
||||
"Gray Scale Shader",
|
||||
`
|
||||
......
|
||||
`,
|
||||
`
|
||||
......
|
||||
uniform float u_intensity;
|
||||
|
||||
void main(){
|
||||
......
|
||||
gl_FragColor = vec4(mix(color.rgb, vec3(grayScale), u_intensity), 1.0);
|
||||
}
|
||||
`
|
||||
);
|
||||
```
|
||||
|
||||
如果你的后处理组件是局部模式,我们还可以通过 [Blend Distance](/apis/core/#PostProcess-blendDistance) 来设置相机靠近碰撞体多少距离时开始混合:
|
||||
|
||||
<Image src="https://gw.alipayobjects.com/zos/OasisHub/76b084c1-f517-47d7-8067-7f838db002f8/2025-01-15%25252017.38.30.gif" />
|
||||
@@ -3,83 +3,69 @@ order: 0
|
||||
title: 后处理总览
|
||||
---
|
||||
|
||||
后处理系统可以对场景渲染的结果进行“加工”。
|
||||
后处理系统可以对相机渲染的结果进行“加工”。
|
||||
|
||||
<Comparison
|
||||
leftSrc="https://gw.alipayobjects.com/zos/OasisHub/3a50ed18-c2d4-4b33-a4e6-af79f2c273f8/2024-07-18%25252018.08.30.gif"
|
||||
leftText="关闭后处理"
|
||||
leftText="OFF"
|
||||
rightSrc="https://gw.alipayobjects.com/zos/OasisHub/4bd5f985-1b82-4aca-b6fa-fd521aab8f57/2024-07-18%25252018.15.30.gif"
|
||||
rightText="开启后处理"
|
||||
rightText="ON"
|
||||
/>
|
||||
|
||||
## 后处理配置
|
||||
|
||||
后处理有两种模式:
|
||||
|
||||
- 全局模式:影响当前场景中的所有相机。
|
||||
- 局部模式:只有当相机靠近后处理实体的碰撞体范围时才生效。
|
||||
|
||||
后处理组件拥有以下属性,可以控制后处理的特效、模式、混合距离等:
|
||||
|
||||
| 属性 | 作用 |
|
||||
| :-- | :-- |
|
||||
| [全局模式](/apis/core/#PostProcess-isGlobal) | 控制这个后处理组件是全局还是局部模式。 |
|
||||
| [混合距离](/apis/core/#PostProcess-blendDistance) | 局部模式时,用来控制相机靠近碰撞体多少距离时,开始混合特效。 |
|
||||
| [优先级](/apis/core/#PostProcess-priority) | 当场景中有多个后处理组件时,优先级越高,越后面开始覆盖/混合。 |
|
||||
| [层级](/apis/core/#PostProcess-layer) | 配合相机的[后处理遮罩](/apis/core/#Camera-postProcessMask) 使用,决定生效的后处理组件。 |
|
||||
| [添加特效](/apis/core/#PostProcess-addEffect) | 添加后处理特效。 |
|
||||
|
||||
## 使用后处理
|
||||
|
||||
### 1.后处理配置
|
||||
### 1.添加后处理组件
|
||||
|
||||
后处理配置统一放在 [场景](/docs/core/scene) 面板下,为了防止性能浪费,默认**关闭总开关**,用户只需要打开总开关,就能激活所有后处理效果:
|
||||
在层级面板,预设了全局、局部后处理的几种模式,选择添加即可直接使用。
|
||||
|
||||
<Image src="https://gw.alipayobjects.com/zos/OasisHub/50f6a2aa-0463-4b66-b54e-edff71187077/image-20240718193530098.png" />
|
||||
<Image src="https://gw.alipayobjects.com/zos/OasisHub/a6e9a327-1823-4dde-94a8-89bb4bf02e3a/2025-01-15%25252011.59.50.gif" />
|
||||
|
||||
当然,也可以手动添加后处理组件,局部模式需要搭配碰撞体进行使用:
|
||||
|
||||
<Image src="https://gw.alipayobjects.com/zos/OasisHub/6eb3b8d5-27d1-419d-8bf6-65371861fb97/2025-01-15%25252014.51.12.gif" />
|
||||
|
||||
<Callout type="info">具体的后处理效果配置,请参考 [后处理效果列表](/docs/graphics/postProcess/effects)</Callout>
|
||||
|
||||
<Callout type="warning">
|
||||
截止 1.3 版本,引擎没有暴露公共 API(因为支持后处理拓展后,API
|
||||
可能会产生变动),我们建议用户在编辑器进行后处理操作。如果想使用内部实验接口,可以调用以下代码:
|
||||
</Callout>
|
||||
|
||||
```typescript
|
||||
// 获取后处理管理器
|
||||
// @ts-ignore
|
||||
const postProcessManager = scene._postProcessManager;
|
||||
// 获取 BloomEffect
|
||||
const bloomEffect = postProcessManager._bloomEffect as BloomEffect;
|
||||
// 获取 TonemappingEffect
|
||||
const tonemappingEffect = postProcessManager._tonemappingEffect as TonemappingEffect;
|
||||
|
||||
// 激活总开关
|
||||
postProcessManager.isActive = true;
|
||||
|
||||
// 调整 BloomEffect 属性
|
||||
bloomEffect.enabled = true;
|
||||
bloomEffect.downScale = BloomDownScaleMode.Half;
|
||||
bloomEffect.threshold = 0.9;
|
||||
bloomEffect.scatter = 0.7;
|
||||
bloomEffect.intensity = 1;
|
||||
bloomEffect.tint.set(1, 1, 1, 1);
|
||||
|
||||
// 调整 TonemappingEffect 属性
|
||||
tonemappingEffect.enabled = true;
|
||||
tonemappingEffect.mode = TonemappingMode.ACES;
|
||||
```
|
||||
|
||||
### 2.相机开关
|
||||
|
||||
相机预览区受**相机组件**控制,相机组件中,以下属性会影响后处理效果:
|
||||
相机预览区受**相机组件**控制,在相机组件中,以下属性也会影响后处理效果:
|
||||
|
||||
- **后处理开关**:可以开启或关闭相机的后期处理效果,后处理的总开关和具体配置在 [场景](/docs/core/scene) 面板。
|
||||
- **HDR 开关**:HDR 模式下,允许输出颜色使用浮点数进行存储,可以得到更大范围的值,用于[泛光特效](/docs/graphics/postProcess/effects)等场景。
|
||||
- **MSAA 配置**:可以调整多重采样抗锯齿的设置,改善锯齿等画面质量。
|
||||
|
||||
<Image src="https://gw.alipayobjects.com/zos/OasisHub/3232935d-a765-4da4-b08e-021aac61458e/image-20240718210947199.png" />
|
||||
| 属性 | 作用 |
|
||||
| :-- | :-- |
|
||||
| [后处理开关](/apis/core/#Camera-enablePostProcess) | 可以开启或关闭相机的后期处理效果。 |
|
||||
| [HDR 开关](/apis/core/#Camera-enableHDR) | HDR 模式下,允许输出颜色使用浮点数进行存储,可以得到更大范围的值,用于[泛光特效](/docs/graphics/postProcess/effects)等场景。 |
|
||||
| [MSAA 配置](/apis/core/#Camera-msaaSamples) | 可以调整多重采样抗锯齿的设置,改善锯齿等画面质量。 |
|
||||
| [后处理遮罩](/apis/core/#Camera-postProcessMask) | 配合后处理组件的[层级](/apis/core/#PostProcess-layer) 使用,决定生效的后处理组件。 |
|
||||
|
||||
<Callout type="info">相机更多配置参考 [相机组件](/docs/graphics/camera/component)</Callout>
|
||||
|
||||
### 3.视图区开关
|
||||
|
||||
除了相机预览区,视图区也能看到后处理效果。视图区的相机是独立的,但是也和相机组件一样拥有后处理等开关(同上,也要注意后处理配置中的开关);视图区的开关只会影响视图窗口,并不会影响项目导出的真实效果:
|
||||
除了相机预览区,视图区也能看到后处理效果。视图区的相机是独立的,但是也和相机组件一样拥有后处理等配置。
|
||||
|
||||
<Image src="https://gw.alipayobjects.com/zos/OasisHub/f9f13d02-931f-4638-af91-4a007007c99f/image-20240718193359413.png" />
|
||||
<Callout type="warning">视图区的开关只会影响视图窗口,并不会影响项目导出的真实效果</Callout>
|
||||
|
||||
<Image src="https://gw.alipayobjects.com/zos/OasisHub/e3c55184-f51c-4a7a-9a12-ad490774dc26/image-20250115151324628-20250115151336116.png" />
|
||||
|
||||
## 最佳实践
|
||||
|
||||
一般来说,下图红框内的一些后处理配置会影响到性能:
|
||||
|
||||
<Image src="https://gw.alipayobjects.com/zos/OasisHub/7e5e272c-fc1e-45cd-92b0-a687c58826c7/image-20240719104328198.png" />
|
||||
|
||||
以及相机的部分配置:
|
||||
|
||||
<Image src="https://gw.alipayobjects.com/zos/OasisHub/5d96cd31-2e12-43eb-8493-f8751e40eb82/image-20240719112101652.png" />
|
||||
|
||||
- 关于相机中 `HDR` 开关,如果场景中绝大部分像素计算没有超过 1(比如没有使用 HDR 贴图), 尽量别开启 HDR,开启后引擎会先渲染到 `R11G11B10_UFloat` 格式的 RenderTarget 中,再渲染到屏幕上,有性能开销。
|
||||
- 关于相机中的 `MSAA` 选项,仅当开启了后处理,且对锯齿表现要求严格的情况下,才建议调整这个值,值越大,性能开销越大。
|
||||
- 泛光特效中,`Down Scale` 默认为 `Half`,即初始降采样的分辨率为画布的一半,如果对精度要求没那么高,可以切换为 `Quarter`,节省为画布的 1/4。
|
||||
|
||||
Reference in New Issue
Block a user