From 121cec5947e64ddcde5a1b9f44280dd83c084491 Mon Sep 17 00:00:00 2001 From: gz65555 Date: Tue, 10 Aug 2021 11:27:37 +0800 Subject: [PATCH 01/10] feat: add scene background texture --- packages/core/src/Background.ts | 80 +++++++++++++++++++ packages/core/src/Engine.ts | 11 +++ .../src/RenderPipeline/BasicRenderPipeline.ts | 27 +++++++ packages/core/src/Scene.ts | 2 +- packages/core/src/enums/BackgroundMode.ts | 4 +- .../src/enums/BackgroundTextureFillMode.ts | 14 ++++ packages/core/src/shader/ShaderPool.ts | 3 + .../extra/background-texture.fs.glsl | 7 ++ .../extra/background-texture.vs.glsl | 9 +++ 9 files changed, 155 insertions(+), 2 deletions(-) create mode 100644 packages/core/src/enums/BackgroundTextureFillMode.ts create mode 100644 packages/core/src/shaderlib/extra/background-texture.fs.glsl create mode 100644 packages/core/src/shaderlib/extra/background-texture.vs.glsl diff --git a/packages/core/src/Background.ts b/packages/core/src/Background.ts index 943eab7acf..d57020f1bf 100644 --- a/packages/core/src/Background.ts +++ b/packages/core/src/Background.ts @@ -1,6 +1,9 @@ import { Color } from "@oasis-engine/math"; +import { Engine } from "."; import { BackgroundMode } from "./enums/BackgroundMode"; +import { BackgroundTextureFillMode } from "./enums/BackgroundTextureFillMode"; import { Sky } from "./sky/Sky"; +import { Texture2D } from "./texture"; /** * Background of scene. @@ -25,4 +28,81 @@ export class Background { * @remarks When `mode` is `BackgroundMode.Sky`, the property will take effects. */ readonly sky: Sky = new Sky(); + + /** @internal */ + _texture: Texture2D = null; + + /** @internal */ + _textureFillMode: BackgroundTextureFillMode = BackgroundTextureFillMode.FitHeight; + + /** + * Background texture. + * @remarks When `mode` is `BackgroundMode.Texture`, the property will take effects. + */ + public get texture(): Texture2D { + return this._texture; + } + + public set texture(v: Texture2D) { + if (this._texture === v) { + return; + } + this._engine._backgroundTextureMaterial.shaderData.setTexture("u_baseTexture", v); + } + + /** + * Background texture fill mode. + * @remarks When `mode` is `BackgroundMode.Texture`, the property will take effects. + * @defaultValue `BackgroundTextureFillMode.FitHeight` + */ + public get textureFillMode(): BackgroundTextureFillMode { + return this._textureFillMode; + } + + public set textureFillMode(textureFillMode: BackgroundTextureFillMode) { + if (textureFillMode === this._textureFillMode) { + return; + } + + this._textureFillMode = textureFillMode; + this._resizeBackground(); + } + + /** + * Constructor of Background. + * @param _engine Engine Which the background belongs to. + */ + constructor(private _engine: Engine) {} + + /** @internal */ + _resizeBackground(): void { + const { canvas } = this._engine; + const { width, height } = canvas; + const ratio = height / width; + const { _backgroundTextureMesh } = this._engine; + const postions = _backgroundTextureMesh.getPositions(); + + switch (this.textureFillMode) { + case BackgroundTextureFillMode.Scale: + postions[0].setValue(-1, -1, 0); + postions[1].setValue(1, -1, 0); + postions[2].setValue(-1, 1, 0); + postions[3].setValue(1, 1, 0); + break; + case BackgroundTextureFillMode.FitWidth: + postions[0].setValue(-1, -1 * ratio, 0); + postions[1].setValue(1, -1 * ratio, 0); + postions[2].setValue(-1, 1 * ratio, 0); + postions[3].setValue(1, 1 * ratio, 0); + break; + case BackgroundTextureFillMode.FitHeight: + postions[0].setValue(-1 / ratio, -1, 0); + postions[1].setValue(1 / ratio, -1, 0); + postions[2].setValue(-1 / ratio, 1, 0); + postions[3].setValue(1 / ratio, 1, 0); + break; + } + _backgroundTextureMesh.setPositions(postions); + _backgroundTextureMesh.uploadData(false); + } } diff --git a/packages/core/src/Engine.ts b/packages/core/src/Engine.ts index 33d86253e1..5c431a8a5e 100644 --- a/packages/core/src/Engine.ts +++ b/packages/core/src/Engine.ts @@ -26,6 +26,7 @@ import { ShaderProgramPool } from "./shader/ShaderProgramPool"; import { RenderState } from "./shader/state/RenderState"; import { Texture2D, TextureCubeFace, TextureCubeMap, TextureFormat } from "./texture"; import { PhysicsManager } from "./PhysicsManager"; +import { ModelMesh, PrimitiveMesh } from "./mesh"; /** TODO: delete */ const engineFeatureManager = new FeatureManager(); @@ -53,6 +54,10 @@ export class Engine extends EventDispatcher { /* @internal */ _whiteTextureCube: TextureCubeMap; /* @internal */ + _backgroundTextureMaterial: Material; + /* @internal */ + _backgroundTextureMesh: ModelMesh; + /* @internal */ _renderCount: number = 0; /* @internal */ _shaderProgramPools: ShaderProgramPool[] = []; @@ -182,6 +187,12 @@ export class Engine extends EventDispatcher { this._whiteTexture2D = whiteTexture2D; this._whiteTextureCube = whiteTextureCube; + + this._backgroundTextureMaterial = new Material(this, Shader.find("background-texture")); + this._backgroundTextureMaterial.isGCIgnored = true; + + this._backgroundTextureMesh = PrimitiveMesh.createPlane(this, 2, 2, 1, 1, false); + this._backgroundTextureMesh.isGCIgnored = true; } /** diff --git a/packages/core/src/RenderPipeline/BasicRenderPipeline.ts b/packages/core/src/RenderPipeline/BasicRenderPipeline.ts index e8ca5278af..acb0e0f556 100644 --- a/packages/core/src/RenderPipeline/BasicRenderPipeline.ts +++ b/packages/core/src/RenderPipeline/BasicRenderPipeline.ts @@ -1,10 +1,12 @@ import { Matrix } from "@oasis-engine/math"; +import { Background } from ".."; import { SpriteMask } from "../2d/sprite/SpriteMask"; import { Logger } from "../base/Logger"; import { Camera } from "../Camera"; import { DisorderedArray } from "../DisorderedArray"; import { Engine } from "../Engine"; import { BackgroundMode } from "../enums/BackgroundMode"; +import { BackgroundTextureFillMode } from "../enums/BackgroundTextureFillMode"; import { CameraClearFlags } from "../enums/CameraClearFlags"; import { Layer } from "../Layer"; import { RenderQueueType } from "../material/enums/RenderQueueType"; @@ -36,6 +38,8 @@ export class BasicRenderPipeline { private _camera: Camera; private _defaultPass: RenderPass; private _renderPassArray: Array; + private _lastCanvasWidth: number = 0; + private _lastCanvasHeight: number = 0; /** * Create a basic render pipeline. @@ -178,6 +182,8 @@ export class BasicRenderPipeline { this._alphaTestQueue.render(camera, pass.replaceMaterial, pass.mask); if (background.mode === BackgroundMode.Sky) { this._drawSky(engine, camera, background.sky); + } else if (background.mode === BackgroundMode.Texture) { + this._drawBackgroundTexture(engine, background); } this._transparentQueue.render(camera, pass.replaceMaterial, pass.mask); } @@ -205,6 +211,27 @@ export class BasicRenderPipeline { } } + private _drawBackgroundTexture(engine: Engine, background: Background) { + const rhi = engine._hardwareRenderer; + const { shaderData, shader, renderState } = engine._backgroundTextureMaterial; + const { _backgroundTextureMesh, canvas } = engine; + + if ( + (this._lastCanvasWidth !== canvas.width || this._lastCanvasHeight !== canvas.width) && + background._textureFillMode !== BackgroundTextureFillMode.Scale + ) { + background._resizeBackground(); + } + + const program = shader._getShaderProgram(engine, Shader._compileMacros); + program.bind(); + program.uploadAll(program.materialUniformBlock, shaderData); + program.uploadUngroupTextures(); + + renderState._apply(engine); + rhi.drawPrimitive(_backgroundTextureMesh, _backgroundTextureMesh.subMesh, program); + } + private _drawSky(engine: Engine, camera: Camera, sky: Sky): void { const { material, mesh, _matrix } = sky; if (!material) { diff --git a/packages/core/src/Scene.ts b/packages/core/src/Scene.ts index cc5944ea4a..e7deb2a684 100644 --- a/packages/core/src/Scene.ts +++ b/packages/core/src/Scene.ts @@ -21,7 +21,7 @@ export class Scene extends EngineObject { /** Scene name. */ name: string; /** The background of the scene. */ - readonly background: Background = new Background(); + readonly background: Background = new Background(this._engine); /** Ambient light. */ readonly ambientLight: AmbientLight; /** Scene-related shader data. */ diff --git a/packages/core/src/enums/BackgroundMode.ts b/packages/core/src/enums/BackgroundMode.ts index caaa9a4d9e..7b46e96b3c 100644 --- a/packages/core/src/enums/BackgroundMode.ts +++ b/packages/core/src/enums/BackgroundMode.ts @@ -5,5 +5,7 @@ export enum BackgroundMode { /* Solid color. */ SolidColor, /* Sky. */ - Sky + Sky, + /** Texture */ + Texture } diff --git a/packages/core/src/enums/BackgroundTextureFillMode.ts b/packages/core/src/enums/BackgroundTextureFillMode.ts new file mode 100644 index 0000000000..95c270adf3 --- /dev/null +++ b/packages/core/src/enums/BackgroundTextureFillMode.ts @@ -0,0 +1,14 @@ +export enum BackgroundTextureFillMode { + /** + * Adapt to width, scale based on texture width. + */ + FitWidth, + /** + * Adapt to height, scale based on texture height. + */ + FitHeight, + /** + * Scale mode, Scale the texture completely according to the canvas size. + */ + Scale +} diff --git a/packages/core/src/shader/ShaderPool.ts b/packages/core/src/shader/ShaderPool.ts index 951390f6f0..5393faaff4 100644 --- a/packages/core/src/shader/ShaderPool.ts +++ b/packages/core/src/shader/ShaderPool.ts @@ -15,6 +15,8 @@ import spriteFs from "../shaderlib/extra/sprite.fs.glsl"; import spriteVs from "../shaderlib/extra/sprite.vs.glsl"; import unlitFs from "../shaderlib/extra/unlit.fs.glsl"; import unlitVs from "../shaderlib/extra/unlit.vs.glsl"; +import backgroundTextureVs from "../shaderlib/extra/background-texture.vs.glsl"; +import backgroundTextureFs from "../shaderlib/extra/background-texture.fs.glsl"; import { Shader } from "./Shader"; /** @@ -32,5 +34,6 @@ export class ShaderPool { Shader.create("particle-shader", particleVs, particleFs); Shader.create("SpriteMask", spriteMaskVs, spriteMaskFs); Shader.create("Sprite", spriteVs, spriteFs); + Shader.create("background-texture", backgroundTextureVs, backgroundTextureFs); } } diff --git a/packages/core/src/shaderlib/extra/background-texture.fs.glsl b/packages/core/src/shaderlib/extra/background-texture.fs.glsl new file mode 100644 index 0000000000..dc68651269 --- /dev/null +++ b/packages/core/src/shaderlib/extra/background-texture.fs.glsl @@ -0,0 +1,7 @@ +uniform sampler2D u_baseTexture; + +varying vec2 v_uv; + +void main() { + gl_FragColor = texture2D(u_baseTexture, v_uv); +} \ No newline at end of file diff --git a/packages/core/src/shaderlib/extra/background-texture.vs.glsl b/packages/core/src/shaderlib/extra/background-texture.vs.glsl new file mode 100644 index 0000000000..62a85783c4 --- /dev/null +++ b/packages/core/src/shaderlib/extra/background-texture.vs.glsl @@ -0,0 +1,9 @@ +attribute vec2 POSITION; +attribute vec2 TEXCOORD_0; + +varying vec2 v_uv; + +void main() { + gl_Position = vec4(POSITION, 0.0, 1.0); + v_uv = TEXCOORD_0; +} \ No newline at end of file From 40c5a864ef3d69f34b17eff45df49a8c471b58d8 Mon Sep 17 00:00:00 2001 From: gz65555 Date: Tue, 10 Aug 2021 11:42:49 +0800 Subject: [PATCH 02/10] style: fix import style --- packages/core/src/Background.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/core/src/Background.ts b/packages/core/src/Background.ts index d57020f1bf..b7938f6424 100644 --- a/packages/core/src/Background.ts +++ b/packages/core/src/Background.ts @@ -1,5 +1,5 @@ import { Color } from "@oasis-engine/math"; -import { Engine } from "."; +import { Engine } from "./Engine"; import { BackgroundMode } from "./enums/BackgroundMode"; import { BackgroundTextureFillMode } from "./enums/BackgroundTextureFillMode"; import { Sky } from "./sky/Sky"; From ec409d8585b75f48ba882ab2a6c1ed19203e633a Mon Sep 17 00:00:00 2001 From: gz65555 Date: Thu, 12 Aug 2021 11:23:41 +0800 Subject: [PATCH 03/10] refactor: rename scale to scaleToFit --- packages/core/src/Background.ts | 75 +++++++++++-------- .../src/RenderPipeline/BasicRenderPipeline.ts | 10 ++- ...reFillMode.ts => BackgroundTextureMode.ts} | 4 +- 3 files changed, 51 insertions(+), 38 deletions(-) rename packages/core/src/enums/{BackgroundTextureFillMode.ts => BackgroundTextureMode.ts} (82%) diff --git a/packages/core/src/Background.ts b/packages/core/src/Background.ts index b7938f6424..9585f4db14 100644 --- a/packages/core/src/Background.ts +++ b/packages/core/src/Background.ts @@ -1,7 +1,7 @@ import { Color } from "@oasis-engine/math"; import { Engine } from "./Engine"; import { BackgroundMode } from "./enums/BackgroundMode"; -import { BackgroundTextureFillMode } from "./enums/BackgroundTextureFillMode"; +import { BackgroundTextureMode } from "./enums/BackgroundTextureMode"; import { Sky } from "./sky/Sky"; import { Texture2D } from "./texture"; @@ -33,7 +33,7 @@ export class Background { _texture: Texture2D = null; /** @internal */ - _textureFillMode: BackgroundTextureFillMode = BackgroundTextureFillMode.FitHeight; + _textureFillMode: BackgroundTextureMode = BackgroundTextureMode.FitHeight; /** * Background texture. @@ -43,11 +43,11 @@ export class Background { return this._texture; } - public set texture(v: Texture2D) { - if (this._texture === v) { - return; + public set texture(value: Texture2D) { + if (this._texture !== value) { + this._texture = value; + this._engine._backgroundTextureMaterial.shaderData.setTexture("u_baseTexture", value); } - this._engine._backgroundTextureMaterial.shaderData.setTexture("u_baseTexture", v); } /** @@ -55,17 +55,17 @@ export class Background { * @remarks When `mode` is `BackgroundMode.Texture`, the property will take effects. * @defaultValue `BackgroundTextureFillMode.FitHeight` */ - public get textureFillMode(): BackgroundTextureFillMode { + public get textureFillMode(): BackgroundTextureMode { return this._textureFillMode; } - public set textureFillMode(textureFillMode: BackgroundTextureFillMode) { - if (textureFillMode === this._textureFillMode) { + public set textureFillMode(value: BackgroundTextureMode) { + if (value === this._textureFillMode) { return; } - this._textureFillMode = textureFillMode; - this._resizeBackground(); + this._textureFillMode = value; + this._resizeBackgroundTexture(); } /** @@ -74,35 +74,46 @@ export class Background { */ constructor(private _engine: Engine) {} - /** @internal */ - _resizeBackground(): void { + /** + * @internal + */ + _resizeBackgroundTexture(): void { + if (!this._texture) { + return; + } const { canvas } = this._engine; const { width, height } = canvas; - const ratio = height / width; + const { width: textureWidth } = this._texture; const { _backgroundTextureMesh } = this._engine; - const postions = _backgroundTextureMesh.getPositions(); + const positions = _backgroundTextureMesh.getPositions(); - switch (this.textureFillMode) { - case BackgroundTextureFillMode.Scale: - postions[0].setValue(-1, -1, 0); - postions[1].setValue(1, -1, 0); - postions[2].setValue(-1, 1, 0); - postions[3].setValue(1, 1, 0); + switch (this._textureFillMode) { + case BackgroundTextureMode.ScaleToFill: + positions[0].setValue(-1, -1, -1); + positions[1].setValue(1, -1, -1); + positions[2].setValue(-1, 1, -1); + positions[3].setValue(1, 1, -1); break; - case BackgroundTextureFillMode.FitWidth: - postions[0].setValue(-1, -1 * ratio, 0); - postions[1].setValue(1, -1 * ratio, 0); - postions[2].setValue(-1, 1 * ratio, 0); - postions[3].setValue(1, 1 * ratio, 0); + case BackgroundTextureMode.FitWidth: + { + const scaleValue = 1 / ((textureWidth * (height / width)) / height); + positions[0].setValue(-1, -scaleValue, -1); + positions[1].setValue(1, -scaleValue, -1); + positions[2].setValue(-1, scaleValue, -1); + positions[3].setValue(1, scaleValue, 0); + } break; - case BackgroundTextureFillMode.FitHeight: - postions[0].setValue(-1 / ratio, -1, 0); - postions[1].setValue(1 / ratio, -1, 0); - postions[2].setValue(-1 / ratio, 1, 0); - postions[3].setValue(1 / ratio, 1, 0); + case BackgroundTextureMode.FitHeight: + { + const scaleValue = (textureWidth * (height / width)) / height; + positions[0].setValue(-scaleValue, -1, -1); + positions[1].setValue(scaleValue, -1, -1); + positions[2].setValue(-scaleValue, 1, -1); + positions[3].setValue(scaleValue, 1, -1); + } break; } - _backgroundTextureMesh.setPositions(postions); + _backgroundTextureMesh.setPositions(positions); _backgroundTextureMesh.uploadData(false); } } diff --git a/packages/core/src/RenderPipeline/BasicRenderPipeline.ts b/packages/core/src/RenderPipeline/BasicRenderPipeline.ts index acb0e0f556..6aa4dcc076 100644 --- a/packages/core/src/RenderPipeline/BasicRenderPipeline.ts +++ b/packages/core/src/RenderPipeline/BasicRenderPipeline.ts @@ -6,7 +6,7 @@ import { Camera } from "../Camera"; import { DisorderedArray } from "../DisorderedArray"; import { Engine } from "../Engine"; import { BackgroundMode } from "../enums/BackgroundMode"; -import { BackgroundTextureFillMode } from "../enums/BackgroundTextureFillMode"; +import { BackgroundTextureMode } from "../enums/BackgroundTextureMode"; import { CameraClearFlags } from "../enums/CameraClearFlags"; import { Layer } from "../Layer"; import { RenderQueueType } from "../material/enums/RenderQueueType"; @@ -217,10 +217,12 @@ export class BasicRenderPipeline { const { _backgroundTextureMesh, canvas } = engine; if ( - (this._lastCanvasWidth !== canvas.width || this._lastCanvasHeight !== canvas.width) && - background._textureFillMode !== BackgroundTextureFillMode.Scale + (this._lastCanvasWidth !== canvas.width || this._lastCanvasHeight !== canvas.height) && + background._textureFillMode !== BackgroundTextureMode.ScaleToFill ) { - background._resizeBackground(); + this._lastCanvasWidth = canvas.width; + this._lastCanvasHeight = canvas.height; + background._resizeBackgroundTexture(); } const program = shader._getShaderProgram(engine, Shader._compileMacros); diff --git a/packages/core/src/enums/BackgroundTextureFillMode.ts b/packages/core/src/enums/BackgroundTextureMode.ts similarity index 82% rename from packages/core/src/enums/BackgroundTextureFillMode.ts rename to packages/core/src/enums/BackgroundTextureMode.ts index 95c270adf3..1ca7b48019 100644 --- a/packages/core/src/enums/BackgroundTextureFillMode.ts +++ b/packages/core/src/enums/BackgroundTextureMode.ts @@ -1,4 +1,4 @@ -export enum BackgroundTextureFillMode { +export enum BackgroundTextureMode { /** * Adapt to width, scale based on texture width. */ @@ -10,5 +10,5 @@ export enum BackgroundTextureFillMode { /** * Scale mode, Scale the texture completely according to the canvas size. */ - Scale + ScaleToFill } From f97a9bbdc8dcc76f657116120bfdd7ee8b93a74a Mon Sep 17 00:00:00 2001 From: gz65555 Date: Thu, 12 Aug 2021 11:42:26 +0800 Subject: [PATCH 04/10] refactor: use vec2 to vec3 --- packages/core/src/Background.ts | 10 ++++------ .../src/shaderlib/extra/background-texture.vs.glsl | 4 ++-- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/packages/core/src/Background.ts b/packages/core/src/Background.ts index 9585f4db14..32b7c0ed25 100644 --- a/packages/core/src/Background.ts +++ b/packages/core/src/Background.ts @@ -61,11 +61,9 @@ export class Background { public set textureFillMode(value: BackgroundTextureMode) { if (value === this._textureFillMode) { - return; + this._textureFillMode = value; + this._resizeBackgroundTexture(); } - - this._textureFillMode = value; - this._resizeBackgroundTexture(); } /** @@ -74,8 +72,8 @@ export class Background { */ constructor(private _engine: Engine) {} - /** - * @internal + /** + * @internal */ _resizeBackgroundTexture(): void { if (!this._texture) { diff --git a/packages/core/src/shaderlib/extra/background-texture.vs.glsl b/packages/core/src/shaderlib/extra/background-texture.vs.glsl index 62a85783c4..6f47a41c6d 100644 --- a/packages/core/src/shaderlib/extra/background-texture.vs.glsl +++ b/packages/core/src/shaderlib/extra/background-texture.vs.glsl @@ -1,9 +1,9 @@ -attribute vec2 POSITION; +attribute vec3 POSITION; attribute vec2 TEXCOORD_0; varying vec2 v_uv; void main() { - gl_Position = vec4(POSITION, 0.0, 1.0); + gl_Position = vec4(POSITION, 1.0); v_uv = TEXCOORD_0; } \ No newline at end of file From 28e32d4ca12988d158cdc598eec4fb33a2e75131 Mon Sep 17 00:00:00 2001 From: gz65555 Date: Fri, 13 Aug 2021 11:42:34 +0800 Subject: [PATCH 05/10] refactor: add internal decoration --- packages/core/src/Background.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/core/src/Background.ts b/packages/core/src/Background.ts index 32b7c0ed25..6eafa74eaa 100644 --- a/packages/core/src/Background.ts +++ b/packages/core/src/Background.ts @@ -51,6 +51,7 @@ export class Background { } /** + * @internal * Background texture fill mode. * @remarks When `mode` is `BackgroundMode.Texture`, the property will take effects. * @defaultValue `BackgroundTextureFillMode.FitHeight` @@ -98,7 +99,7 @@ export class Background { positions[0].setValue(-1, -scaleValue, -1); positions[1].setValue(1, -scaleValue, -1); positions[2].setValue(-1, scaleValue, -1); - positions[3].setValue(1, scaleValue, 0); + positions[3].setValue(1, scaleValue, -1); } break; case BackgroundTextureMode.FitHeight: From 667eee0d292ddeaf3b47a1be2950a9e948aff27a Mon Sep 17 00:00:00 2001 From: gz65555 Date: Fri, 13 Aug 2021 11:50:05 +0800 Subject: [PATCH 06/10] refactor: use Vector2 instead of value --- .../src/RenderPipeline/BasicRenderPipeline.ts | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/packages/core/src/RenderPipeline/BasicRenderPipeline.ts b/packages/core/src/RenderPipeline/BasicRenderPipeline.ts index 6aa4dcc076..acde77285b 100644 --- a/packages/core/src/RenderPipeline/BasicRenderPipeline.ts +++ b/packages/core/src/RenderPipeline/BasicRenderPipeline.ts @@ -1,4 +1,4 @@ -import { Matrix } from "@oasis-engine/math"; +import { Matrix, Vector2 } from "@oasis-engine/math"; import { Background } from ".."; import { SpriteMask } from "../2d/sprite/SpriteMask"; import { Logger } from "../base/Logger"; @@ -38,8 +38,7 @@ export class BasicRenderPipeline { private _camera: Camera; private _defaultPass: RenderPass; private _renderPassArray: Array; - private _lastCanvasWidth: number = 0; - private _lastCanvasHeight: number = 0; + private _lastCanvasSize = new Vector2(); /** * Create a basic render pipeline. @@ -213,24 +212,23 @@ export class BasicRenderPipeline { private _drawBackgroundTexture(engine: Engine, background: Background) { const rhi = engine._hardwareRenderer; - const { shaderData, shader, renderState } = engine._backgroundTextureMaterial; + const { _backgroundTextureMaterial } = engine; const { _backgroundTextureMesh, canvas } = engine; if ( - (this._lastCanvasWidth !== canvas.width || this._lastCanvasHeight !== canvas.height) && + (this._lastCanvasSize.x !== canvas.width || this._lastCanvasSize.y !== canvas.height) && background._textureFillMode !== BackgroundTextureMode.ScaleToFill ) { - this._lastCanvasWidth = canvas.width; - this._lastCanvasHeight = canvas.height; + this._lastCanvasSize.setValue(canvas.width, canvas.height); background._resizeBackgroundTexture(); } - const program = shader._getShaderProgram(engine, Shader._compileMacros); + const program = _backgroundTextureMaterial.shader._getShaderProgram(engine, Shader._compileMacros); program.bind(); - program.uploadAll(program.materialUniformBlock, shaderData); + program.uploadAll(program.materialUniformBlock, _backgroundTextureMaterial.shaderData); program.uploadUngroupTextures(); - renderState._apply(engine); + _backgroundTextureMaterial.renderState._apply(engine); rhi.drawPrimitive(_backgroundTextureMesh, _backgroundTextureMesh.subMesh, program); } From 6c0fc1a99f5e4a51dc4678a75f0bb9905350887f Mon Sep 17 00:00:00 2001 From: gz65555 Date: Fri, 13 Aug 2021 11:55:39 +0800 Subject: [PATCH 07/10] refactor: fix value equal bug --- packages/core/src/Background.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/core/src/Background.ts b/packages/core/src/Background.ts index 6eafa74eaa..627c3860e8 100644 --- a/packages/core/src/Background.ts +++ b/packages/core/src/Background.ts @@ -61,7 +61,7 @@ export class Background { } public set textureFillMode(value: BackgroundTextureMode) { - if (value === this._textureFillMode) { + if (value !== this._textureFillMode) { this._textureFillMode = value; this._resizeBackgroundTexture(); } From a24d4af3bc79c24520f419c17e4b2e2b5a0957d7 Mon Sep 17 00:00:00 2001 From: gz65555 Date: Fri, 13 Aug 2021 17:49:19 +0800 Subject: [PATCH 08/10] refactor: rename background fill mode --- packages/core/src/Background.ts | 23 +++++++++---------- .../src/RenderPipeline/BasicRenderPipeline.ts | 4 ++-- .../src/enums/BackgroundTextureFillMode.ts | 11 +++++++++ .../core/src/enums/BackgroundTextureMode.ts | 14 ----------- 4 files changed, 24 insertions(+), 28 deletions(-) create mode 100644 packages/core/src/enums/BackgroundTextureFillMode.ts delete mode 100644 packages/core/src/enums/BackgroundTextureMode.ts diff --git a/packages/core/src/Background.ts b/packages/core/src/Background.ts index 627c3860e8..cd207ac339 100644 --- a/packages/core/src/Background.ts +++ b/packages/core/src/Background.ts @@ -1,7 +1,7 @@ import { Color } from "@oasis-engine/math"; import { Engine } from "./Engine"; import { BackgroundMode } from "./enums/BackgroundMode"; -import { BackgroundTextureMode } from "./enums/BackgroundTextureMode"; +import { BackgroundTextureFillMode } from "./enums/BackgroundTextureFillMode"; import { Sky } from "./sky/Sky"; import { Texture2D } from "./texture"; @@ -33,17 +33,17 @@ export class Background { _texture: Texture2D = null; /** @internal */ - _textureFillMode: BackgroundTextureMode = BackgroundTextureMode.FitHeight; + _textureFillMode: BackgroundTextureFillMode = BackgroundTextureFillMode.AspectFitHeight; /** * Background texture. * @remarks When `mode` is `BackgroundMode.Texture`, the property will take effects. */ - public get texture(): Texture2D { + get texture(): Texture2D { return this._texture; } - public set texture(value: Texture2D) { + set texture(value: Texture2D) { if (this._texture !== value) { this._texture = value; this._engine._backgroundTextureMaterial.shaderData.setTexture("u_baseTexture", value); @@ -56,11 +56,11 @@ export class Background { * @remarks When `mode` is `BackgroundMode.Texture`, the property will take effects. * @defaultValue `BackgroundTextureFillMode.FitHeight` */ - public get textureFillMode(): BackgroundTextureMode { + get textureFillMode(): BackgroundTextureFillMode { return this._textureFillMode; } - public set textureFillMode(value: BackgroundTextureMode) { + set textureFillMode(value: BackgroundTextureFillMode) { if (value !== this._textureFillMode) { this._textureFillMode = value; this._resizeBackgroundTexture(); @@ -82,29 +82,28 @@ export class Background { } const { canvas } = this._engine; const { width, height } = canvas; - const { width: textureWidth } = this._texture; const { _backgroundTextureMesh } = this._engine; const positions = _backgroundTextureMesh.getPositions(); switch (this._textureFillMode) { - case BackgroundTextureMode.ScaleToFill: + case BackgroundTextureFillMode.Fill: positions[0].setValue(-1, -1, -1); positions[1].setValue(1, -1, -1); positions[2].setValue(-1, 1, -1); positions[3].setValue(1, 1, -1); break; - case BackgroundTextureMode.FitWidth: + case BackgroundTextureFillMode.AspectFitWidth: { - const scaleValue = 1 / ((textureWidth * (height / width)) / height); + const scaleValue = 1 / ((this._texture.width * (height / width)) / height); positions[0].setValue(-1, -scaleValue, -1); positions[1].setValue(1, -scaleValue, -1); positions[2].setValue(-1, scaleValue, -1); positions[3].setValue(1, scaleValue, -1); } break; - case BackgroundTextureMode.FitHeight: + case BackgroundTextureFillMode.AspectFitHeight: { - const scaleValue = (textureWidth * (height / width)) / height; + const scaleValue = (this._texture.width * (height / width)) / height; positions[0].setValue(-scaleValue, -1, -1); positions[1].setValue(scaleValue, -1, -1); positions[2].setValue(-scaleValue, 1, -1); diff --git a/packages/core/src/RenderPipeline/BasicRenderPipeline.ts b/packages/core/src/RenderPipeline/BasicRenderPipeline.ts index acde77285b..531d0760a9 100644 --- a/packages/core/src/RenderPipeline/BasicRenderPipeline.ts +++ b/packages/core/src/RenderPipeline/BasicRenderPipeline.ts @@ -6,7 +6,7 @@ import { Camera } from "../Camera"; import { DisorderedArray } from "../DisorderedArray"; import { Engine } from "../Engine"; import { BackgroundMode } from "../enums/BackgroundMode"; -import { BackgroundTextureMode } from "../enums/BackgroundTextureMode"; +import { BackgroundTextureFillMode } from "../enums/BackgroundTextureFillMode"; import { CameraClearFlags } from "../enums/CameraClearFlags"; import { Layer } from "../Layer"; import { RenderQueueType } from "../material/enums/RenderQueueType"; @@ -217,7 +217,7 @@ export class BasicRenderPipeline { if ( (this._lastCanvasSize.x !== canvas.width || this._lastCanvasSize.y !== canvas.height) && - background._textureFillMode !== BackgroundTextureMode.ScaleToFill + background._textureFillMode !== BackgroundTextureFillMode.Fill ) { this._lastCanvasSize.setValue(canvas.width, canvas.height); background._resizeBackgroundTexture(); diff --git a/packages/core/src/enums/BackgroundTextureFillMode.ts b/packages/core/src/enums/BackgroundTextureFillMode.ts new file mode 100644 index 0000000000..d899c0823e --- /dev/null +++ b/packages/core/src/enums/BackgroundTextureFillMode.ts @@ -0,0 +1,11 @@ +/** + * Filling mode of background texture. + */ +export enum BackgroundTextureFillMode { + /* Maintain the aspect ratio and scale the texture to fit the width of the canvas. */ + AspectFitWidth, + /* Maintain the aspect ratio and scale the texture to fit the height of the canvas. */ + AspectFitHeight, + /* Scale the texture fully fills the canvas. */ + Fill +} diff --git a/packages/core/src/enums/BackgroundTextureMode.ts b/packages/core/src/enums/BackgroundTextureMode.ts deleted file mode 100644 index 1ca7b48019..0000000000 --- a/packages/core/src/enums/BackgroundTextureMode.ts +++ /dev/null @@ -1,14 +0,0 @@ -export enum BackgroundTextureMode { - /** - * Adapt to width, scale based on texture width. - */ - FitWidth, - /** - * Adapt to height, scale based on texture height. - */ - FitHeight, - /** - * Scale mode, Scale the texture completely according to the canvas size. - */ - ScaleToFill -} From d940dacb268b61c6bc15a82a77d0d105013035e4 Mon Sep 17 00:00:00 2001 From: gz65555 Date: Wed, 18 Aug 2021 14:26:22 +0800 Subject: [PATCH 09/10] test: test for background --- packages/core/tests/Background.test.ts | 70 ++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) create mode 100644 packages/core/tests/Background.test.ts diff --git a/packages/core/tests/Background.test.ts b/packages/core/tests/Background.test.ts new file mode 100644 index 0000000000..5b20265e37 --- /dev/null +++ b/packages/core/tests/Background.test.ts @@ -0,0 +1,70 @@ +import { WebCanvas, WebGLRenderer } from "../../rhi-webgl"; +import { Engine, Texture2D } from "../src"; +import { BackgroundTextureFillMode } from "../src/enums/BackgroundTextureFillMode"; + +describe("Background Test", function () { + const hardwareRenderer = new WebGLRenderer(); + const canvas = new WebCanvas(document.createElement("canvas")); + canvas.width = 100; + canvas.height = 100; + const engine = new Engine(canvas, hardwareRenderer); + const scene = engine.sceneManager.activeScene; + it("set texture should be success", () => { + const texture = new Texture2D(engine, 50, 100); + scene.background._resizeBackgroundTexture(); + scene.background.texture = texture; + expect(scene.background.texture).toEqual(texture) + scene.background.texture = texture; + expect(scene.background.texture).toEqual(texture); + expect(scene.background.textureFillMode).toEqual(BackgroundTextureFillMode.AspectFitHeight); + scene.background.textureFillMode = BackgroundTextureFillMode.AspectFitHeight; + expect(scene.background.textureFillMode).toEqual(BackgroundTextureFillMode.AspectFitHeight); + }); + it("set texture fill should be success", () => { + scene.background.textureFillMode = BackgroundTextureFillMode.Fill; + const positions = engine._backgroundTextureMesh.getPositions(); + expect(positions[0].x).toBeCloseTo(-1); + expect(positions[0].y).toBeCloseTo(-1); + + expect(positions[1].x).toBeCloseTo(1); + expect(positions[1].y).toBeCloseTo(-1); + + expect(positions[2].x).toBeCloseTo(-1); + expect(positions[2].y).toBeCloseTo(1); + + expect(positions[3].x).toBeCloseTo(1); + expect(positions[3].y).toBeCloseTo(1); + }); + + it("set texture fill should be success", () => { + scene.background.textureFillMode = BackgroundTextureFillMode.AspectFitHeight; + const positions = engine._backgroundTextureMesh.getPositions(); + expect(positions[0].x).toBeCloseTo(-0.5); + expect(positions[0].y).toBeCloseTo(-1); + + expect(positions[1].x).toBeCloseTo(0.5); + expect(positions[1].y).toBeCloseTo(-1); + + expect(positions[2].x).toBeCloseTo(-0.5); + expect(positions[2].y).toBeCloseTo(1); + + expect(positions[3].x).toBeCloseTo(0.5); + expect(positions[3].y).toBeCloseTo(1); + }); + + it("set texture fill should be success", () => { + scene.background.textureFillMode = BackgroundTextureFillMode.AspectFitWidth; + const positions = engine._backgroundTextureMesh.getPositions(); + expect(positions[0].x).toBeCloseTo(-1); + expect(positions[0].y).toBeCloseTo(-2); + + expect(positions[1].x).toBeCloseTo(1); + expect(positions[1].y).toBeCloseTo(-2); + + expect(positions[2].x).toBeCloseTo(-1); + expect(positions[2].y).toBeCloseTo(2); + + expect(positions[3].x).toBeCloseTo(1); + expect(positions[3].y).toBeCloseTo(2); + }); +}); From 12835a09058d1bcc5eeb21000007dd9d7ceb6ce5 Mon Sep 17 00:00:00 2001 From: gz65555 Date: Fri, 20 Aug 2021 11:57:02 +0800 Subject: [PATCH 10/10] refactor: fix background texture bug --- packages/core/src/Background.ts | 24 ++++++++++++------------ packages/core/src/Engine.ts | 2 ++ 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/packages/core/src/Background.ts b/packages/core/src/Background.ts index 7e0f5ece5f..53c55097fa 100644 --- a/packages/core/src/Background.ts +++ b/packages/core/src/Background.ts @@ -86,24 +86,24 @@ export class Background { switch (this._textureFillMode) { case BackgroundTextureFillMode.Fill: - positions[0].setValue(-1, -1, -1); - positions[1].setValue(1, -1, -1); - positions[2].setValue(-1, 1, -1); - positions[3].setValue(1, 1, -1); + positions[0].setValue(-1, -1, 1); + positions[1].setValue(1, -1, 1); + positions[2].setValue(-1, 1, 1); + positions[3].setValue(1, 1, 1); break; case BackgroundTextureFillMode.AspectFitWidth: const fitWidthScale = 1 / ((this._texture.width * (height / width)) / height); - positions[0].setValue(-1, -fitWidthScale, -1); - positions[1].setValue(1, -fitWidthScale, -1); - positions[2].setValue(-1, fitWidthScale, -1); - positions[3].setValue(1, fitWidthScale, -1); + positions[0].setValue(-1, -fitWidthScale, 1); + positions[1].setValue(1, -fitWidthScale, 1); + positions[2].setValue(-1, fitWidthScale, 1); + positions[3].setValue(1, fitWidthScale, 1); break; case BackgroundTextureFillMode.AspectFitHeight: const fitHeightScale = (this._texture.width * (height / width)) / height; - positions[0].setValue(-fitHeightScale, -1, -1); - positions[1].setValue(fitHeightScale, -1, -1); - positions[2].setValue(-fitHeightScale, 1, -1); - positions[3].setValue(fitHeightScale, 1, -1); + positions[0].setValue(-fitHeightScale, -1, 1); + positions[1].setValue(fitHeightScale, -1, 1); + positions[2].setValue(-fitHeightScale, 1, 1); + positions[3].setValue(fitHeightScale, 1, 1); break; } _backgroundTextureMesh.setPositions(positions); diff --git a/packages/core/src/Engine.ts b/packages/core/src/Engine.ts index 5c431a8a5e..7b1eba4cfb 100644 --- a/packages/core/src/Engine.ts +++ b/packages/core/src/Engine.ts @@ -27,6 +27,7 @@ import { RenderState } from "./shader/state/RenderState"; import { Texture2D, TextureCubeFace, TextureCubeMap, TextureFormat } from "./texture"; import { PhysicsManager } from "./PhysicsManager"; import { ModelMesh, PrimitiveMesh } from "./mesh"; +import { CompareFunction } from "./shader"; /** TODO: delete */ const engineFeatureManager = new FeatureManager(); @@ -190,6 +191,7 @@ export class Engine extends EventDispatcher { this._backgroundTextureMaterial = new Material(this, Shader.find("background-texture")); this._backgroundTextureMaterial.isGCIgnored = true; + this._backgroundTextureMaterial.renderState.depthState.compareFunction = CompareFunction.LessEqual; this._backgroundTextureMesh = PrimitiveMesh.createPlane(this, 2, 2, 1, 1, false); this._backgroundTextureMesh.isGCIgnored = true;