webgl
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseWebGL Development Skill
WebGL开发技能
File Organization: This skill uses split structure. Seefor advanced patterns and security examples.references/
文件结构:本技能采用拆分式结构。高级模式与安全示例请查看目录。references/
1. Overview
1. 概述
This skill provides WebGL expertise for creating custom shaders and visual effects in the JARVIS AI Assistant HUD. It focuses on GPU-accelerated rendering with security considerations.
Risk Level: MEDIUM - Direct GPU access, potential for resource exhaustion, driver vulnerabilities
Primary Use Cases:
- Custom shaders for holographic effects
- Post-processing effects (bloom, glitch)
- Particle systems with compute shaders
- Real-time data visualization
本技能为JARVIS AI助手HUD提供WebGL专业能力,用于创建自定义着色器与视觉特效。重点关注带有安全考量的GPU加速渲染。
风险等级:中等 - 直接访问GPU,存在资源耗尽、驱动漏洞风险
主要使用场景:
- 用于全息效果的自定义着色器
- 后期处理特效(bloom、故障效果)
- 带有计算着色器的粒子系统
- 实时数据可视化
2. Core Responsibilities
2. 核心职责
2.1 Fundamental Principles
2.1 基本原则
- TDD First: Write tests before implementation - test shaders, contexts, and resources
- Performance Aware: Optimize GPU usage - batch draws, reuse buffers, compress textures
- GPU Safety: Implement timeout mechanisms and resource limits
- Shader Validation: Validate all shader inputs before compilation
- Context Management: Handle context loss gracefully
- Performance Budgets: Set strict limits on draw calls and triangles
- Fallback Strategy: Provide non-WebGL fallbacks
- Memory Management: Track and limit texture/buffer usage
- 优先TDD:在实现前编写测试 - 测试着色器、上下文与资源
- 性能感知:优化GPU使用率 - 批量绘制、复用缓冲区、压缩纹理
- GPU安全:实现超时机制与资源限制
- 着色器验证:编译前验证所有着色器输入
- 上下文管理:优雅处理上下文丢失情况
- 性能预算:为绘制调用与三角形数量设置严格限制
- 降级策略:提供非WebGL替代方案
- 内存管理:跟踪并限制纹理/缓冲区使用
3. Technology Stack & Versions
3. 技术栈与版本
3.1 Browser Support
3.1 浏览器支持
| Browser | WebGL 2.0 | Notes |
|---|---|---|
| Chrome | 56+ | Full support |
| Firefox | 51+ | Full support |
| Safari | 15+ | WebGL 2.0 support |
| Edge | 79+ | Chromium-based |
| 浏览器 | WebGL 2.0 | 说明 |
|---|---|---|
| Chrome | 56+ | 完全支持 |
| Firefox | 51+ | 完全支持 |
| Safari | 15+ | 支持WebGL 2.0 |
| Edge | 79+ | 基于Chromium内核 |
3.2 Security Considerations
3.2 安全考量
typescript
// Check WebGL support and capabilities
function getWebGLContext(canvas: HTMLCanvasElement): WebGL2RenderingContext | null {
const gl = canvas.getContext('webgl2', {
alpha: true,
antialias: true,
powerPreference: 'high-performance',
failIfMajorPerformanceCaveat: true // Fail if software rendering
})
if (!gl) {
console.warn('WebGL 2.0 not supported')
return null
}
return gl
}typescript
// Check WebGL support and capabilities
function getWebGLContext(canvas: HTMLCanvasElement): WebGL2RenderingContext | null {
const gl = canvas.getContext('webgl2', {
alpha: true,
antialias: true,
powerPreference: 'high-performance',
failIfMajorPerformanceCaveat: true // Fail if software rendering
})
if (!gl) {
console.warn('WebGL 2.0 not supported')
return null
}
return gl
}4. Implementation Patterns
4. 实现模式
4.1 Safe Shader Compilation
4.1 安全着色器编译
typescript
// utils/shaderUtils.ts
// ✅ Safe shader compilation with error handling
export function compileShader(
gl: WebGL2RenderingContext,
source: string,
type: number
): WebGLShader | null {
const shader = gl.createShader(type)
if (!shader) return null
gl.shaderSource(shader, source)
gl.compileShader(shader)
if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
const error = gl.getShaderInfoLog(shader)
console.error('Shader compilation error:', error)
gl.deleteShader(shader)
return null
}
return shader
}
// ✅ Safe program linking
export function createProgram(
gl: WebGL2RenderingContext,
vertexShader: WebGLShader,
fragmentShader: WebGLShader
): WebGLProgram | null {
const program = gl.createProgram()
if (!program) return null
gl.attachShader(program, vertexShader)
gl.attachShader(program, fragmentShader)
gl.linkProgram(program)
if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
const error = gl.getProgramInfoLog(program)
console.error('Program linking error:', error)
gl.deleteProgram(program)
return null
}
return program
}typescript
// utils/shaderUtils.ts
// ✅ Safe shader compilation with error handling
export function compileShader(
gl: WebGL2RenderingContext,
source: string,
type: number
): WebGLShader | null {
const shader = gl.createShader(type)
if (!shader) return null
gl.shaderSource(shader, source)
gl.compileShader(shader)
if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
const error = gl.getShaderInfoLog(shader)
console.error('Shader compilation error:', error)
gl.deleteShader(shader)
return null
}
return shader
}
// ✅ Safe program linking
export function createProgram(
gl: WebGL2RenderingContext,
vertexShader: WebGLShader,
fragmentShader: WebGLShader
): WebGLProgram | null {
const program = gl.createProgram()
if (!program) return null
gl.attachShader(program, vertexShader)
gl.attachShader(program, fragmentShader)
gl.linkProgram(program)
if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
const error = gl.getProgramInfoLog(program)
console.error('Program linking error:', error)
gl.deleteProgram(program)
return null
}
return program
}4.2 Context Loss Handling
4.2 上下文丢失处理
typescript
// composables/useWebGL.ts
export function useWebGL(canvas: Ref<HTMLCanvasElement | null>) {
const gl = ref<WebGL2RenderingContext | null>(null)
const contextLost = ref(false)
onMounted(() => {
if (!canvas.value) return
// ✅ Handle context loss
canvas.value.addEventListener('webglcontextlost', (e) => {
e.preventDefault()
contextLost.value = true
console.warn('WebGL context lost')
})
canvas.value.addEventListener('webglcontextrestored', () => {
contextLost.value = false
initializeGL()
console.info('WebGL context restored')
})
initializeGL()
})
function initializeGL() {
gl.value = getWebGLContext(canvas.value!)
// Reinitialize all resources
}
return { gl, contextLost }
}typescript
// composables/useWebGL.ts
export function useWebGL(canvas: Ref<HTMLCanvasElement | null>) {
const gl = ref<WebGL2RenderingContext | null>(null)
const contextLost = ref(false)
onMounted(() => {
if (!canvas.value) return
// ✅ Handle context loss
canvas.value.addEventListener('webglcontextlost', (e) => {
e.preventDefault()
contextLost.value = true
console.warn('WebGL context lost')
})
canvas.value.addEventListener('webglcontextrestored', () => {
contextLost.value = false
initializeGL()
console.info('WebGL context restored')
})
initializeGL()
})
function initializeGL() {
gl.value = getWebGLContext(canvas.value!)
// Reinitialize all resources
}
return { gl, contextLost }
}4.3 Holographic Shader
4.3 全息着色器
glsl
// shaders/holographic.frag
#version 300 es
precision highp float;
uniform float uTime;
uniform vec3 uColor;
uniform float uScanlineIntensity;
in vec2 vUv;
out vec4 fragColor;
void main() {
// Scanline effect
float scanline = sin(vUv.y * 200.0 + uTime * 2.0) * 0.5 + 0.5;
scanline = mix(1.0, scanline, uScanlineIntensity);
// Edge glow
float edge = smoothstep(0.0, 0.1, vUv.x) *
smoothstep(1.0, 0.9, vUv.x) *
smoothstep(0.0, 0.1, vUv.y) *
smoothstep(1.0, 0.9, vUv.y);
vec3 color = uColor * scanline * edge;
float alpha = edge * 0.8;
fragColor = vec4(color, alpha);
}glsl
// shaders/holographic.frag
#version 300 es
precision highp float;
uniform float uTime;
uniform vec3 uColor;
uniform float uScanlineIntensity;
in vec2 vUv;
out vec4 fragColor;
void main() {
// Scanline effect
float scanline = sin(vUv.y * 200.0 + uTime * 2.0) * 0.5 + 0.5;
scanline = mix(1.0, scanline, uScanlineIntensity);
// Edge glow
float edge = smoothstep(0.0, 0.1, vUv.x) *
smoothstep(1.0, 0.9, vUv.x) *
smoothstep(0.0, 0.1, vUv.y) *
smoothstep(1.0, 0.9, vUv.y);
vec3 color = uColor * scanline * edge;
float alpha = edge * 0.8;
fragColor = vec4(color, alpha);
}4.4 Resource Management
4.4 资源管理
typescript
// utils/resourceManager.ts
export class WebGLResourceManager {
private textures: Set<WebGLTexture> = new Set()
private buffers: Set<WebGLBuffer> = new Set()
private programs: Set<WebGLProgram> = new Set()
private textureMemory = 0
private readonly MAX_TEXTURE_MEMORY = 256 * 1024 * 1024 // 256MB
constructor(private gl: WebGL2RenderingContext) {}
createTexture(width: number, height: number): WebGLTexture | null {
const size = width * height * 4 // RGBA
// ✅ Enforce memory limits
if (this.textureMemory + size > this.MAX_TEXTURE_MEMORY) {
console.error('Texture memory limit exceeded')
return null
}
const texture = this.gl.createTexture()
if (texture) {
this.textures.add(texture)
this.textureMemory += size
}
return texture
}
dispose(): void {
this.textures.forEach(t => this.gl.deleteTexture(t))
this.buffers.forEach(b => this.gl.deleteBuffer(b))
this.programs.forEach(p => this.gl.deleteProgram(p))
this.textureMemory = 0
}
}typescript
// utils/resourceManager.ts
export class WebGLResourceManager {
private textures: Set<WebGLTexture> = new Set()
private buffers: Set<WebGLBuffer> = new Set()
private programs: Set<WebGLProgram> = new Set()
private textureMemory = 0
private readonly MAX_TEXTURE_MEMORY = 256 * 1024 * 1024 // 256MB
constructor(private gl: WebGL2RenderingContext) {}
createTexture(width: number, height: number): WebGLTexture | null {
const size = width * height * 4 // RGBA
// ✅ Enforce memory limits
if (this.textureMemory + size > this.MAX_TEXTURE_MEMORY) {
console.error('Texture memory limit exceeded')
return null
}
const texture = this.gl.createTexture()
if (texture) {
this.textures.add(texture)
this.textureMemory += size
}
return texture
}
dispose(): void {
this.textures.forEach(t => this.gl.deleteTexture(t))
this.buffers.forEach(b => this.gl.deleteBuffer(b))
this.programs.forEach(p => this.gl.deleteProgram(p))
this.textureMemory = 0
}
}4.5 Uniform Validation
4.5 统一变量验证
typescript
// ✅ Type-safe uniform setting
export function setUniforms(
gl: WebGL2RenderingContext,
program: WebGLProgram,
uniforms: Record<string, number | number[] | Float32Array>
): void {
for (const [name, value] of Object.entries(uniforms)) {
const location = gl.getUniformLocation(program, name)
if (!location) {
console.warn(`Uniform '${name}' not found`)
continue
}
if (typeof value === 'number') {
gl.uniform1f(location, value)
} else if (Array.isArray(value)) {
switch (value.length) {
case 2: gl.uniform2fv(location, value); break
case 3: gl.uniform3fv(location, value); break
case 4: gl.uniform4fv(location, value); break
case 16: gl.uniformMatrix4fv(location, false, value); break
}
}
}
}typescript
// ✅ Type-safe uniform setting
export function setUniforms(
gl: WebGL2RenderingContext,
program: WebGLProgram,
uniforms: Record<string, number | number[] | Float32Array>
): void {
for (const [name, value] of Object.entries(uniforms)) {
const location = gl.getUniformLocation(program, name)
if (!location) {
console.warn(`Uniform '${name}' not found`)
continue
}
if (typeof value === 'number') {
gl.uniform1f(location, value)
} else if (Array.isArray(value)) {
switch (value.length) {
case 2: gl.uniform2fv(location, value); break
case 3: gl.uniform3fv(location, value); break
case 4: gl.uniform4fv(location, value); break
case 16: gl.uniformMatrix4fv(location, false, value); break
}
}
}
}5. Implementation Workflow (TDD)
5. 实现工作流(TDD)
5.1 Step-by-Step Process
5.1 分步流程
- Write failing test -> 2. Implement minimum -> 3. Refactor -> 4. Verify
typescript
// Step 1: tests/webgl/shaderCompilation.test.ts
import { describe, it, expect, beforeEach } from 'vitest'
import { compileShader } from '@/utils/shaderUtils'
describe('WebGL Shader Compilation', () => {
let gl: WebGL2RenderingContext
beforeEach(() => {
gl = document.createElement('canvas').getContext('webgl2')!
})
it('should compile valid shader', () => {
const source = `#version 300 es
in vec4 aPosition;
void main() { gl_Position = aPosition; }`
expect(compileShader(gl, source, gl.VERTEX_SHADER)).not.toBeNull()
})
it('should return null for invalid shader', () => {
expect(compileShader(gl, 'invalid', gl.FRAGMENT_SHADER)).toBeNull()
})
})
// Step 2-3: Implement and refactor (see section 4.1)
// Step 4: npm test && npm run typecheck && npm run build- 编写失败测试 -> 2. 最小化实现 -> 3. 重构 -> 4. 验证
typescript
// Step 1: tests/webgl/shaderCompilation.test.ts
import { describe, it, expect, beforeEach } from 'vitest'
import { compileShader } from '@/utils/shaderUtils'
describe('WebGL Shader Compilation', () => {
let gl: WebGL2RenderingContext
beforeEach(() => {
gl = document.createElement('canvas').getContext('webgl2')!
})
it('should compile valid shader', () => {
const source = `#version 300 es
in vec4 aPosition;
void main() { gl_Position = aPosition; }`
expect(compileShader(gl, source, gl.VERTEX_SHADER)).not.toBeNull()
})
it('should return null for invalid shader', () => {
expect(compileShader(gl, 'invalid', gl.FRAGMENT_SHADER)).toBeNull()
})
})
// Step 2-3: Implement and refactor (see section 4.1)
// Step 4: npm test && npm run typecheck && npm run build5.2 Testing Context and Resources
5.2 上下文与资源测试
typescript
describe('WebGL Context', () => {
it('should handle context loss', async () => {
const { gl, contextLost } = useWebGL(ref(canvas))
gl.value?.getExtension('WEBGL_lose_context')?.loseContext()
await nextTick()
expect(contextLost.value).toBe(true)
})
})
describe('Resource Manager', () => {
it('should enforce memory limits', () => {
const manager = new WebGLResourceManager(gl)
expect(manager.createTexture(1024, 1024)).not.toBeNull()
expect(manager.createTexture(16384, 16384)).toBeNull() // Exceeds limit
})
})typescript
describe('WebGL Context', () => {
it('should handle context loss', async () => {
const { gl, contextLost } = useWebGL(ref(canvas))
gl.value?.getExtension('WEBGL_lose_context')?.loseContext()
await nextTick()
expect(contextLost.value).toBe(true)
})
})
describe('Resource Manager', () => {
it('should enforce memory limits', () => {
const manager = new WebGLResourceManager(gl)
expect(manager.createTexture(1024, 1024)).not.toBeNull()
expect(manager.createTexture(16384, 16384)).toBeNull() // Exceeds limit
})
})6. Performance Patterns
6. 性能模式
6.1 Buffer Reuse
6.1 缓冲区复用
typescript
// Bad - Creates new buffer every frame
const buffer = gl.createBuffer()
gl.bufferData(gl.ARRAY_BUFFER, data, gl.DYNAMIC_DRAW)
gl.deleteBuffer(buffer)
// Good - Reuse buffer, update only data
gl.bufferSubData(gl.ARRAY_BUFFER, 0, data) // Update existing buffertypescript
// Bad - Creates new buffer every frame
const buffer = gl.createBuffer()
gl.bufferData(gl.ARRAY_BUFFER, data, gl.DYNAMIC_DRAW)
gl.deleteBuffer(buffer)
// Good - Reuse buffer, update only data
gl.bufferSubData(gl.ARRAY_BUFFER, 0, data) // Update existing buffer6.2 Draw Call Batching
6.2 绘制调用批处理
typescript
// Bad - One draw call per object
objects.forEach(obj => {
gl.useProgram(obj.program)
gl.drawElements(...)
})
// Good - Batch by material/shader
const batches = groupByMaterial(objects)
batches.forEach(batch => {
gl.useProgram(batch.program)
batch.objects.forEach(obj => gl.drawElements(...))
})typescript
// Bad - One draw call per object
objects.forEach(obj => {
gl.useProgram(obj.program)
gl.drawElements(...)
})
// Good - Batch by material/shader
const batches = groupByMaterial(objects)
batches.forEach(batch => {
gl.useProgram(batch.program)
batch.objects.forEach(obj => gl.drawElements(...))
})6.3 Texture Compression
6.3 纹理压缩
typescript
// Bad - Always uncompressed RGBA
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image)
// Good - Use compressed formats when available
const ext = gl.getExtension('WEBGL_compressed_texture_s3tc')
if (ext) gl.compressedTexImage2D(gl.TEXTURE_2D, 0, ext.COMPRESSED_RGBA_S3TC_DXT5_EXT, ...)typescript
// Bad - Always uncompressed RGBA
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image)
// Good - Use compressed formats when available
const ext = gl.getExtension('WEBGL_compressed_texture_s3tc')
if (ext) gl.compressedTexImage2D(gl.TEXTURE_2D, 0, ext.COMPRESSED_RGBA_S3TC_DXT5_EXT, ...)6.4 Instanced Rendering
6.4 实例化渲染
typescript
// Bad - Individual draw calls for particles
particles.forEach(p => {
gl.uniform3fv(uPosition, p.position)
gl.drawArrays(gl.TRIANGLES, 0, 6)
})
// Good - Single instanced draw call
gl.drawArraysInstanced(gl.TRIANGLES, 0, 6, particles.length)typescript
// Bad - Individual draw calls for particles
particles.forEach(p => {
gl.uniform3fv(uPosition, p.position)
gl.drawArrays(gl.TRIANGLES, 0, 6)
})
// Good - Single instanced draw call
gl.drawArraysInstanced(gl.TRIANGLES, 0, 6, particles.length)6.5 VAO Usage
6.5 VAO使用
typescript
// Bad - Rebind attributes every frame
gl.enableVertexAttribArray(0)
gl.vertexAttribPointer(0, 3, gl.FLOAT, false, 0, 0)
// Good - Use VAO to store attribute state
const vao = gl.createVertexArray()
gl.bindVertexArray(vao)
// Set up once, then just bind VAO for renderingtypescript
// Bad - Rebind attributes every frame
gl.enableVertexAttribArray(0)
gl.vertexAttribPointer(0, 3, gl.FLOAT, false, 0, 0)
// Good - Use VAO to store attribute state
const vao = gl.createVertexArray()
gl.bindVertexArray(vao)
// Set up once, then just bind VAO for rendering7. Security Standards
7. 安全标准
7.1 Known Vulnerabilities
7.1 已知漏洞
| CVE | Severity | Description | Mitigation |
|---|---|---|---|
| CVE-2024-11691 | HIGH | Apple M series memory corruption | Update browser, OS patches |
| CVE-2023-1531 | HIGH | Chrome use-after-free | Update Chrome |
| CVE编号 | 严重程度 | 描述 | 缓解措施 |
|---|---|---|---|
| CVE-2024-11691 | 高 | Apple M系列内存损坏 | 更新浏览器、操作系统补丁 |
| CVE-2023-1531 | 高 | Chrome使用后释放漏洞 | 更新Chrome |
7.2 OWASP Top 10 Coverage
7.2 OWASP Top 10覆盖
| OWASP Category | Risk | Mitigation |
|---|---|---|
| A06 Vulnerable Components | HIGH | Keep browsers updated |
| A10 SSRF | LOW | Context isolation by browser |
| OWASP类别 | 风险 | 缓解措施 |
|---|---|---|
| A06 易受攻击的组件 | 高 | 保持浏览器更新 |
| A10 SSRF | 低 | 浏览器上下文隔离 |
7.3 GPU Resource Protection
7.3 GPU资源保护
typescript
// ✅ Implement resource limits
const LIMITS = {
maxDrawCalls: 100,
maxTriangles: 1_000_000,
maxTextures: 32,
maxTextureSize: 4096
}
function checkLimits(stats: RenderStats): boolean {
if (stats.drawCalls > LIMITS.maxDrawCalls) {
console.error('Draw call limit exceeded')
return false
}
if (stats.triangles > LIMITS.maxTriangles) {
console.error('Triangle limit exceeded')
return false
}
return true
}typescript
// ✅ Implement resource limits
const LIMITS = {
maxDrawCalls: 100,
maxTriangles: 1_000_000,
maxTextures: 32,
maxTextureSize: 4096
}
function checkLimits(stats: RenderStats): boolean {
if (stats.drawCalls > LIMITS.maxDrawCalls) {
console.error('Draw call limit exceeded')
return false
}
if (stats.triangles > LIMITS.maxTriangles) {
console.error('Triangle limit exceeded')
return false
}
return true
}8. Common Mistakes & Anti-Patterns
8. 常见错误与反模式
8.1 Critical Security Anti-Patterns
8.1 严重安全反模式
Never: Skip Context Loss Handling
禁止:跳过上下文丢失处理
typescript
// ❌ DANGEROUS - App crashes on context loss
const gl = canvas.getContext('webgl2')
// No context loss handler!
// ✅ SECURE - Handle gracefully
canvas.addEventListener('webglcontextlost', handleLoss)
canvas.addEventListener('webglcontextrestored', handleRestore)typescript
// ❌ DANGEROUS - App crashes on context loss
const gl = canvas.getContext('webgl2')
// No context loss handler!
// ✅ SECURE - Handle gracefully
canvas.addEventListener('webglcontextlost', handleLoss)
canvas.addEventListener('webglcontextrestored', handleRestore)Never: Unlimited Resource Allocation
禁止:无限制资源分配
typescript
// ❌ DANGEROUS - GPU memory exhaustion
for (let i = 0; i < userCount; i++) {
textures.push(gl.createTexture())
}
// ✅ SECURE - Enforce limits
if (textureCount < MAX_TEXTURES) {
textures.push(gl.createTexture())
}typescript
// ❌ DANGEROUS - GPU memory exhaustion
for (let i = 0; i < userCount; i++) {
textures.push(gl.createTexture())
}
// ✅ SECURE - Enforce limits
if (textureCount < MAX_TEXTURES) {
textures.push(gl.createTexture())
}8.2 Performance Anti-Patterns
8.2 性能反模式
Avoid: Excessive State Changes
避免:过度状态切换
typescript
// ❌ BAD - Unbatched draw calls
objects.forEach(obj => {
gl.useProgram(obj.program)
gl.bindTexture(gl.TEXTURE_2D, obj.texture)
gl.drawElements(...)
})
// ✅ GOOD - Batch by material
batches.forEach(batch => {
gl.useProgram(batch.program)
gl.bindTexture(gl.TEXTURE_2D, batch.texture)
batch.objects.forEach(obj => gl.drawElements(...))
})typescript
// ❌ BAD - Unbatched draw calls
objects.forEach(obj => {
gl.useProgram(obj.program)
gl.bindTexture(gl.TEXTURE_2D, obj.texture)
gl.drawElements(...)
})
// ✅ GOOD - Batch by material
batches.forEach(batch => {
gl.useProgram(batch.program)
gl.bindTexture(gl.TEXTURE_2D, batch.texture)
batch.objects.forEach(obj => gl.drawElements(...))
})9. Pre-Implementation Checklist
9. 预实现检查清单
Phase 1: Before Writing Code
阶段1:编写代码前
- Write failing tests for shaders, context, and resources
- Define performance budgets (draw calls <100, memory <256MB)
- Identify required WebGL extensions
- 为着色器、上下文与资源编写失败测试
- 定义性能预算(绘制调用<100,内存<256MB)
- 确定所需WebGL扩展
Phase 2: During Implementation
阶段2:实现过程中
- Context loss handling with recovery
- Resource limits and memory tracking
- Shader validation before compilation
- Use VAOs, batch draws, reuse buffers
- Instanced rendering for particles
- 带有恢复机制的上下文丢失处理
- 资源限制与内存跟踪
- 编译前的着色器验证
- 使用VAO、批量绘制、复用缓冲区
- 粒子系统的实例化渲染
Phase 3: Before Committing
阶段3:提交前
- Tests pass:
npm test -- --run tests/webgl/ - Type check:
npm run typecheck - Build:
npm run build - Performance verified (draws, memory)
- Fallback for no WebGL tested
- 测试通过:
npm test -- --run tests/webgl/ - 类型检查:
npm run typecheck - 构建:
npm run build - 性能验证(绘制调用、内存)
- 无WebGL环境的降级方案测试
10. Summary
10. 总结
WebGL provides GPU-accelerated graphics for JARVIS HUD. Key principles: handle context loss, enforce resource limits, validate shaders, track memory, batch draw calls, minimize state changes.
Remember: WebGL bypasses browser sandboxing - always protect against resource exhaustion.
References: ,
references/advanced-patterns.mdreferences/security-examples.mdWebGL为JARVIS HUD提供GPU加速图形能力。核心原则:处理上下文丢失、实施资源限制、验证着色器、跟踪内存、批量绘制调用、最小化状态切换。
注意:WebGL会绕过浏览器沙箱 - 始终防范资源耗尽风险。
参考文档:,
references/advanced-patterns.mdreferences/security-examples.md