Run in the browser
Run the scene from the earlier pages in a browser with the WebGPU backend, behind AwakeKt's loading screen.
WebGPU Web (wasmJs)
The app and GameRenderPlan stay in commonMain unchanged. This page adds a wasmJs target, the
WebGPU backend, and a page to host it.
Add the WebGPU backend
The WebGPU backend builds on wgpu4k, which only publishes snapshot builds. So the backend is published as a snapshot too, to Maven Central's snapshot repository, and Core releases do not include it. Each Core release publishes a WebGPU snapshot built from it instead.
Add the snapshot repository in settings.gradle.kts:
dependencyResolutionManagement {
repositories {
mavenCentral()
maven("https://central.sonatype.com/repository/maven-snapshots/") {
content { excludeGroup("io.ygdrasil") }
}
// The wgpu4k builds the WebGPU backend was tested with, which Sonatype no longer serves.
maven("https://awakekt.github.io/awake/") { content { includeGroup("io.ygdrasil") } }
}
}
Add the backend to the catalog at your Core version with -SNAPSHOT appended, the WebGPU build of
that Core release:
[libraries]
awake-backend-webgpu = { module = "com.awakekt.awake.backend:webgpu", version = "0.43.0-SNAPSHOT" }
Then add a browser target and the dependency:
kotlin {
@OptIn(org.jetbrains.kotlin.gradle.ExperimentalWasmDsl::class)
wasmJs {
browser()
binaries.executable()
}
sourceSets {
wasmJsMain.dependencies {
implementation(libs.awake.backend.webgpu)
}
}
}
The snapshot carries the exact wgpu4k builds it was tested with, so Gradle resolves those without more setup.
Keep WebGPU on your Core release
0.43.0-SNAPSHOT depends on every Core module at exactly 0.43.0 and
holds them there, so a build that also asks for a newer Core fails to resolve rather than mixing
two, and an older Core in the build is moved up to 0.43.0. Do not take the newest
-SNAPSHOT in the snapshot repository instead: that one is built from main after the release,
and it moves the wasmJs target onto Core snapshots.
Launch the app
In wasmJsMain, hand the same app and plan to launchWebGpuGame:
import com.awakekt.awake.webgpu.application.launchWebGpuGame
fun main() = launchWebGpuGame(firstScene(), GameRenderPlan)
launchWebGpuGame finds the <canvas> with id awake-canvas, keeps it the size of the window,
and draws a frame on every animation frame. Pass canvasId to use a different canvas.
On a high-DPI screen the canvas has 2.25 to 9 times the pixels of a 1x one. To trade some of them
for frame rate, pass renderScale = { settings.renderScale }: the 3D scene renders at that fraction
of the canvas and the UI stays sharp. maxPixelRatio caps the whole canvas, UI included. See
Resolution and render scale.
Add the page and the loading screen
Put an index.html in src/wasmJsMain/resources/:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover">
<title>Hello AwakeKt</title>
<style>
html, body { margin: 0; width: 100%; height: 100%; overflow: hidden; }
canvas { display: block; width: 100vw; height: 100vh; }
</style>
</head>
<body>
<canvas id="awake-canvas"></canvas>
<script src="awake-loader.js" data-product="Hello"></script>
<script src="hello.js"></script>
</body>
</html>
- The canvas id matches what
launchWebGpuGamelooks for. hello.jsstands for your app's bundle, which is named after the Gradle module.awake-loader.jsis AwakeKt's loading screen. Copyawake-loader.jsfrom the WebGPU backend intosrc/wasmJsMain/resources/, next toindex.html. Load it before the bundle.
The loading screen shows the AwakeKt mark and a progress bar: first the .wasm download, by
bytes, then WebGPU and shader startup. The first frame drawn to the canvas dismisses it. If the
download fails, the browser has no WebGPU, or the engine fails to start, it shows a message instead
of leaving a black canvas. data-product is the name shown after "AwakeKt" on the screen; leave it
out to show only "AwakeKt".
For a game rather than an AwakeKt product, set data-mode="game" and data-title="Your Game": the
screen turns neutral monochrome, so it suits any art direction, shows your game's title, and keeps a
small "Made with AwakeKt" line. Add data-attribution="none" to drop that line.
Ship the texture transcoder
A project's cooked textures (.ktx2) are transcoded in the browser by Basis Universal, which the page
loads from basis/basis_transcoder.js and basis/basis_transcoder.wasm beside index.html. Apply
Core's Gradle plugin to your web module and it puts them there, for the development server and the
production build:
It takes the files from the texture-ktx-loader-wasm-js klib your app already depends on and checks
them against the digests Core pins, so the build fails if they aren't the release's own; keep the plugin
on the same version as Core. An app that doesn't use KTX2 textures gets nothing added. The game template
applies it already.
If you can't apply the plugin, copy the two files by hand from the basis/ folder of the klib of your
Core version. The klib is on Maven Central under com.awakekt.awake.asset, and in your Gradle cache
once the app has built:
unzip texture-ktx-loader-wasm-js-<version>.klib 'basis/basis_transcoder.js' 'basis/basis_transcoder.wasm' -d src/wasmJsMain/resources
To check, open basis/basis_transcoder.js from the running page: it must be JavaScript, not an HTML
404 page. Without the files the app still runs, logs "No Basis Universal transcoder" once with the
path it tried, and loads each texture's mobile file or source image instead.
Ship the socket worker
A game that talks to its server with awake:net:client-browser runs its WebSocket in a Web Worker
from awake-net/socket-worker.js. Apply com.awakekt.awake.plugin.socket-worker to your web module
the same way and the page serves it; without it the socket runs on the page. See
Networking in the browser.
Run it
Open the address it prints in a browser with WebGPU. The loading screen suggests a current Chrome or Edge, or Safari 26 or later.
One plan for both backends
The WebGPU backend runs as much of GameRenderPlan as it supports and reports anything it
leaves out, so the plan never needs a browser copy.
No WebGPU, no start
In a browser without WebGPU, launchWebGpuGame stops before the engine starts, with "WebGPU is
unavailable in this browser or device", and the loading screen says so.
See also
- WebGPU backend for how the backend works.
- Releases and compatibility for which targets each release supports.