本文へ移動
cccskills
無料GitHub で公開日本語紹介

melonjs-renderer-backends

melonJSがWebGPU・WebGL 2・Canvasのどの描画方式で動いているかを把握し、機能差やフォールバック時の挙動に応じてゲームを調整する方法を確認できます。

原文原文の説明を見る

Use this skill when a feature works on one machine and not another, when choosing or pinning a renderer, or when writing code that must degrade gracefully. Covers the WebGPU to WebGL 2 to Canvas fallback ladder, what each backend supports, capability detection, and the subsystems that warn once and then stop working on Canvas. Triggers on: video.AUTO, video.WEBGPU, video.WEBGL, video.CANVAS, renderer.type, supportsDepthBuffer, shaderLanguage, WebGPU, WebGL2, Canvas fallback, context loss, backend, works on my machine.

melonjs/melonJSスター 6,429(GitHub 6,429 + cccskills 0)

実行スコア 未検証

インストール方法を見る

こんなときに便利

  • 端末によって描画結果が違う原因を調べたいとき
  • Canvasで使える機能と制限を確認したいとき
  • 描画機能の有無に応じた処理を実装したいとき
  • GPUコンテキスト復元後の処理を整えたいとき

日本語での紹介

できること

melonJSの描画方式が環境によって異なる場合の確認方法をまとめています。既定のvideo.AUTOがWebGPU、WebGL 2、Canvasの順に選ぶ仕組みと、各方式で利用できる描画機能を把握できます。renderer.typeや機能判定フラグを使った分岐、機能を段階的に無効化する設計、特定の方式を指定する場合の考え方、GPUコンテキスト復元後のリソース再取得も扱います。

こんなときに便利

手元では動くシェーダーや3D表示が、別の端末では効かない・崩れるといった問題の調査に役立ちます。Canvasへ切り替わった場合に何が使えなくなるかを確認したいときや、ゲームに必要な描画機能が利用可能か判定したいときにも参照できます。テスト環境と実際の利用環境で異なる描画方式を確認する際にも使えます。

使い方の例

  • 「この描画機能がCanvasでどう動くか確認して」
  • 「必要な機能がない端末では起動を止める判定を追加して」
  • 「コンテキスト復元後にGPUリソースを再取得して」

注意点

対象はmelonJS 20.xの描画方式です。video.WEBGLを指定するとWebGL 1のみの端末では初期化に失敗し、別方式へ切り替わりません。

この紹介文は、公開されている SKILL.md をもとに AI(OpenAI Codex)が作成しました。正確な仕様は下の原文を確認してください。

含まれるファイル(1)

  • SKILL.md9.4 KB

SKILL.md(原文)

インストールする前に、エージェントに与えられる指示の中身を確認できます。

Renderer backends and graceful degradation

video.AUTO picks a backend at runtime. The same code runs on a different renderer depending on the machine, and several subsystems degrade to nothing rather than erroring. This is the root cause of most "works on my machine" reports.

The ladder

video.AUTO (the default) tries WebGPU → WebGL 2 → Canvas and uses the first that initialises.

const app = new Application(800, 600, {
    parent: "screen",
    renderer: video.AUTO,     // or video.WEBGPU / video.WEBGL / video.CANVAS
});
await app.init();

WebGL 1 is not in the ladder — 20.x made WebGL 2 the baseline, and pinning video.WEBGL rejects on a WebGL-1-only device rather than degrading.

What each backend can do

WebGPUWebGL 2Canvas
sprites, tilemaps, text✅✅✅
blend modes✅✅✅ except "none"
shaders and post effects✅✅❌ inert
Light2d glow (drawLight)✅✅✅ cached radial gradient
normal-map lighting, Light3d✅✅❌ inert
Mesh✅✅⚠️ CPU-projected, no depth
Camera3d / depth sorting✅✅❌ warns, renders wrong
InstancedMesh✅✅⚠️ one draw per instance
GPU tilemap rendering✅✅❌ per-tile CPU path

The Canvas column is the problem: none of it throws. Each of those paths warns once and then degrades or no-ops, so the game runs and looks wrong.

Two Canvas rows are worth spelling out because they are easy to misread as total failures. A Light2d still draws — the Canvas renderer bakes a radial gradient per light and blits it — what disappears is per-pixel normal-map shading, which warns once (Light2d normal-map lighting requires the WebGL renderer) and then renders sprites unlit. A Mesh still draws too, sorted with the painter's algorithm and no depth buffer, so convex models look right and anything self-overlapping does not. "none" (replace, alpha included) is the one blend mode Canvas cannot express — there is no globalCompositeOperation that disables blending for the drawn area alone — so it resolves to "normal", and setBlendMode reports that back.

Detecting what you have

app.renderer.type;                    // "WebGPU" | "WebGL2" | "CANVAS"
app.renderer.supportsDepthBuffer;     // the practical "is this a GPU backend" test
app.renderer.shaderLanguage;          // "wgsl" | "glsl" | null (null on Canvas)

There are narrower flags for the features that do not travel together: supportsShaderTileLayers, supportsRetainedMesh and supportsInstancing — all three false on Canvas, true on both GPU backends. Prefer a capability flag over comparing type against a string; type is an identity check for code coupled to one backend's machinery.

For a scene that genuinely requires a GPU backend, fail loudly rather than rendering something broken:

await app.init();
if (!app.renderer.supportsDepthBuffer) {
    throw new Error("this game needs WebGL 2 or WebGPU");
}

Writing code that degrades well

Decorative effects — let them no-op. A missing vignette is fine.

Load-bearing effects — guard the carrier. If a shader draws your content rather than decorating it, the carrier renderable shows through raw when the effect is disabled: a 1×1 white texture stretched to fill a quad renders as a white box exactly where the effect should have been.

if (effect.enabled) {
    // draw the carrier the shader consumes
}

Dual-language shaders — a ShaderEffect compiles the body matching renderer.shaderLanguage. With no matching body — a GLSL-only effect on WebGPU, any effect on Canvas — the constructor warns once, leaves enabled === false, and every method becomes a no-op. Pass { glsl, wgsl } rather than a bare string, or gate on renderer.shaderLanguage.

Pinning a backend

Pin only with a reason. video.WEBGL costs you the WebGPU path and the Canvas fallback, so a WebGL-1-only device gets nothing at all.

Legitimate reasons: reproducing a backend-specific bug, a benchmark, or a known driver issue in the field.

For one-off testing you do not need to touch the settings at all: the URI fragments #webgpu, #webgl (or #webgl2) and #canvas override the renderer setting for that run, and behave exactly like passing the matching constant — #webgl on a WebGL-1-only device rejects rather than falling back.

Context loss

A GPU context can be lost at any time — tab backgrounding, driver reset, memory pressure. melonJS handles restoration on both GPU backends: WebGL recompiles every live GLShader and replays its uniform snapshot, WebGPU renegotiates a device and rebuilds its batchers, and both then emit event.ONCONTEXT_RESTORED (the paired loss event is event.ONCONTEXT_LOST).

What you must handle is your own GPU-side state. If you cached a raw texture or program handle, re-acquire it on restore rather than holding the stale one:

import { event } from "melonjs";

event.on(event.ONCONTEXT_RESTORED, (renderer) => {
    // re-acquire anything you were holding by raw handle
});

Test on the backend your users get, not the one your harness picks

video.AUTO prefers WebGPU where it exists. Headless Chromium usually has no GPU adapter and falls back to WebGL, so an automated suite can pass every run while the WebGPU path is broken — the two differ in real, throwing ways (see below). Pin the backend explicitly when it matters: renderer: video.WEBGPU, or the #webgpu / #webgl URI fragment on a page you can open by hand.

Practical differences

  • Frame capture orientation differs: row 0 of a toFrameTexture() capture is the bottom of the frame under WebGL and the top under WebGPU, so a GLSL body that flips with 1.0 - uv.y must not do so in its WGSL twin. The WebGPU capture also preserves alpha, where the WebGL one captures into an opaque RGB texture.
  • The advanced blend modes cost far more than they look. overlay, difference, hard-light, soft-light, color-dodge, color-burn, darken and lighten cannot be expressed as fixed-function blending, so on both GPU backends each such draw is bracketed individually: capture the destination, redraw offscreen, composite through BlendEffect. Fine for accents, ruinous for hundreds of objects. normal, additive, multiply, screen and exclusion are ordinary fixed-function state and cost nothing extra.
  • WebGPU rejects a zero-sized image source; WebGL shrugs at it. Uploading a 0-width or 0-height canvas throws OperationError: GPUQueue.copyExternalImageToTexture: External image state is not valid, from a stack that reads drawImage → addQuad → getBinding. WebGL uploads the same source without complaint, so this is a class of bug that cannot appear on one backend and stops the game dead on the other. The usual source is a Text whose string is empty or whitespace-only — it measures to nothing, so its glyph canvas has no width. Give a placeholder label a real glyph and hide it with alpha/position instead of blanking its text.
  • 3D meshes do not honour blend modes. The mesh pass draws with its own depth/blend state; asking for one of the advanced modes logs a one-time blend mode "…" is not supported for 3D meshes warning and falls back to "normal". Gradient fills warn the same way.

Symptom → cause

symptomcause
effect works locally, not for a userthey got the Canvas fallback, or a different GPU backend
sprites render unlit though lights are in the sceneCanvas fallback — normal-map shading is inert (check the console)
mesh looks inside-out where it overlaps itselfCanvas fallback — painter's algorithm, no depth buffer
shader works on one machine onlyGLSL-only effect, AUTO chose WebGPU elsewhere — the console carries the warning
a solid box where an effect should becarrier drawn while the effect is disabled
nothing renders at all on an old devicevideo.WEBGL pinned; WebGL 1 is rejected, not downgraded
ported shader is vertically flippedthe WebGL capture is bottom-up, the WebGPU one top-down
copyExternalImageToTexture: External image state is not valida zero-sized upload source — most often a Text with an empty or whitespace-only string
runs on the test machine, dies on the dev'sthe harness fell back to WebGL and never exercised WebGPU
a blended mode is ignored on a meshmeshes fall back to "normal"; look for the one-time warning
textures vanish after the tab is restoredcached raw GPU handles not re-acquired on context restore

Related skills

  • melonjs-getting-started — renderer selection in the Application settings
  • melonjs-effects-and-shaders — dual-language shaders and the Canvas no-op
  • melonjs-3d — the tier that requires a GPU backend outright

レビュー

まだレビューはありません。使ってみた感想をお寄せください。

コメント

ログインなしで書き込めます。使ってみた感想、質問、動かなかった環境などを気軽にどうぞ。

まだコメントはありません。最初のコメントを書いてみませんか。

送信するとすぐに公開されます。メールアドレスや電話番号などの個人情報は書かないでください。URL は 2 つまでです。

0 / 1000 文字

このフォームは reCAPTCHA で保護されており、Google のプライバシーポリシーと利用規約が適用されます。

同じリポジトリのスキル

melonjs

無料概要あり

melonJSを使ったゲーム制作で、目的に合う専門ガイドを選ぶための入口です。初期化から描画、入力、物理演算、音声、2D・3D機能まで案内します。

  • melonJSで作る内容に合うガイドを探したいとき
  • 新しいゲームの初期化手順を知りたいとき
  • 3Dやモデル読み込みの参照先を探したいとき
melonjs/melonJS6,4292026年10月29日 更新

melonjs-20-migration

無料概要あり

melonJS 19.x以前の知識を20.x向けに更新し、初期化や描画効果、廃止・非推奨APIの変更点を確認して移行時の不具合を調べられます。

  • 19.x以前のゲームを20.xへ移行したいとき
  • 古いAPIが見つからない原因を調べたいとき
  • 非推奨の描画効果を置き換えたいとき
melonjs/melonJS6,4292026年10月29日 更新

melonjs-3d

無料概要あり

melonJSの3D・2.5Dゲーム向けに、カメラ、メッシュ、ライト、奥行き順、透明表現やフォグの設定と座標系の注意点を確認できます。

  • 3Dカメラをステージに設定したいとき
  • メッシュやビルボードを配置したいとき
  • 奥行き順や透明表現を調整したいとき
melonjs/melonJS6,4292026年10月29日 更新

melonjs-3d-assets

無料概要あり

melonJSでglTF・GLBやOBJ・MTLの3Dモデルを読み込み、マテリアルやライト、アニメーション、影、インスタンスの扱い方を確認できます。

  • glTF・GLBのシーンを読み込みたいとき
  • OBJモデルとMTL素材を使いたいとき
  • モデルの向きや大きさを調整したいとき
melonjs/melonJS6,4292026年10月29日 更新

melonjs-audio

無料概要あり

melonJSで効果音やBGMを読み込み、再生・停止・音量調整するほか、位置に応じた音や音声合成、ミックス全体へのエフェクト設定を扱うスキルです。

  • 効果音とBGMを読み込みたいとき
  • ゲーム内の位置に応じて音を鳴らしたいとき
  • 音声ファイルなしで短い音を作りたいとき
melonjs/melonJS6,4292026年10月29日 更新

melonjs-camera-and-drawing

無料概要あり

melonJSのカメラ追従や画面効果、座標変換、図形描画を実装する際の要点を確認できます。描画のクリッピングやCanvasへの焼き込み、ピクセルの読み出しも扱います。

  • プレイヤーを追うカメラの範囲を設定したいとき
  • ワールド座標と画面座標を変換したいとき
  • 独自描画に図形やグラデーションを使いたいとき
melonjs/melonJS6,4292026年10月29日 更新

melonjs のスキルをすべて見る

このスキルの問題を報告する