From 3136e1d33fe10542d857f76aa82600db4f2e5238 Mon Sep 17 00:00:00 2001 From: Davide Tantillo Date: Wed, 2 Oct 2024 14:59:09 +0200 Subject: [PATCH] [ts][webgl] Allow to define a custom Shader for SceneRenderer. --- .../spine-player/example/custom-shader.html | 137 +++++++++++++ .../spine-webgl/example/custom-shader.html | 186 ++++++++++++++++++ spine-ts/spine-webgl/src/SceneRenderer.ts | 15 +- spine-ts/spine-webgl/src/Shader.ts | 11 ++ spine-ts/spine-webgl/src/SpineCanvas.ts | 13 +- 5 files changed, 357 insertions(+), 5 deletions(-) create mode 100644 spine-ts/spine-player/example/custom-shader.html create mode 100644 spine-ts/spine-webgl/example/custom-shader.html diff --git a/spine-ts/spine-player/example/custom-shader.html b/spine-ts/spine-player/example/custom-shader.html new file mode 100644 index 000000000..bb29c2015 --- /dev/null +++ b/spine-ts/spine-player/example/custom-shader.html @@ -0,0 +1,137 @@ + + + + + + + + + + + + +
+
+ Red: +
+ Green: +
+ Blue: +
+ + + + + \ No newline at end of file diff --git a/spine-ts/spine-webgl/example/custom-shader.html b/spine-ts/spine-webgl/example/custom-shader.html new file mode 100644 index 000000000..11ad11d9e --- /dev/null +++ b/spine-ts/spine-webgl/example/custom-shader.html @@ -0,0 +1,186 @@ + + + + + + + + + + + +
+ Red: +
+ Green: +
+ Blue: +
+ + + + + \ No newline at end of file diff --git a/spine-ts/spine-webgl/src/SceneRenderer.ts b/spine-ts/spine-webgl/src/SceneRenderer.ts index c4e4c9bc1..53db76a30 100644 --- a/spine-ts/spine-webgl/src/SceneRenderer.ts +++ b/spine-ts/spine-webgl/src/SceneRenderer.ts @@ -31,7 +31,7 @@ import { Color, Disposable, Skeleton, MathUtils, TextureAtlasRegion } from "@eso import { OrthoCamera } from "./Camera.js"; import { GLTexture } from "./GLTexture.js"; import { PolygonBatcher } from "./PolygonBatcher.js"; -import { Shader } from "./Shader.js"; +import { CustomShader, Shader } from "./Shader.js"; import { ShapeRenderer } from "./ShapeRenderer.js"; import { SkeletonDebugRenderer } from "./SkeletonDebugRenderer.js"; import { SkeletonRenderer, VertexTransformer } from "./SkeletonRenderer.js"; @@ -60,12 +60,15 @@ export class SceneRenderer implements Disposable { skeletonRenderer: SkeletonRenderer; skeletonDebugRenderer: SkeletonDebugRenderer; - constructor (canvas: HTMLCanvasElement, context: ManagedWebGLRenderingContext | WebGLRenderingContext, twoColorTint: boolean = true) { + constructor (canvas: HTMLCanvasElement, context: ManagedWebGLRenderingContext | WebGLRenderingContext, twoColorTint: boolean = true, customShader?: Shader) { this.canvas = canvas; this.context = context instanceof ManagedWebGLRenderingContext ? context : new ManagedWebGLRenderingContext(context); this.twoColorTint = twoColorTint; this.camera = new OrthoCamera(canvas.width, canvas.height); - this.batcherShader = twoColorTint ? Shader.newTwoColoredTextured(this.context) : Shader.newColoredTextured(this.context); + if (customShader) + this.batcherShader = customShader; + else + this.batcherShader = twoColorTint ? Shader.newTwoColoredTextured(this.context) : Shader.newColoredTextured(this.context); this.batcher = new PolygonBatcher(this.context, twoColorTint); this.shapesShader = Shader.newColored(this.context); this.shapes = new ShapeRenderer(this.context); @@ -489,6 +492,10 @@ export class SceneRenderer implements Disposable { this.camera.update(); } + setCustomBatcherShader(shader: CustomShader) { + this.batcherShader = shader; + } + private enableRenderer (renderer: PolygonBatcher | ShapeRenderer | SkeletonDebugRenderer) { if (this.activeRenderer === renderer) return; this.end(); @@ -496,6 +503,8 @@ export class SceneRenderer implements Disposable { this.batcherShader.bind(); this.batcherShader.setUniform4x4f(Shader.MVP_MATRIX, this.camera.projectionView.values); this.batcherShader.setUniformi("u_texture", 0); + if (this.batcherShader instanceof CustomShader && this.batcherShader.setUniformsCallback !== undefined) + this.batcherShader.setUniformsCallback(this.batcherShader); this.batcher.begin(this.batcherShader); this.activeRenderer = this.batcher; } else if (renderer instanceof ShapeRenderer) { diff --git a/spine-ts/spine-webgl/src/Shader.ts b/spine-ts/spine-webgl/src/Shader.ts index c99502d91..3242c27b7 100644 --- a/spine-ts/spine-webgl/src/Shader.ts +++ b/spine-ts/spine-webgl/src/Shader.ts @@ -298,3 +298,14 @@ void main () { return new Shader(context, vs, fs); } } + +export class CustomShader extends Shader { + constructor ( + context: ManagedWebGLRenderingContext | WebGLRenderingContext, + vertexShader: string, + fragmentShader: string, + public setUniformsCallback?: (shader: Shader) => void, + ) { + super(context, vertexShader, fragmentShader); + } +} \ No newline at end of file diff --git a/spine-ts/spine-webgl/src/SpineCanvas.ts b/spine-ts/spine-webgl/src/SpineCanvas.ts index e11f67c1f..6a3d45b20 100644 --- a/spine-ts/spine-webgl/src/SpineCanvas.ts +++ b/spine-ts/spine-webgl/src/SpineCanvas.ts @@ -27,7 +27,7 @@ * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *****************************************************************************/ -import { TimeKeeper, AssetManager, ManagedWebGLRenderingContext, SceneRenderer, Input, StringMap } from "./index.js"; +import { TimeKeeper, AssetManager, ManagedWebGLRenderingContext, SceneRenderer, Input, StringMap, CustomShader, Shader } from "./index.js"; /** An app running inside a {@link SpineCanvas}. The app life-cycle * is as follows: @@ -56,6 +56,12 @@ export interface SpineCanvasConfig { pathPrefix?: string; /* The WebGL context configuration */ webglConfig?: any; + /** Your custom Shader configuration. See {@link CustomShader} */ + shader?: { + vertexShader: string, + fragmentShader: string, + setUniformCallback: (shader: Shader) => void, + }; } /** Manages the life-cycle and WebGL context of a {@link SpineCanvasApp}. The app loads @@ -75,6 +81,8 @@ export class SpineCanvas { readonly assetManager: AssetManager; /** The input processor used to listen to mouse, touch, and keyboard events. */ readonly input: Input; + /** The custom shader, if {@link SpineCanvasConfig.shader} config is passed. */ + readonly shader?: Shader; private disposed = false; @@ -93,7 +101,8 @@ export class SpineCanvas { this.htmlCanvas = canvas; this.context = new ManagedWebGLRenderingContext(canvas, config.webglConfig); - this.renderer = new SceneRenderer(canvas, this.context); + this.shader = config.shader ? new CustomShader(this.context, config.shader.vertexShader, config.shader.fragmentShader, config.shader.setUniformCallback) : undefined; + this.renderer = new SceneRenderer(canvas, this.context, true, this.shader); this.gl = this.context.gl; this.assetManager = new AssetManager(this.context, config.pathPrefix); this.input = new Input(canvas);