Material monolith with immutable MaterialDefinition plus
MaterialInstance. Remove legacy topology mutation, WebGL-style blend/side fields, material-owned
render order and shadow participation, material display transforms, shared UV matrices, shadow
proxy materials, onBeforeCompile, and shaderCacheId. Move object ordering and shadow flags to
Mesh; require construction-time topology, explicit coverage/compositing, typed
MaterialAttributeSemantic/MaterialUniformSemantic/MaterialTextureSemantic bindings, and
explicit pass pipeline state. This is a direct migration with no compatibility adapter.MaterialBlock into the fixed
MaterialTextureBlock. The material scalar block is now 432 bytes, the texture-slot block is
1,920 bytes, WebGPU material textures begin at binding 2, and custom uniform block registrations
begin after ten built-in WebGL2 binding points.replaceColor() now requires linear or srgb,
and the default Forward pipeline always routes surface presentation through the Render Graph so
the final output transfer is owned by the output stage rather than individual materials.RenderColorEncoding. Manual
RenderTarget presentation now accepts an explicit colorEncoding; linear inputs receive the final
sRGB transfer, while display-transformed srgb inputs are preserved without a second conversion.Add canonical built-in material definitions, stable material IDs and revisions, explicit forward/depth-only/shadow-caster/picking roles, role-aware shader variants, per-slot texture/UV transform/encoding/channel data, and deterministic coverage/transmission/compositing ownership. Shadow rendering now requests the original material's shadow role, glTF constructs layered PBR topology and all texture transforms before instantiation, and display conversion remains solely in post-processing/output.
Keep default Forward lighting, clear colors, transparent blending, and intermediate effects in linear space, then apply one exact linear-to-sRGB transfer at the browser surface. Multi-camera load/blend stays in a renderer-owned linear composition target, while already transformed Color Uber output is presented without a second conversion. Single-camera MSAA resolves into the persistent single-sample composition target; multi-camera stacks use one single-sample color/depth/stencil composition contract so later cameras can load prior contents exactly.
Keep ShaderMaterial scene output linear and make custom pipeline presentation encoding explicit. ShaderToy now relies on the shared Forward output transfer, while the compute particle field and crystal path tracer declare their display-referred output so their authored grading is not transferred twice.
Advance the RHI benchmark manifest to schema 4 and model fixed surface-output draws separately from primary scene and post-process draws; immutable snapshots from earlier schemas remain historical evidence and are not rewritten.
Route opaque-composited transmission surfaces through the after-opaque forward queue so their scene-color dependency is satisfied without conflating transmission with alpha blending. Apply texture-slot encoding consistently to 2D, cube, and environment samples, including explicit sRGB decoding for the LDR studio IBL. WebGPU shader lowering now retains the managed material sampler for single-UV shaders instead of bypassing texture transforms, decoding, and channel remapping, restoring WebGL2/WebGPU material parity.
Add the high-end rendering profile, per-camera standard/reversed depth modes, finite/infinite
reversed-Z projection, depth-convention-aware surfaces, render targets, shadows, storage graphics,
and GPU picking. Add optional camera-relative GPU transforms while preserving CPU world identity,
plus submission-transactional current/previous camera, mesh, instance, skinning, and morph state.
Node.invalidateTransformHistory() resets discontinuous motion deterministically.
Add the WebGPU-only ClusteredForwardPlusPipelineFactory high-end opaque-scene slice. Registered
ordinary Mesh buckets now use stable dirty GPU Scene records, six-level previous-frame Hi-Z
occlusion, projected-size LOD compaction, fixed indexed-indirect draws, depth-driven logarithmic
3D clusters, a bounded count/prefix/write light allocator, storage GGX PBR, HDR Bloom, ACES
display, and on-demand visibility/overflow diagnostics. Add real WebGPU renderer coverage for the
compute/dispatch/indirect-draw path. Make Hi-Z conservative for both standard and reversed depth,
use the committed previous view/projection/depth convention for temporal occlusion, preserve the
depth prepass during color shading, and use inverse-transpose object normal matrices. Registered
buckets now migrate at runtime between the GPU path and a shared Forward compatibility path for
material/geometry replacement, alpha, transparency, skinning, morphing, unregistered meshes, and
object-capacity overflow; the fallback preserves normal opaque/transparent sorting, shadows, and
transmission scene-color input without double-drawing GPU-managed meshes. Device limit
requirements cover every configured geometry/cluster buffer and dispatch dimension. Add a real
WebGPU 100k-static + 10k-dynamic + 256-light scale/recovery acceptance fixture and deterministic
cluster-overflow coverage. Share metallic/roughness surface evaluation and the BRDF between
ordinary Forward and clustered storage shaders so Forward+ replaces only light-list iteration. Add
native GPU Scene base-color, metallic, roughness, combined metallic-roughness, occlusion,
emission, and normal maps with UV0/UV1, UV matrices, tangent streams, sampler mutation, runtime
texture replacement, and device-recovery coverage; incompatible alpha/layered/deformed inputs
continue to use the Forward fallback.
Let scriptable pipeline factories create persistent renderer-owned storage buffers, stage dirty
writes before graph import, and commit or discard CPU temporal state at the actual submission
boundary through frameSubmitted() and frameDiscarded(). Pipeline-owned buffers retain normal
device-loss recipes and submission-aware destruction. Frame completion still runs when a
post-submission pipeline callback throws, so presentation, events, diagnostics, and temporal
cleanup are not skipped after GPU work has already been submitted.
Let scriptable render graphs import engine-managed Texture objects as sampled persistent
resources while preserving renderer upload/recovery/submission ownership. Expose the public
per-stage sampler limit alongside the existing sampled-texture limit.
Add modern WebGPU capability discovery for subgroups, adapter subgroup-size limits,
shader-f16, and timestamp-query; expose renderer feature queries for explicit f32/workgroup
fallback selection. Direct WGSL f16 now preserves the exact native artifact while completing Naga
validation through an equivalent f32 specialization. Compute buffer minBindingSize is derived
from WGSL store types, including the required one-element runtime-array minimum.
Add submission-aware timestamp QuerySets, pass timestamp writes, explicit resolves, and validated debug groups/markers to the portable RHI. Opt-in renderer diagnostics now publish Render Graph record/compile/prepare/execute CPU timing, per-pass asynchronous GPU timing, and compiled resource lifetime intervals through a non-blocking three-slot readback ring; the default diagnostics-off path creates no query resources.
Add explicit Render Graph texture views for mip, array-layer, dimension, compatible-format, and depth/stencil-aspect access across sampled, storage, attachment, and copy paths. Add renderer-owned double/triple-buffer history textures whose recipes survive device recovery, whose contents invalidate on descriptor or device-generation changes, and whose current/history rotation commits only after a successful submitted writer frame. History recipes initially accept one single-sample 2D color mip/layer so slot validity always means complete initialization.
Add camera-relative cascaded shadows for directional lights on the shared WebGL 2/WebGPU shadow
atlas path. DirectionalLight.shadow now supports one to four cascades, practical split
weighting, a maximum shadow distance, cross-cascade blending, and texel stabilization while
preserving the existing single-shadow default. Filtered directional shadow contrast is
art-directable through shadowStrength. Add an interactive pastel sunset geometry-garden example
with live cascade count, stabilization, orbit controls, split, blend, strength, distance, and 4×
MSAA.
Promote OrbitControls from an example helper to the public src/controls API, add constrained
setView() support for scripted tours, and make maintained examples reuse the engine control
instead of carrying local camera gesture implementations.
MaterialBlock std140 ABI for layered PBR material data and reserve WebGPU group
3 bindings 0/1 for the pass-global opaque scene texture. Portable custom uniform blocks retain
registration order and now start at WebGPU group 3 binding 2.KHR_materials_anisotropy,
KHR_materials_clearcoat, KHR_materials_transmission, KHR_materials_volume, and
KHR_materials_ior, plus spectrally integrated thin-film KHR_materials_iridescence.PostProcessRenderPipelineFactory, engine-owned
soft-knee/13-tap/tent-pyramid Bloom, and a one-pass ColorUber display transform with LMS white
balance, grading, PBR Neutral/ACES/Reinhard tone mapping, vignette, exact sRGB output, and
display-space dithering.Text2D wrapping for mixed CJK/Latin content, max-line clipping and ellipsis,
baseline, paragraph spacing, and letter spacing. Add in-place Sprite source replacement,
material-only Sprite initialization, atlas-batched SlicedSprite, four-state UiButton, and
ImageGen-authored responsive text/nine-slice examples for WebGL 2 and WebGPU.sortingLayer and zIndex for Sprite/Text2D display order, retain stable
scene-tree order for ties, make pointer picking select the same topmost 2D node, and restrict
transparent instancing to adjacent compatible items so batching cannot reorder interleaved
textures. Document the independent top-left Camera2D and centered Sprite-anchor contracts, and add
an ImageGen-authored pixel-town example with A* walking, click-to-route interaction, and foot-Y
ordering across both backends.SpriteFrame's top-left atlas-row offset for flipY textures on both backends. Full
textures were unaffected, but subframes previously selected the vertically opposite source row,
swapping nine-slice top/bottom pieces and requiring reversed character-direction maps. Use a
strictly nine-slice-safe postal UI atlas with uniform stretchable edges and deterministically
mirrored corners/edge lighting.Renderer. Create every
backend through await Renderer.create(...); direct new Renderer() and new Stage()
construction are unavailable so initialization always has one explicit asynchronous boundary.WebGLRenderer, WebGPURenderer, WebGLRenderTarget, and WebGPURenderTarget
classes and their backend-specific parameter and lifecycle types. The sole offscreen surface
remains the backend-neutral RenderTarget returned by Renderer.Renderer.isBackendSupported('webgpu', options).
Explicit backend requests remain fail-closed; auto still probes WebGPU without requesting a
device or allocating GPU resources.src/render and the RHI to src/render/rhi/{webgl2,webgpu}. Remove
the legacy src/renderer and src/rhi source trees and do not provide compatibility re-export
paths.build-hilo3d-games Agent Skill with strict TypeScript/Vite starters for 2D, 3D,
and hybrid games, stable-first 2.0.0 dependency resolution, focused public-API references, and
repository checks that keep bundled examples and version-selection behavior valid.npm run release:check retains the
complete validation matrix, while prepublishOnly performs only fast deterministic checks before
prepack builds the tarball, avoiding repeated browser suites and expired publish OTPs.Sprite, SpriteFrame sequence animation,
Canvas-2D-backed Text2D, pixel-space Camera2D, actual-size sprite pointer hit tests, and
automatic portable instance batches capped at 128 sprites per draw. Sprite raster uses one GLSL ES
3.00 source through native WebGL 2 or the existing Naga WGSL pipeline.Camera.priority, per-camera color/depth/
stencil clear policy, and Camera.visibility & Node.layer filtering for Mesh, Light, scriptable
culling, and pointer input. All cameras record into one Render Graph/RHI frame; Camera2D defaults
to the dedicated 2D layer and preserves prior 3D color.RendererCommonOptions.renderPipeline,
reusable RenderPipelineFactory configurations, frame-scoped culling/renderer-list handles, a
narrow ScriptableRenderGraph, retained pass-parameter pools, recovery-aware persistent targets,
and shared scene, shadow, fullscreen, copy, and present pass primitives.ForwardRenderPipelineFactory feature injection with per-Renderer feature runtimes and
creation-time capability/limit/format requirements. The empty default feature set retains the
existing direct forward recorder with no intermediate scene target or public-facade draw cost.
WebGPU-only storage-buffer, storage-texture, compute-pass, and indirect-draw requirements
now participate in backend selection and device capability/limit/format validation.StorageLayout, renderer-owned StorageBuffer upload/readback/recovery semantics, public graph
buffer access, Direct WGSL ComputeShader validation through Naga, immutable ComputeKernel,
ComputeRenderPass, and uniform/storage/complete-2D sampled or write-only-storage-texture
bindings. Compute is a dedicated pass model rather than a Material subtype.GPUDrivenRenderPass, and
SceneRenderPass group-3 pass-global storage variants. Scene variants reuse ordinary renderer
lists and deterministically expand instanced batches to direct per-mesh draws.StorageBuffer objects
imported per frame; each Renderer accepts one pending storage-buffer readback. cpu-shadow
recovery restores CPU bytes rather than later GPU mutations, and Direct WGSL f16 remains
fail-closed until the Naga validation path can validate it end to end. Storage-aware graphics
retains broader Material/Scene texture reflection, while GPUDrivenRenderPass validates explicit
graph view dimension, format, and sample type before backend execution.sampledDepth
option fail-closed; a custom SRP can explicitly compose depth prepass, compute culling, and a
storage-aware Scene pass for Forward+.Renderer.waitForIdle() for application completion fences. Native WebGL 2 or
WebGPU interoperability is opt-in through Renderer.getExtension() instead of public gl or
gpuDevice fields.renderToTarget() through the configured pipeline, make public graph handles unique across
invocations, reject nested rendering through record/prepare/execute, add transactional per-key
persistent-target release, preserve pre-draw Mesh event mutation before draw preparation, and
align after-scene events/face counts with every renderer-list occurrence actually drawn by live
graph passes.RHIFactory composition root for concrete RHI construction and support probes;
backend drivers receive the concrete RHI directly rather than a command-forwarding facade.waitForIdle() observes new
failures without hiding tracker/collection errors.validate:ci; the
physical-GPU lane remains a separate manual workflow.Renderer export with an abstract shared renderer base and a
separate RendererContract type. Backend implementations now inherit common frame planning,
render/light queues, diagnostics, and resource ownership from that base; the protected result is
available as the exported RenderGraphFramePlan type for custom subclasses.Renderer.renderFrame(callback) application-frame boundary. Custom
renderer implementations must provide it; callbacks may not return a Promise or retain the frame
facade after returning.UniformBuffer a backend-neutral CPU/std140 object. Remove its WebGL-native getBuffer(),
bind(), and destroy() methods; native allocations now belong to renderer-local WebGL/WebGPU
managers and are released through renderer resource ownership.Texture a backend-neutral CPU descriptor. Remove Texture.getCache(), reset(),
getGLTexture(), setGLTexture(), updateTexture(), the protected WebGL upload hooks, and the
root TextureWebGLState type; WebGL allocation, upload revision, descriptor snapshot, and native
cache ownership now belong to the renderer's texture manager/uploader.TextureBinding and MaterialTexture to engine Texture<unknown> objects so both
backends consume one real resource contract. Remove the WebGL-native location, type, size,
and glTypeInfo fields from ProgramBindingInfo.Shader.reset(gl?) to backend-independent Shader.reset(). Change RendererFrameCallback
to return unknown; the runtime rejects Promise-like results and escaped frame facades rather
than allowing asynchronous recording.GeometryData.glBuffer field. Geometry data now exposes only CPU
content/revisions, while each backend owns its buffer variants.WebGPUTextureManager mutations now preserve render-target ownership;
registerExternal() rejects target-owned textures instead of creating detached allocations.Class.create/Class.mix and EventMixin APIs in favor of native classes and
EventDispatcher; use backend-neutral releaseGPUResources() for renderer resource lifecycles.Stage.create() to default to backend: 'auto'. Auto selection uses the
public, device- and GPU-resource-free WebGPURenderer.isSupported() adapter probe and prefers
WebGPU when the fallback-adapter policy, required features/limits, and engine minimum limits are
satisfied; it otherwise creates WebGL 2 directly. The probe never requests a device or canvas
context and never initializes the shader compiler, pipelines, or resources. Supplying
preserveDrawingBuffer or requesting alpha: true, premultipliedAlpha: false straight-alpha
compositing selects WebGL 2 directly. Synchronous new Stage() remains WebGL 2 by default because
it cannot await adapter discovery.backend: 'webgpu' fail-closed with no fallback. Once auto has selected WebGPU,
device/context creation, compiler, pipeline, and resource initialization errors also reject
directly instead of being reinterpreted as capability failures.Renderer/RenderTarget the backend-neutral offscreen contract for WebGL 2 and WebGPU,
including MRT, 1×/4× MSAA, sampleable attachments, target rendering, resize, and asynchronous
readback. MeshPicker now accepts a Stage and returns Promise<Mesh[]> from a backend-neutral
GPU object-ID pass with no CPU fallback.Framebuffer, LightShadow, and CubeLightShadow types, public light
lightShadow fields, renderer-owned useFramebuffer/framebufferOption, implicit render-target
creation, and backend-specific framebuffer example. Native framebuffer and shadow allocation are
renderer internals; the replacement example uses the shared RenderTarget contract.logGLResource() export. Use
renderer.resourceManager.getDiagnostics(rootNode?) for stable backend-neutral ownership counts.capabilities and extensions singletons. WebGL 2 callers use the
owning WebGLRenderer.capabilities and WebGLRenderer.extensions; remaining public low-level
Program/Buffer/VAO cache inspection requires getCache(gl), while Texture native caches are
backend-private.ShadowCastingLightParameters. Area, ambient, and base lights reject shadow configuration before
backend selection instead of allowing a backend to ignore it.WebGPUTextureManager construction to receive an already initialized
NagaShaderTranslator; the optional resource-destroy callback moves to the third argument.KTXLoadRequest texture overrides to the exported KTXTextureOptions contract. Callers
may set sampler, lifecycle, name, UV, and anisotropy options, but container-owned texel format,
extent, image, mipmap, and compression metadata can no longer be overridden.FrameBlock, CameraBlock, SceneBlock,
LightBlock, MaterialBlock, ModelBlock, GeometryBlock, SkinningBlock, or MorphBlock
ABI. Custom ShaderMaterial numeric uniforms must migrate to a registered UBO; samplers are the
only classic uniform exception.KHR_techniques_webgl loading and its GLSL 1.00 sample assets because the extension's
arbitrary classic-uniform shader interface is incompatible with the fixed WebGL 2 UBO ABI.Texture.colorSpaceConversion boolean. External images now always use
the browser-standard sRGB-managed path, while raw TypedArray/DataView pixels remain explicit
untagged values on both backends.Texture.updateSubTexture(xOffset, yOffset, image) with the sole descriptor form
updateSubTexture({ mipLevel, face?, layer?, z?, x, y, width, height, depth?, image }). The
positional overload has been removed.SkinedMesh is now SkinnedMesh, needBasicUnifroms is
needBasicUniforms, ignoreTranparent is ignoreTransparent, and the
diffuse-environment/ambient-light material flag now uses its correctly spelled name.renderer/common, renderer/shader, renderer/webgl,
renderer/webgpu, rhi/webgl, and rhi/webgpu boundaries. Move GLSL-to-WGSL compilation above
the RHI, move WebGL shadow allocation under its renderer backend, and keep common frame planning
free of native graphics handles.webxr.html is explicitly WebGL 2-only while
browsers expose XR presentation through XRWebGLLayer, and compute_gpu_driven.html is
explicitly WebGPU-only because its required capabilities are not simulated on WebGL 2.OES_standard_derivatives and WEBGL_depth_texture requests because both are
WebGL 2 core features, and enforce this class of WebGL 1 extension wrapper in the modernity gate.@compute structurally associated with ComputeShader validation.@align/@size wrappers that work
with WebGPU's default language features; do not request or depend on the optional
uniform_buffer_standard_layout feature.sampler3D,
sampler2DArray, sampler2DArrayShadow, and every signed/unsigned integer sampler family for 2D,
3D, cube, and 2D-array textures now pass through Naga into dimension- and sample-type-correct bind
groups. Managed Texture supports 2D, cube, 3D, and 2D-array targets plus signed/unsigned integer
formats. Integer textures require nearest-only sampling, anisotropy 1, and explicit complete mip
chains; mipmapped 3D textures also require explicit complete chains. Both backends reject
compressed 3D textures before allocation, while native compressed 2D-array textures remain
supported.texture_depth_*; WebGPU enforces nearest-only non-filtering depth samplers, while WebGL 2
selects comparison mode from reflected sampler types.+X, -X, +Y, -Y, +Z, -Z order; add portable raw
depth16/depth32float and feature-gated depth32float-stencil8 uploads; reject nonportable raw depth
tuples before allocation; and use physical 4×4 upload extents for compressed 2×2/1×1 mip tails.Texture.needDestroy invalidates old allocations across every WebGL context and
WebGPU device instead of being consumed by only the first backend.MaterialBlock changes from a reusable snapshot of the final std140 bytes, including
direct mutations of nested color/matrix and texture-derived values, without requiring manual
isDirty; unchanged bytes do not advance revisions or upload again.flipY to TypedArray/DataView sources in the same deterministic byte order.HTMLVideoElement textures from decoded-frame callbacks through a private staging
canvas. Queue completion fences prevent the canvas from changing during a copy; source changes,
release, and device recovery cancel and rebuild observation without a WebGL or placeholder
fallback.mesh → pass owner → material/shader/instancing variant, cap each mesh at 32 variants
with LRU eviction, atomically union resources across passes, and reclaim failed-frame and replaced
identity resources without destroying shared final references.commonOptions
snapshots in every header and shader-variant key.webgpuDeviceLost, safely skip renders,
request a fresh equivalent adapter with the frozen initial options, revalidate the fallback policy
plus all required features and limits, and request a replacement device with the same effective
descriptor. Rebuild context/managers while preserving selected RenderTarget and attachment
identities, then emit webgpuDeviceRestored. Emit webgpuDeviceRecoveryFailed and make later
renders throw explicitly on failure; renderer destruction cancels in-flight or stale-generation
recovery.Texture-identity recovery backings for isImageCanRelease textures,
including immutable raw/cube/mipmap/sub-texture snapshots and private external-source references,
so a new WebGL 2 context allocation or WebGPU device can replay uploads without restoring access
to the released public image.releaseGPUResources() reusable on WebGPU by rebuilding main-canvas depth/MSAA attachments
immediately instead of tearing down the device. Scope shadow cameras and debug helpers per
renderer/light and prune them when debug, shadow, enabled, stage membership, release, recovery, or
destruction changes ownership.Texture identities survive resize and context/device recovery; WebGL 2
resize updates every draw/resolve/depth attachment transactionally. Both backends present through
fullscreen texture-load pipelines; WebGL 2 restores canvas and saved framebuffer state on every
clear/resolve failure instead of blitting into an antialiased default framebuffer. WebGPU keeps
its required 256-byte row alignment internal to the implementation.MeshPicker exclusively on the shared
render-target contract, with dual-backend interaction tests and no hidden fallback path.LINE_LOOP and TRIANGLE_FAN to explicit LINES and TRIANGLES indices before upload
for indexed, non-indexed, and glTF-loaded geometry, so WebGL 2 and WebGPU consume the same
topology.InstanceBlock instead of matrix vertex attributes.RenderTarget identity, and exact pre/post-recovery readback. It supplements the full
example-gallery WebGPU matrix; it is not the only WebGPU UI path.[64, 128, 200, 255] pixel readback.GPUQueue with onSubmittedWorkDone() before the
final instrumentation sample so delayed validation events cannot arrive after a passing result.
Interaction gates additionally require action-local draw/submit progress and GPU readback changes
for life-game attachment updates, ShaderToy pointer input, post-process kernels, and glTF Viewer
replacement. WebGPU color render-target allocations include COPY_DST, so public attachment
updateSubTexture() writes are real GPU updates rather than ignored validation errors.forceFallbackAdapter: false, disables Chromium's software rasterizer, rejects fallback
and known software adapters, and reuses the production draw/recovery/readback fixture without
pretending that physical GPU availability is a portable PR or release requirement. WebXR remains
excluded from the WebGPU gate.ivec*/uvec* inputs through strictly typed
vertexAttribIPointer calls. Keep point-shadow cube attachments square and complete. Refresh
CameraBlock for each of the six point-shadow faces even though the shadow camera object is
reused. Prepare ShaderToy derivatives in uniform control flow so the same GLSL compiles cleanly
through Naga and Dawn.LightBlock. Restrict shadow parameters to those three
light kinds and reject Area/Ambient/base-light shadow assignment before backend selection.COPY_WRITE_BUFFER_BINDING WebGL2 constant.