Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support post process #2129

Merged
merged 49 commits into from
Jul 11, 2024
Merged
Show file tree
Hide file tree
Changes from 48 commits
Commits
Show all changes
49 commits
Select commit Hold shift + click to select a range
7dd4ad9
feat: init API from RFC
zhuxudong Jun 6, 2024
84ab347
refactor: use pass
zhuxudong Jun 6, 2024
7fce166
feat: init passes
zhuxudong Jun 7, 2024
fe68f92
feat: init effect api
zhuxudong Jun 11, 2024
297edda
feat: add hdr
zhuxudong Jun 11, 2024
d976fc2
refactor: change independentCanvasEnabled
zhuxudong Jun 13, 2024
fa36515
feat: add RT switch
zhuxudong Jun 14, 2024
03240bf
feat: init filter effect
zhuxudong Jun 18, 2024
2a2221f
feat: add HQ bloom
zhuxudong Jun 18, 2024
3e00e8e
fix: gamma to linear
zhuxudong Jun 18, 2024
2dc255a
feat: init bloom shader
zhuxudong Jun 18, 2024
09b76e4
feat: support bloom shader
zhuxudong Jun 20, 2024
27a56d7
Merge branch 'dev/1.3' into feat/post-process
zhuxudong Jun 20, 2024
f13e3ea
feat: init tonemapping
zhuxudong Jun 20, 2024
53531d5
fix: shader error
zhuxudong Jun 24, 2024
0205090
refactor: limit max iteration
zhuxudong Jun 25, 2024
9fb5169
fix: clamp specular AA
zhuxudong Jun 25, 2024
7884c6d
ci: test error
zhuxudong Jun 28, 2024
52a1c91
Merge branch 'dev/1.3' into feat/post-process
zhuxudong Jun 28, 2024
54dcbaa
refactor: use RenderBufferStoreAction
zhuxudong Jul 2, 2024
1cc4f0a
refactor: move postProcess code to manager
zhuxudong Jul 2, 2024
d38375c
refactor: use triangle to blit render target
zhuxudong Jul 2, 2024
cd9facc
refactor: remove post renderTarget from context to manager
zhuxudong Jul 2, 2024
409ad66
refactor: neutral shader refactor
zhuxudong Jul 2, 2024
d459ec9
refactor: add full workflow ACES tonemapping
zhuxudong Jul 3, 2024
e248d60
refactor: rename
zhuxudong Jul 3, 2024
db81a33
fix: color space error
zhuxudong Jul 3, 2024
bb5f096
refactor: saturate final color
zhuxudong Jul 3, 2024
7979b9b
ci: add e2e test
zhuxudong Jul 3, 2024
d377549
ci: commit AI check
zhuxudong Jul 3, 2024
c9a218c
refactor: use better hdr format (#12)
GuoLei1990 Jul 8, 2024
55bbd85
perf: use R11G11B10_Ufloat format for HDR
zhuxudong Jul 8, 2024
02d2199
refactor: move shader strings to shaderlib
zhuxudong Jul 8, 2024
95a8945
refactor: rename
zhuxudong Jul 8, 2024
1ad73ca
chore: rename
zhuxudong Jul 8, 2024
1d748e4
test: change api
zhuxudong Jul 8, 2024
528329e
perf: use mediump precision
zhuxudong Jul 8, 2024
26288f1
perf: blit to screen
zhuxudong Jul 9, 2024
4356e66
ci: add comment
zhuxudong Jul 9, 2024
3e978f8
perf: use const pre compute
zhuxudong Jul 9, 2024
edc047b
perf: use aces simple workflow
zhuxudong Jul 9, 2024
75c7013
perf: check active post pocess effect when enablePostProcess
zhuxudong Jul 9, 2024
c3c499b
perf: release internal RT when disable bloom
zhuxudong Jul 9, 2024
c86a9d4
perf: no need generateMipmaps before blit
zhuxudong Jul 10, 2024
5458d9c
perf: less blit
zhuxudong Jul 11, 2024
3120f58
refactor: delete engine in constructor
zhuxudong Jul 11, 2024
24d5a31
refactor: format code and e2e
zhuxudong Jul 11, 2024
17cf57e
fix: clamp specular AA
zhuxudong Jul 11, 2024
5bf3965
refactor: comment
zhuxudong Jul 11, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 67 additions & 0 deletions e2e/case/.initPostProcessEnv.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import {
AmbientLight,
AssetType,
BackgroundMode,
Camera,
GLTFResource,
PrimitiveMesh,
SkyBoxMaterial,
Texture2D,
Vector3,
WebGLEngine
} from "@galacean/engine";
import { initScreenshot, updateForE2E } from "./.mockForE2E";

export async function initPostProcessEnv(
callback: (camera: Camera, resArray: [GLTFResource, AmbientLight, Texture2D]) => void
) {
WebGLEngine.create({ canvas: "canvas" }).then((engine) => {
engine.canvas.resizeByClientSize();

const scene = engine.sceneManager.activeScene;
const rootEntity = scene.createRootEntity();

//Create camera
const cameraNode = rootEntity.createChild("camera_node");
cameraNode.transform.position.set(4, 0, 6);
cameraNode.transform.lookAt(new Vector3(1, 0, 0));
const camera = cameraNode.addComponent(Camera);

Promise.all([
engine.resourceManager
.load<GLTFResource>("https://gw.alipayobjects.com/os/bmw-prod/a1da72a4-023e-4bb1-9629-0f4b0f6b6fc4.glb")
.then((glTF) => {
const defaultSceneRoot = glTF.instantiateSceneRoot();
rootEntity.addChild(defaultSceneRoot);
return glTF;
}),
engine.resourceManager
.load<AmbientLight>({
type: AssetType.Env,
url: "https://gw.alipayobjects.com/os/bmw-prod/89c54544-1184-45a1-b0f5-c0b17e5c3e68.bin"
})
.then((ambientLight) => {
scene.ambientLight = ambientLight;
const sky = scene.background.sky;
const skyMaterial = new SkyBoxMaterial(engine);
scene.background.mode = BackgroundMode.Sky;

sky.material = skyMaterial;
sky.mesh = PrimitiveMesh.createCuboid(engine, 1, 1, 1);
skyMaterial.texture = ambientLight.specularTexture;
skyMaterial.textureDecodeRGBM = true;
return ambientLight;
}),
engine.resourceManager.load<Texture2D>({
type: AssetType.Texture2D,
url: "https://mdn.alipayobjects.com/huamei_dmxymu/afts/img/A*tMeTQ4Mx60oAAAAAAAAAAAAADuuHAQ/original"
})
]).then((resArray) => {
callback(camera, resArray);

updateForE2E(engine);

initScreenshot(engine, camera);
});
});
}
25 changes: 25 additions & 0 deletions e2e/case/postProcess-HDR-bloom-ACES.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/**
* @title Bloom + HDR + ACES Tonemapping
* @category PostProcess
*/
import { Camera, TonemappingMode } from "@galacean/engine";
import { initPostProcessEnv } from "./.initPostProcessEnv";

initPostProcessEnv((camera: Camera, resArray) => {
const [_, __, dirtTexture] = resArray;
const scene = camera.scene;

camera.enablePostProcess = true;
camera.enableHDR = true;
// @ts-ignore
const bloomEffect = scene._postProcessManager._bloomEffect;
// @ts-ignore
const tonemappingEffect = scene._postProcessManager._tonemappingEffect;

bloomEffect.enabled = true;
tonemappingEffect.enabled = true;

bloomEffect.threshold = 0.5;
bloomEffect.dirtTexture = dirtTexture;
tonemappingEffect.mode = TonemappingMode.ACES;
});
25 changes: 25 additions & 0 deletions e2e/case/postProcess-HDR-bloom-neutral.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/**
* @title Bloom + HDR + Neutral Tonemapping
* @category PostProcess
*/
import { Camera, TonemappingMode } from "@galacean/engine";
import { initPostProcessEnv } from "./.initPostProcessEnv";

initPostProcessEnv((camera: Camera, resArray) => {
const [_, __, dirtTexture] = resArray;
const scene = camera.scene;

camera.enablePostProcess = true;
camera.enableHDR = true;
// @ts-ignore
const bloomEffect = scene._postProcessManager._bloomEffect;
// @ts-ignore
const tonemappingEffect = scene._postProcessManager._tonemappingEffect;
Comment on lines +14 to +17
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Avoid using private properties directly.

Using private properties like _postProcessManager directly is discouraged. Consider adding public methods to access these properties.

// @ts-ignore
const bloomEffect = scene._postProcessManager._bloomEffect;
// @ts-ignore
const tonemappingEffect = scene._postProcessManager._tonemappingEffect;

// Consider refactoring to use public methods if available

Committable suggestion was skipped due to low confidence.


bloomEffect.enabled = true;
tonemappingEffect.enabled = true;

bloomEffect.threshold = 0.5;
bloomEffect.dirtTexture = dirtTexture;
tonemappingEffect.mode = TonemappingMode.Neutral;
});
25 changes: 25 additions & 0 deletions e2e/case/postProcess-LDR-bloom-neutral.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/**
* @title Bloom + LDR + Neutral Tonemapping
* @category PostProcess
*/
import { Camera, TonemappingMode } from "@galacean/engine";
import { initPostProcessEnv } from "./.initPostProcessEnv";

initPostProcessEnv((camera: Camera, resArray) => {
const [_, __, dirtTexture] = resArray;
const scene = camera.scene;

camera.enablePostProcess = true;
camera.enableHDR = false;
// @ts-ignore
const bloomEffect = scene._postProcessManager._bloomEffect;
// @ts-ignore
const tonemappingEffect = scene._postProcessManager._tonemappingEffect;
Comment on lines +14 to +17
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Avoid using private properties directly.

Using private properties like _postProcessManager directly is discouraged. Consider adding public methods to access these properties.

// @ts-ignore
const bloomEffect = scene._postProcessManager._bloomEffect;
// @ts-ignore
const tonemappingEffect = scene._postProcessManager._tonemappingEffect;

// Consider refactoring to use public methods if available

Committable suggestion was skipped due to low confidence.


bloomEffect.enabled = true;
tonemappingEffect.enabled = true;

bloomEffect.threshold = 0.5;
bloomEffect.dirtTexture = dirtTexture;
tonemappingEffect.mode = TonemappingMode.Neutral;
});
17 changes: 17 additions & 0 deletions e2e/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -180,5 +180,22 @@ export const E2E_CONFIG = {
caseFileName: "particleRenderer-dream",
threshold: 0.3
}
},
PostProcess: {
HDRBloomACES: {
category: "PostProcess",
caseFileName: "postProcess-HDR-bloom-ACES",
threshold: 0.2
},
HDRBloomNeutral: {
category: "PostProcess",
caseFileName: "postProcess-HDR-bloom-neutral",
threshold: 0.2
},
LDRBloomNeutral: {
category: "PostProcess",
caseFileName: "postProcess-LDR-bloom-neutral",
threshold: 0.2
}
}
};
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
15 changes: 8 additions & 7 deletions packages/core/src/BasicResources.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ import { TextureFormat } from "./texture/enums/TextureFormat";
* @internal
*/
export class BasicResources {
/**
* Use triangle to blit texture, ref: https://michaldrobot.com/2014/04/01/gcn-execution-patterns-in-full-screen-passes/ .
*/
readonly blitMesh: ModelMesh;
readonly flipYBlitMesh: ModelMesh;
readonly blitMaterial: Material;
Expand All @@ -30,16 +33,14 @@ export class BasicResources {
// prettier-ignore
const vertices = new Float32Array([
-1, -1, 0, 1, // left-bottom
1, -1, 1, 1, // right-bottom
-1, 1, 0, 0, // left-top
1, 1, 1, 0]); // right-top
3, -1, 2, 1, // right-bottom
-1, 3, 0, -1 ]); // left-top

// prettier-ignore
const flipYVertices = new Float32Array([
1, -1, 1, 0, // right-bottom
3, -1, 2, 0, // right-bottom
-1, -1, 0, 0, // left-bottom
1, 1, 1, 1, // right-top
-1, 1, 0, 1]); // left-top
-1, 3, 0, 2]); // left-top

const blitMaterial = new Material(engine, Shader.find("blit"));
blitMaterial._addReferCount(1);
Expand Down Expand Up @@ -80,7 +81,7 @@ export class BasicResources {
mesh._addReferCount(1);
mesh.setVertexElements([new VertexElement("POSITION_UV", 0, VertexElementFormat.Vector4, 0)]);
mesh.setVertexBufferBinding(new Buffer(engine, BufferBindFlag.VertexBuffer, vertices, BufferUsage.Static), 16);
mesh.addSubMesh(0, 4, MeshTopology.TriangleStrip);
mesh.addSubMesh(0, 3, MeshTopology.Triangles);
GuoLei1990 marked this conversation as resolved.
Show resolved Hide resolved
return mesh;
}

Expand Down
63 changes: 48 additions & 15 deletions packages/core/src/Camera.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { BasicRenderPipeline } from "./RenderPipeline/BasicRenderPipeline";
import { PipelineUtils } from "./RenderPipeline/PipelineUtils";
import { Transform } from "./Transform";
import { VirtualCamera } from "./VirtualCamera";
import { Logger } from "./base";
import { GLCapabilityType, Logger } from "./base";
import { deepClone, ignoreClone } from "./clone/CloneManager";
import { CameraClearFlags } from "./enums/CameraClearFlags";
import { CameraType } from "./enums/CameraType";
Expand All @@ -21,6 +21,7 @@ import { ShaderMacroCollection } from "./shader/ShaderMacroCollection";
import { ShaderProperty } from "./shader/ShaderProperty";
import { ShaderTagKey } from "./shader/ShaderTagKey";
import { ShaderDataGroup } from "./shader/enums/ShaderDataGroup";
import { TextureFormat } from "./texture";
import { RenderTarget } from "./texture/RenderTarget";
import { TextureCubeFace } from "./texture/enums/TextureCubeFace";

Expand Down Expand Up @@ -118,6 +119,8 @@ export class Camera extends Component {
private _renderTarget: RenderTarget = null;
private _depthBufferParams: Vector4 = new Vector4();
private _opaqueTextureEnabled: boolean = false;
private _enableHDR = false;
private _enablePostProcess = false;

@ignoreClone
private _frustumChangeFlag: BoolUpdateFlag;
Expand All @@ -141,7 +144,6 @@ export class Camera extends Component {
* If enabled, the opaque texture can be accessed in the shader using `camera_OpaqueTexture`.
*
* @defaultValue `false`
*
* @remarks If enabled, the `independentCanvasEnabled` property will be forced to be true.
*/
get opaqueTextureEnabled(): boolean {
Expand All @@ -161,11 +163,11 @@ export class Camera extends Component {
* @remarks If true, the msaa in viewport can turn or off independently by `msaaSamples` property.
*/
get independentCanvasEnabled(): boolean {
if (this._renderTarget) {
return false;
if (this.enableHDR || (this.enablePostProcess && this.scene._postProcessManager.hasActiveEffect)) {
return true;
}

return this._forceUseInternalCanvas();
return this.opaqueTextureEnabled && !this._renderTarget;
}

/**
Expand Down Expand Up @@ -356,15 +358,40 @@ export class Camera extends Component {

/**
* Whether to enable HDR.
* @todo When render pipeline modification
* @defaultValue `false`
* @remarks If enabled, the `independentCanvasEnabled` property will be forced to be true.
*/
get enableHDR(): boolean {
console.log("not implementation");
return false;
return this._enableHDR;
}

set enableHDR(value: boolean) {
console.log("not implementation");
if (this.enableHDR !== value) {
const rhi = this.engine._hardwareRenderer;
const supportHDR = rhi.isWebGL2 || rhi.canIUse(GLCapabilityType.textureHalfFloat);
if (value && !supportHDR) {
Logger.warn("Can't enable HDR in this device.");
return;
}
this._enableHDR = value;
this._checkMainCanvasAntialiasWaste();
}
}
GuoLei1990 marked this conversation as resolved.
Show resolved Hide resolved

/**
* Whether to enable post process.
* @defaultValue `false`
* @remarks If enabled, the `independentCanvasEnabled` property will be forced to be true.
*/
get enablePostProcess(): boolean {
return this._enablePostProcess;
}

set enablePostProcess(value: boolean) {
if (this._enablePostProcess !== value) {
this._enablePostProcess = value;
this._checkMainCanvasAntialiasWaste();
GuoLei1990 marked this conversation as resolved.
Show resolved Hide resolved
}
}

/**
Expand All @@ -380,7 +407,6 @@ export class Camera extends Component {
value && this._addResourceReferCount(value, 1);
this._renderTarget = value;
this._onPixelViewportChanged();
this._checkMainCanvasAntialiasWaste();
}
}

Expand Down Expand Up @@ -662,6 +688,17 @@ export class Camera extends Component {
this.scene._componentsManager.removeCamera(this);
}

/**
* @internal
*/
_getInternalColorTextureFormat(): TextureFormat {
return this._enableHDR
? this.engine._hardwareRenderer.isWebGL2
? TextureFormat.R11G11B10_UFloat
: TextureFormat.R16G16B16A16
: TextureFormat.R8G8B8A8;
}

/**
* @internal
* @inheritdoc
Expand Down Expand Up @@ -768,10 +805,6 @@ export class Camera extends Component {
return this._inverseProjectionMatrix;
}

private _forceUseInternalCanvas(): boolean {
return this.opaqueTextureEnabled;
}

@ignoreClone
private _onPixelViewportChanged(): void {
this._updatePixelViewport();
Expand All @@ -781,7 +814,7 @@ export class Camera extends Component {

private _checkMainCanvasAntialiasWaste(): void {
if (this.independentCanvasEnabled && Vector4.equals(this._viewport, PipelineUtils.defaultViewport)) {
console.warn(
Logger.warn(
"Camera use independent canvas and viewport cover the whole screen, it is recommended to disable antialias, depth and stencil to save memory when create engine."
);
}
Expand Down
Loading
Loading