mirror of
https://github.com/openfrontio/OpenFrontIO.git
synced 2026-06-25 02:22:46 +00:00
bcd1412f75
Refactor the monolithic TerritoryWebGLRenderer into a modular, extensible architecture that separates ground truth computation from rendering passes. This change also includes related improvements to game state management and hover information handling. WebGPU Architecture Refactor: - Extract all shaders to external .wgsl files (no inlined shaders) - Separate ground truth data management (GroundTruthData) from rendering - Create pass-based architecture with ComputePass and RenderPass interfaces - Implement compute passes: StateUpdatePass, DefendedClearPass, DefendedUpdatePass - Implement render pass: TerritoryRenderPass - Add TerritoryRenderer orchestrator with dependency-based execution ordering - Add WebGPUDevice for device initialization and management - Add ShaderLoader utility for loading .wgsl files via Vite ?raw imports Performance Optimizations: - Dependency order computed once at init (topological sort) - Early exit checks at orchestrator and pass levels - Bind groups rebuilt when textures/buffers are recreated - Zero per-frame allocations (reuse command encoders and staging buffers) Architecture Benefits: - Easy to extend with new compute/render passes (borders, temporal smoothing, etc.) - Clear separation between tick-based compute and frame-based rendering - All shaders in external files for better maintainability - Ground truth data computed once and reused by all passes Related Changes: - Add defended tile state support to GameMap (isDefended/setDefended) - Expose tileStateView() for direct GPU state access - Extract hover info logic to HoverInfo utility - Remove TerrainLayer (terrain now rendered by WebGPU territory pass) - Update GameRenderer to use transparent overlay canvas - Add viewOffset() method to TransformHandler Files: - Deleted: TerritoryWebGLRenderer.ts (1217 lines), TerrainLayer.ts (77 lines) - Added: 17 new files in webgpu/ directory structure - Updated: TerritoryLayer.ts, GameRenderer.ts, PlayerInfoOverlay.ts, GameMap.ts, GameView.ts, GameImpl.ts, TransformHandler.ts, vite-env.d.ts
67 lines
1.6 KiB
TypeScript
67 lines
1.6 KiB
TypeScript
/**
|
|
* Manages WebGPU device initialization and canvas context configuration.
|
|
*/
|
|
|
|
export class WebGPUDevice {
|
|
public readonly device: GPUDevice;
|
|
public readonly context: GPUCanvasContext;
|
|
public readonly canvasFormat: GPUTextureFormat;
|
|
|
|
private constructor(
|
|
device: GPUDevice,
|
|
context: GPUCanvasContext,
|
|
canvasFormat: GPUTextureFormat,
|
|
) {
|
|
this.device = device;
|
|
this.context = context;
|
|
this.canvasFormat = canvasFormat;
|
|
}
|
|
|
|
/**
|
|
* Initialize WebGPU device and canvas context.
|
|
* @param canvas Canvas element to configure
|
|
* @returns WebGPUDevice instance or null if WebGPU is not available
|
|
*/
|
|
static async create(canvas: HTMLCanvasElement): Promise<WebGPUDevice | null> {
|
|
const nav = globalThis.navigator as any;
|
|
if (!nav?.gpu || typeof nav.gpu.requestAdapter !== "function") {
|
|
return null;
|
|
}
|
|
|
|
const adapter = await nav.gpu.requestAdapter();
|
|
if (!adapter) {
|
|
return null;
|
|
}
|
|
|
|
const device = await adapter.requestDevice();
|
|
const context = canvas.getContext("webgpu");
|
|
if (!context) {
|
|
return null;
|
|
}
|
|
|
|
const canvasFormat =
|
|
typeof nav.gpu.getPreferredCanvasFormat === "function"
|
|
? nav.gpu.getPreferredCanvasFormat()
|
|
: "bgra8unorm";
|
|
|
|
context.configure({
|
|
device,
|
|
format: canvasFormat,
|
|
alphaMode: "opaque",
|
|
});
|
|
|
|
return new WebGPUDevice(device, context, canvasFormat);
|
|
}
|
|
|
|
/**
|
|
* Reconfigure the canvas context (e.g., when canvas size changes).
|
|
*/
|
|
reconfigure(): void {
|
|
this.context.configure({
|
|
device: this.device,
|
|
format: this.canvasFormat,
|
|
alphaMode: "opaque",
|
|
});
|
|
}
|
|
}
|