Skip to content

Commit 65974d5

Browse files
authored
Merge pull request #1332 from melonjs/fix/renderer-and-plugin-fixes
Fix renderer batcher API, setBlendMode PMA, and plugin registration
2 parents 5207b75 + b485a09 commit 65974d5

File tree

7 files changed

+42
-18
lines changed

7 files changed

+42
-18
lines changed

packages/melonjs/CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,10 @@
2626
- TypeScript: convert application, input, and UI modules to TypeScript — application, header, resize, input, pointer, pointerevent, gamepad, uibaseelement, uispriteelement, uitextbutton
2727

2828
### Fixed
29+
- WebGLRenderer: `setBatcher()` now rebinds the shared vertex buffer when switching batchers, allowing custom batchers with their own GL buffers to integrate without manual cleanup
30+
- WebGLRenderer: `setBlendMode()` now accepts a `premultipliedAlpha` parameter (default `true`) for correct blending with non-premultiplied textures; removed internal `gl`/`context` parameter from both WebGL and Canvas renderers
31+
- Renderer: add base `setBlendMode()` and `GPURenderer` property to fix TypeScript `as any` casts in `header.ts` and `resize.ts`
32+
- Plugin: `plugin.register()` now uses `pluginClass.name` for name derivation, fixing class name extraction when bundlers strip class names
2933
- TMXTileset: fix animation key using first frame tileid instead of the tile's own id
3034
- CanvasRenderer: replace bezier ellipse approximation with native `context.ellipse()` (with polyfill for older browsers)
3135
- Plugin: fix `plugin.get()` throwing `TypeError` when searching by name with no match (instanceof on string)

packages/melonjs/src/application/header.ts

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,11 @@ import type Application from "./application.ts";
88
export function consoleHeader(app: Application): void {
99
const renderType = app.renderer.type;
1010
const gpu_renderer =
11-
typeof (app.renderer as any).GPURenderer === "string"
12-
? ` (${(app.renderer as any).GPURenderer})`
11+
typeof app.renderer.GPURenderer === "string"
12+
? ` (${app.renderer.GPURenderer})`
1313
: "";
1414
const depthTesting =
15-
renderType.includes("WebGL") &&
16-
(app.renderer as any).depthTest === "z-buffer"
15+
renderType.includes("WebGL") && app.renderer.depthTest === "z-buffer"
1716
? "Depth Test | "
1817
: "";
1918
const audioType = device.hasWebAudio ? "Web Audio" : "HTML5 Audio";

packages/melonjs/src/application/resize.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ import type Application from "./application.ts";
1212
function scale(game: Application, x: number, y: number): void {
1313
const renderer = game.renderer;
1414
const canvas = renderer.getCanvas();
15-
const context = renderer.getContext();
1615
const settings = renderer.settings as any;
1716
const pixelRatio = device.devicePixelRatio;
1817

@@ -28,7 +27,7 @@ function scale(game: Application, x: number, y: number): void {
2827

2928
// if anti-alias and blend mode were reset (e.g. Canvas mode)
3029
renderer.setAntiAlias(settings.antiAlias);
31-
(renderer as any).setBlendMode(settings.blendMode, context);
30+
renderer.setBlendMode(settings.blendMode);
3231

3332
// force repaint
3433
game.repaint();

packages/melonjs/src/plugin/plugin.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,8 @@ export function register(
9595
...args: any[]
9696
): void {
9797
// derive name from class if not provided
98-
const pluginName = name || pluginClass.toString().match(/ (\w+)/)![1];
98+
const pluginName =
99+
name || pluginClass.name || pluginClass.toString().match(/ (\w+)/)![1];
99100

100101
// ensure me.plugins[name] is not already "used"
101102
if (cache[pluginName]) {

packages/melonjs/src/video/canvas/canvas_renderer.js

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ export default class CanvasRenderer extends Renderer {
108108
}
109109

110110
/**
111-
* set a blend mode for the given context. <br>
111+
* set the current blend mode for this renderer. <br>
112112
* All renderers support: <br>
113113
* - "normal" : draws new content on top of the existing content <br>
114114
* <img src="../images/normal-blendmode.png" width="180"/> <br>
@@ -140,11 +140,10 @@ export default class CanvasRenderer extends Renderer {
140140
* <img src="../images/exclusion-blendmode.png" width="180"/> <br>
141141
* @see https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/globalCompositeOperation
142142
* @param {string} [mode="normal"] - blend mode
143-
* @param {CanvasRenderingContext2D} [context]
144143
* @returns {string} the blend mode actually applied (may differ if the requested mode is unsupported)
145144
*/
146-
setBlendMode(mode = "normal", context) {
147-
context = context || this.getContext();
145+
setBlendMode(mode = "normal") {
146+
const context = this.getContext();
148147
this.currentBlendMode = mode;
149148
switch (mode) {
150149
case "lighter":

packages/melonjs/src/video/renderer.js

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,12 @@ export default class Renderer {
7373
*/
7474
this.depthTest = "sorting";
7575

76+
/**
77+
* The GPU renderer string (WebGL only, undefined for Canvas)
78+
* @type {string|undefined}
79+
*/
80+
this.GPURenderer = undefined;
81+
7682
/**
7783
* The Path2D instance used by the renderer to draw primitives
7884
* @type {Path2D}
@@ -240,6 +246,16 @@ export default class Renderer {
240246
return this.currentBlendMode;
241247
}
242248

249+
/**
250+
* set the current blend mode.
251+
* Subclasses (CanvasRenderer, WebGLRenderer) implement the actual GL/Canvas logic.
252+
* @param {string} [mode="normal"] - blend mode
253+
* @param {boolean} [premultipliedAlpha=true] - whether textures use premultiplied alpha (WebGL only)
254+
*/
255+
setBlendMode(mode = "normal") {
256+
this.currentBlendMode = mode;
257+
}
258+
243259
/**
244260
* get the current fill & stroke style color.
245261
* @returns {Color} current global color

packages/melonjs/src/video/webgl/webgl_renderer.js

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -358,6 +358,8 @@ export default class WebGLRenderer extends Renderer {
358358
// flush the current batcher
359359
this.currentBatcher.flush();
360360
}
361+
// rebind the renderer's shared vertex buffer (custom batchers may have bound their own)
362+
this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.vertexBuffer);
361363
this.currentBatcher = batcher;
362364
this.currentBatcher.bind();
363365
}
@@ -724,7 +726,7 @@ export default class WebGLRenderer extends Renderer {
724726
}
725727

726728
/**
727-
* set a blend mode for the given context. <br>
729+
* set the current blend mode for this renderer. <br>
728730
* All renderers support: <br>
729731
* - "normal" : draws new content on top of the existing content <br>
730732
* <img src="../images/normal-blendmode.png" width="180"/> <br>
@@ -744,15 +746,19 @@ export default class WebGLRenderer extends Renderer {
744746
* and will always fall back to "normal" in WebGL. <br>
745747
* @see https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/globalCompositeOperation
746748
* @param {string} [mode="normal"] - blend mode
747-
* @param {WebGLRenderingContext} [gl] - a WebGL context
749+
* @param {boolean} [premultipliedAlpha=true] - whether textures use premultiplied alpha (affects source blend factor)
748750
* @returns {string} the blend mode actually applied (may differ if the requested mode is unsupported)
749751
*/
750-
setBlendMode(mode = "normal", gl = this.gl) {
752+
setBlendMode(mode = "normal", premultipliedAlpha = true) {
751753
if (this.currentBlendMode !== mode) {
754+
const gl = this.gl;
752755
this.flush();
753756
gl.enable(gl.BLEND);
754757
this.currentBlendMode = mode;
755758

759+
// source factor depends on whether textures use premultiplied alpha
760+
const srcAlpha = premultipliedAlpha ? gl.ONE : gl.SRC_ALPHA;
761+
756762
switch (mode) {
757763
case "screen":
758764
gl.blendEquation(gl.FUNC_ADD);
@@ -763,7 +769,7 @@ export default class WebGLRenderer extends Renderer {
763769
case "additive":
764770
case "add":
765771
gl.blendEquation(gl.FUNC_ADD);
766-
gl.blendFunc(gl.ONE, gl.ONE);
772+
gl.blendFunc(srcAlpha, gl.ONE);
767773
break;
768774

769775
case "multiply":
@@ -777,7 +783,7 @@ export default class WebGLRenderer extends Renderer {
777783
gl.blendFunc(gl.ONE, gl.ONE);
778784
} else {
779785
gl.blendEquation(gl.FUNC_ADD);
780-
gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA);
786+
gl.blendFunc(srcAlpha, gl.ONE_MINUS_SRC_ALPHA);
781787
this.currentBlendMode = "normal";
782788
}
783789
break;
@@ -788,14 +794,14 @@ export default class WebGLRenderer extends Renderer {
788794
gl.blendFunc(gl.ONE, gl.ONE);
789795
} else {
790796
gl.blendEquation(gl.FUNC_ADD);
791-
gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA);
797+
gl.blendFunc(srcAlpha, gl.ONE_MINUS_SRC_ALPHA);
792798
this.currentBlendMode = "normal";
793799
}
794800
break;
795801

796802
default:
797803
gl.blendEquation(gl.FUNC_ADD);
798-
gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA);
804+
gl.blendFunc(srcAlpha, gl.ONE_MINUS_SRC_ALPHA);
799805
this.currentBlendMode = "normal";
800806
break;
801807
}

0 commit comments

Comments
 (0)