您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
全栈WebGL性能优化(含WASM加速、智能LOD、动态批处理)
当前为
// ==UserScript== // @name WebGL (Shaders优化工具) // @namespace http://tampermonkey.net/ // @version 3.0.0 // @description 全栈WebGL性能优化(含WASM加速、智能LOD、动态批处理) // @author KiwiFruit // @match *://*/* // @license MIT // @grant GM.addStyle // @grant GM.getValue // @grant GM.setValue // @grant GM.getResourceUrl // @grant GM.xmlHttpRequest // @connect wasm-optimizer.example.com // @resource APIKEY https://yourdomain.com/apikey.txt // @resource optimizer.wasm https://wasm-optimizer.example.com/optimizer.wasm // ==/UserScript== (function() { 'use strict'; /* global GLTFLoader,CryptoJS */ // 核心依赖类(本地实现) class OctreeNode { constructor(nodes, bounds) { this.nodes = nodes || []; this.bounds = bounds || { x: 0, y: 0, z: 0, size: 1 }; this.children = new Array(8).fill(null); } insert(item) { if (!this.bounds.contains(item.position)) return false; if (this.nodes.length < 8) { this.nodes.push(item); return true; } if (!this.children[0]) this.subdivide(); return this.children.some(child => child.insert(item)); } subdivide() { const half = this.bounds.size / 2; const corners = [ { x: -1, y: -1, z: -1 }, { x: 1, y: -1, z: -1 }, { x: -1, y: 1, z: -1 }, { x: 1, y: 1, z: -1 }, { x: -1, y: -1, z: 1 }, { x: 1, y: -1, z: 1 }, { x: -1, y: 1, z: 1 }, { x: 1, y: 1, z: 1 } ]; corners.forEach((corner, index) => { const bounds = { x: this.bounds.x + corner.x * half, y: this.bounds.y + corner.y * half, z: this.bounds.z + corner.z * half, size: half }; this.children[index] = new OctreeNode([], bounds); }); } } class DynamicBatcher { constructor(config) { this.config = { maxBatches: config.maxBatches || 32, maxVertices: config.maxVertices || 65536, ...config }; this.batches = new Map(); this.currentBatch = null; } createBatch(materialId) { const batch = { materialId, vertices: [], indices: [], buffer: null, timestamp: Date.now() }; this.batches.set(materialId, batch); return batch; } addMesh(mesh) { const batch = this.batches.get(mesh.material.id) || this.createBatch(mesh.material.id); batch.vertices.push(...mesh.vertices); batch.indices.push(...mesh.indices); if (batch.vertices.length > this.config.maxVertices) { this.flushBatch(batch); } return batch; } flushBatch(batch) { if (!batch.vertices.length) return; // WebGL缓冲区创建逻辑(省略具体实现) batch.buffer = this.createWebGLBuffer(batch.vertices, batch.indices); batch.vertices = []; batch.indices = []; } } // 主优化器类 class WebGLOptimizer { constructor() { this.glContext = null; this.wasmModule = null; this.resourceLoader = null; this.performanceMonitor = null; this.resourceCache = new Map(); this.errorHandlers = []; this.recoveryTasks = []; this.initState = 'pending'; } // 资源加载器 async initResourceLoader() { this.resourceLoader = { loadTexture: async (url) => { try { const response = await GM.xmlHttpRequest({ method: 'GET', url, responseType: 'arraybuffer' }); return new Uint8Array(response.response); } catch (error) { this.handleError('resourceLoader', error); return null; } }, loadModel: async (url) => { const gltfLoader = new GLTFLoader(); const model = await gltfLoader.load(url); return this.optimizeModel(model); } }; } // 性能监控器 initPerformanceMonitor() { this.performanceMonitor = { fps: 0, memoryUsage: 0, frameTimes: [], start: performance.now(), update: () => { const now = performance.now(); const delta = now - this.start; this.fps = Math.round(1000 / delta); this.start = now; this.frameTimes.push(delta); if (this.frameTimes.length > 60) this.frameTimes.shift(); this.memoryUsage = performance.memory.usedJSHeapSize; }, getStats: () => ({ fps: this.fps, avgFrameTime: this.frameTimes.reduce((a, b) => a + b, 0) / this.frameTimes.length, memoryUsage: this.memoryUsage }) }; setInterval(() => this.performanceMonitor.update(), 16); } // 核心优化方法 async optimizeScene(scene) { try { // 1. 资源预处理 const optimizedResources = await Promise.all( scene.resources.map(async res => ({ ...res, data: await this.resourceLoader.loadTexture(res.url) })) ); // 2. 空间分割 const octree = new OctreeNode(); scene.meshes.forEach(mesh => octree.insert(mesh)); // 3. 动态批处理 const batcher = new DynamicBatcher({ maxBatches: 64 }); const batches = scene.meshes.map(mesh => batcher.addMesh(mesh)); // 4. 着色器优化 const optimizedShaders = await this.wasmModule.optimizeShaders({ vertex: scene.shader.vertex, fragment: scene.shader.fragment }); // 5. 渲染管线配置 const program = this.glContext.createProgram(); optimizedShaders.uniforms.forEach(uniform => { this.glContext.uniformBlockBinding( program, this.glContext.getUniformBlockIndex(program, uniform.name), uniform.binding ); }); return { optimizedResources, octree, batches, program, stats: this.performanceMonitor.getStats() }; } catch (error) { this.handleError('optimizeScene', error); return null; } } // 错误处理系统 handleError(stage, error) { const severity = this.getErrorSeverity(error); const context = { stage, error: { message: error.message, stack: error.stack, code: error.code || 'UNKNOWN' }, timestamp: Date.now(), context: { glContext: this.glContext, wasmModule: this.wasmModule, performance: this.performanceMonitor.getStats() } }; // 触发错误处理链 this.errorHandlers.forEach(handler => handler(context)); // 根据严重程度采取行动 switch(severity) { case 'critical': this.recoverFromCriticalError(context); break; case 'severe': this.scheduleRecoveryTask(context); break; case 'warning': this.logWarning(context); break; } } // 资源管理 async loadWASM() { try { const wasmBinary = await GM.getResourceText('optimizer.wasm'); const module = await WebAssembly.instantiate( new Uint8Array(wasmBinary), { env: { memory: new WebAssembly.Memory({ initial: 256 }), abort: (msg, file) => this.handleError('wasm', new Error(`WASM Abort: ${msg}`)) } } ); this.wasmModule = module.instance.exports; return true; } catch (error) { this.handleError('wasmLoader', error); return false; } } // 初始化流程 async init() { this.initState = 'initializing'; try { // 阶段1: 环境准备 const context = await this.createWebGLContext(); this.glContext = context; // 阶段2: 资源加载 await this.loadWASM(); await this.initResourceLoader(); // 阶段3: 系统初始化 this.initPerformanceMonitor(); this.setupEventHandlers(); this.initSecurity(); // 阶段4: 首次渲染 const sampleScene = await this.loadSampleScene(); this.optimizeScene(sampleScene); this.initState = 'ready'; return true; } catch (error) { this.handleError('init', error); return false; } finally { this.initState = 'initialized'; } } // 安全机制 initSecurity() { // CSP策略 GM.addStyle(` #webgl-optimizer-container { display: none !important; visibility: hidden !important; } `); // 防注入检测 const allowedDomains = ['yourdomain.com', 'wasm-optimizer.example.com']; if (!allowedDomains.some(domain => window.location.hostname.includes(domain))) { throw new Error('Domain not authorized'); } // 定期安全检查 setInterval(() => { if (!this.wasmModule || !this.glContext) { this.handleError('security', new Error('Core components missing')); } }, 60000); } // 资源释放 releaseResources() { if (this.glContext) { this.glContext.deleteProgram(this.glContext.currentProgram); this.glContext.currentProgram = null; } if (this.wasmModule) { this.wasmModule = null; // 手动释放WASM内存 const memory = this.wasmModule.env.memory; new Uint8Array(memory.buffer, 0, memory.buffer.byteLength).fill(0); } this.resourceCache.clear(); this.recoveryTasks = []; this.errorHandlers = []; } // 自动恢复 async recoverFromCriticalError(context) { try { await this.releaseResources(); await this.init(); return true; } catch (recoveryError) { this.handleError('recovery', recoveryError); return false; } } // 事件处理 setupEventHandlers() { window.addEventListener('resize', () => { if (this.glContext) { const canvas = this.glContext.canvas; canvas.width = canvas.clientWidth; canvas.height = canvas.clientHeight; this.glContext.viewport(0, 0, canvas.width, canvas.height); } }); window.addEventListener('beforeunload', () => { this.releaseResources(); }); } // 工具方法 getErrorSeverity(error) { if (error.message.includes('out of memory')) return 'critical'; if (error.code === 'MODULE_NOT_FOUND') return 'severe'; return 'warning'; } // 核心WebGL上下文创建 async createWebGLContext() { const canvas = document.createElement('canvas'); canvas.style.display = 'block'; document.body.appendChild(canvas); const contextAttributes = { antialias: true, depth: true, stencil: true, premultipliedAlpha: true, preserveDrawingBuffer: false, powerPreference: 'high-performance', failIfMajorPerformanceCaveat: true, alpha: false, version: 2, extensions: ['EXT_color_buffer_float'] }; const gl = canvas.getContext('webgl2', contextAttributes); if (!gl) throw new Error('WebGL2 context creation failed'); // 初始化GL状态 gl.enable(gl.DEPTH_TEST); gl.depthFunc(gl.LEQUAL); gl.clearColor(0.0, 0.0, 0.0, 1.0); gl.clearDepth(1.0); return { gl, canvas }; } // 示例场景加载 async loadSampleScene() { try { const response = await GM.xmlHttpRequest({ method: 'GET', url: '/samplescene.json', headers: { 'Authorization': `Bearer ${this.getSecureAPIKey()}` } }); return JSON.parse(response.responseText); } catch (error) { this.handleError('sampleScene', error); return null; } } // 安全API密钥获取 getSecureAPIKey() { const encryptedKey = GM.getValue('APIKEY', ''); if (!encryptedKey) throw new Error('API key not initialized'); return CryptoJS.AES.decrypt(encryptedKey, this.generateKeySalt()).toString(CryptoJS.enc.Utf8); } generateKeySalt() { return CryptoJS.lib.WordArray.random(16).toString(); } } // 全局初始化 const optimizer = new WebGLOptimizer(); optimizer.errorHandlers.push({ handle: (context) => { console.error(`[${context.stage}] Error: ${context.error.message}`); if (context.stage === 'init' && context.error.code === 'MODULE_NOT_FOUND') { window.location.reload(); } } }); // 异步初始化 (async () => { try { await optimizer.init(); console.log('WebGLOptimizer initialized successfully'); optimizer.startPerformanceReporting(); } catch (error) { console.error('Critical initialization failure:', error); optimizer.handleError('global', error); } })(); // 性能报告 WebGLOptimizer.prototype.startPerformanceReporting = function() { setInterval(() => { const stats = this.performanceMonitor.getStats(); GM.setValue('performanceStats', stats); console.log('Performance stats:', stats); }, 5000); }; })();