From 24bb73f09e896c9d5214b860c119727e2d1b4b99 Mon Sep 17 00:00:00 2001 From: yu-ogi Date: Tue, 14 May 2024 14:15:45 +0900 Subject: [PATCH] feat: support `RendererCandidate` --- CHANGELOG.md | 5 ++++ package-lock.json | 8 +++--- package.json | 2 +- src/ResourceFactory.ts | 3 +- src/canvas/RenderingHelper.ts | 40 +++++++++++++++++++++++---- src/canvas/shims/SurfaceFactory.ts | 10 ++++--- src/canvas/webgl/WebGLSharedObject.ts | 28 +++++++++++++++++-- 7 files changed, 79 insertions(+), 17 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4753b6d..e3b255e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ # CHANGELOG +## unreleased changes +* @akashic/pdi-types@1.14.0 に更新 +* `RendererCandidate` をサポート + * `WebGLRenderer` で部分的に depth buffer をサポートするように + ## 2.9.1 * View の外をクリック時に `pointDown` イベントが発生しないよう修正 diff --git a/package-lock.json b/package-lock.json index ff66356..b0a141f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14,7 +14,7 @@ "devDependencies": { "@akashic/amflow": "^3.3.0", "@akashic/eslint-config": "^2.0.0", - "@akashic/pdi-types": "^1.13.0", + "@akashic/pdi-types": "^1.14.0", "@akashic/playlog": "^3.3.0", "@types/jest": "^29.2.0", "@types/node": "^18.0.0", @@ -78,9 +78,9 @@ } }, "node_modules/@akashic/pdi-types": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/@akashic/pdi-types/-/pdi-types-1.13.0.tgz", - "integrity": "sha512-yyRKDis3Zqq/YWoaCrW1TG0sA3WjRLZbyR82Slp5Gs2bSHHwZ2wVYBw2QF9u9w5iG7syBJ7KL5kS1zNd33xUQw==", + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/@akashic/pdi-types/-/pdi-types-1.14.0.tgz", + "integrity": "sha512-QwCQHII8nNdO6nOc/x1MAyN6PGpzsSrhBpq+WYXlav3MbDxZEX9JGJEIbrNdAfEZMK5CJ5LCpkVvQxTOefnZwg==", "dev": true, "dependencies": { "@akashic/amflow": "~3.3.0", diff --git a/package.json b/package.json index dcbffa5..cfbf744 100644 --- a/package.json +++ b/package.json @@ -43,7 +43,7 @@ "devDependencies": { "@akashic/amflow": "^3.3.0", "@akashic/eslint-config": "^2.0.0", - "@akashic/pdi-types": "^1.13.0", + "@akashic/pdi-types": "^1.14.0", "@akashic/playlog": "^3.3.0", "@types/jest": "^29.2.0", "@types/node": "^18.0.0", diff --git a/src/ResourceFactory.ts b/src/ResourceFactory.ts index a5e0eec..5d0f15b 100644 --- a/src/ResourceFactory.ts +++ b/src/ResourceFactory.ts @@ -1,4 +1,5 @@ import type * as pdi from "@akashic/pdi-types"; +import type { RendererCandidate } from "@akashic/pdi-types"; import type { AudioAsset } from "./asset/AudioAsset"; import { BinaryAsset } from "./asset/BinaryAsset"; import { GeneratedSVGImageAsset } from "./asset/GeneratedSVGImageAsset"; @@ -23,7 +24,7 @@ export interface ResourceFactoryParameterObject { export class ResourceFactory implements pdi.ResourceFactory { _audioPluginManager: AudioPluginManager; _audioManager: AudioManager; - _rendererCandidates: string[] | undefined; + _rendererCandidates: (string | RendererCandidate)[] | undefined; _surfaceFactory: SurfaceFactory; _platform: Platform; diff --git a/src/canvas/RenderingHelper.ts b/src/canvas/RenderingHelper.ts index c4fdff3..4f9816c 100644 --- a/src/canvas/RenderingHelper.ts +++ b/src/canvas/RenderingHelper.ts @@ -1,3 +1,12 @@ +import type { RendererCandidate } from "@akashic/pdi-types"; + +interface WebGLRendererCandidate extends RendererCandidate { + type: "webgl"; + options?: { + enableDepth: boolean; + }; +} + export module RenderingHelper { export function toPowerOfTwo(x: number): number { if ((x & (x - 1)) !== 0) { @@ -14,11 +23,32 @@ export module RenderingHelper { return Math.min(Math.max(x, 0.0), 1.0); } - export function usedWebGL(rendererCandidates?: string[]): boolean { - let used = false; - if (rendererCandidates && (0 < rendererCandidates.length)) { - used = (rendererCandidates[0] === "webgl"); + export function usedWebGL(rendererCandidates?: (string | RendererCandidate)[]): false | Required { + if (!rendererCandidates || rendererCandidates.length === 0) { + return false; + } + + const candidate = rendererCandidates[0]; + + if (typeof candidate === "string") { + if (candidate === "webgl") { + return { + type: "webgl", + options: { + enableDepth: false + } + }; + } + } else if (candidate.type === "webgl") { + const webglRendererCandidate = candidate as WebGLRendererCandidate; + return { + type: "webgl", + options: { + enableDepth: !!webglRendererCandidate.options?.enableDepth + } + }; } - return used; + + return false; } } diff --git a/src/canvas/shims/SurfaceFactory.ts b/src/canvas/shims/SurfaceFactory.ts index 583765c..a6e879d 100644 --- a/src/canvas/shims/SurfaceFactory.ts +++ b/src/canvas/shims/SurfaceFactory.ts @@ -1,3 +1,4 @@ +import type { RendererCandidate } from "@akashic/pdi-types"; import type { CanvasSurface } from "../CanvasSurface"; import { Context2DSurface } from "../context2d/Context2DSurface"; import { RenderingHelper } from "../RenderingHelper"; @@ -8,10 +9,11 @@ export class SurfaceFactory { _shared: WebGLSharedObject | undefined; _disposer: CanvasDisposer = new CanvasDisposer(); - createPrimarySurface(width: number, height: number, rendererCandidates?: string[]): CanvasSurface { - if (RenderingHelper.usedWebGL(rendererCandidates)) { + createPrimarySurface(width: number, height: number, rendererCandidates?: (string | RendererCandidate)[]): CanvasSurface { + const usedWebGL = RenderingHelper.usedWebGL(rendererCandidates); + if (usedWebGL) { if (!this._shared) { - this._shared = new WebGLSharedObject(width, height); + this._shared = new WebGLSharedObject({ width, height, enableDepth: usedWebGL.options.enableDepth }); } return this._shared.getPrimarySurface(); } else { @@ -19,7 +21,7 @@ export class SurfaceFactory { } } - createBackSurface(width: number, height: number, rendererCandidates?: string[]): CanvasSurface { + createBackSurface(width: number, height: number, rendererCandidates?: (string | RendererCandidate)[]): CanvasSurface { const surface = RenderingHelper.usedWebGL(rendererCandidates) ? this._shared!.createBackSurface(width, height) : new Context2DSurface(width, height); diff --git a/src/canvas/webgl/WebGLSharedObject.ts b/src/canvas/webgl/WebGLSharedObject.ts index 644fdff..86551ab 100644 --- a/src/canvas/webgl/WebGLSharedObject.ts +++ b/src/canvas/webgl/WebGLSharedObject.ts @@ -23,9 +23,22 @@ export interface RenderTarget { texture: WebGLTexture | null; } +export interface WebGLSharedObjectParameterObject { + width: number; + height: number; + + /** + * depth buffer を有効にするかどうか。 + * 本値が指定された場合、`this.clear()` 時に depth buffer がクリアされることに注意。 + * 本値は実験的なオプションのため、将来的に挙動が変更される可能性がある。 + */ + enableDepth?: boolean; +} + export class WebGLSharedObject { private _context: WebGLRenderingContext; private _surface: WebGLPrimarySurface; + private _enableDepth: boolean; private _renderTarget: RenderTarget = undefined!; private _defaultShaderProgram: WebGLShaderProgram = undefined!; @@ -48,13 +61,17 @@ export class WebGLSharedObject { private _compositeOps: {[key in pdi.CompositeOperationString]: [number, number]; } = undefined!; private _deleteRequestedTargets: RenderTarget[] = undefined!; - constructor(width: number, height: number) { + constructor(params: WebGLSharedObjectParameterObject) { + const width = params.width; + const height = params.height; + const enableDepth = !!params.enableDepth; const surface = new WebGLPrimarySurface(this, width, height); - const context = surface.canvas.getContext("webgl", { depth: false, preserveDrawingBuffer: true }); + const context = surface.canvas.getContext("webgl", { depth: enableDepth, preserveDrawingBuffer: true }); if (!context) { throw new Error("WebGLSharedObject#constructor: could not initialize WebGLRenderingContext"); } + this._enableDepth = enableDepth; this._surface = surface; this._context = context; this._init(); @@ -105,6 +122,13 @@ export class WebGLSharedObject { } clear(): void { + if (this._enableDepth) { + this._context.depthMask(true); // NOTE: 既存の描画に影響を与えないよう、クリア時のみ有効にする + this._context.clear(this._context.COLOR_BUFFER_BIT | this._context.DEPTH_BUFFER_BIT); + this._context.depthMask(false); + return; + } + this._context.clear(this._context.COLOR_BUFFER_BIT); }