WebGL偶发仅渲染纯色不显示quad问题排查求助
WebGL偶发黑屏问题修复方案
核心问题排查
以下是导致你在webview中偶发黑屏、Chrome安卓端正常的根本原因:
- 冗余uniform变量触发严格模式错误
你的片元着色器中没有定义frame变量,调用gl.getUniformLocation(program, "frame")会返回null,后续渲染循环中反复调用gl.uniform1i(frameUniform, timeStamp)给空位置赋值,嵌入式webview的WebGL实现对这类错误处理更严格,会直接中断渲染流程,而Chrome浏览器对这类非致命错误做了兼容忽略,因此仅在webview中出现异常。 - 画布尺寸初始化时机不可靠
页面onload触发时部分webview还未完成布局计算,window.innerWidth/innerHeight可能返回0值,此时画布和视口尺寸为0,自然无法渲染出画面,就会出现偶发黑屏。 - 冗余深度测试配置(非强制,建议优化)
你的场景仅渲染一个全屏四边形,完全不需要深度测试,反复开启深度测试、清空深度缓冲属于冗余操作,可能触发部分老旧驱动的兼容问题。
修复代码
<html> <head> <title>WebGL</title> <style> body { margin: 0; } #glCanvas { position: absolute; top: 0; left: 0; width: 100%; height: 100%; } </style> </head> <body onload="main();"> <canvas id="glCanvas"></canvas> <script type="text/javascript"> function main() { var canvas = document.querySelector("#glCanvas"); var gl = canvas.getContext("webgl"); if(gl == null) { alert("Unable to initialize WebGL. Your browser or machine may not support it."); return; } let resolutionUniform; // 统一处理画布尺寸更新 function updateCanvasSize() { canvas.width = window.innerWidth; canvas.height = window.innerHeight; gl.viewport(0, 0, window.innerWidth, window.innerHeight); gl.uniform2fv(resolutionUniform, new Float32Array([canvas.width, canvas.height])); } var vertexShaderSc = ` precision highp float; precision highp int; attribute vec2 position; void main(void) { gl_Position = vec4(position, 0.0, 1.0); } `; var fragmentShaderSc = ` precision highp float; precision highp int; uniform vec2 resolution; uniform float time; void main(void) { vec2 uv = gl_FragCoord.xy/resolution.xy; gl_FragColor = vec4(uv+time, 0.0, 1.0); } `; var vertexShader = gl.createShader(gl.VERTEX_SHADER); var fragmentShader = gl.createShader(gl.FRAGMENT_SHADER); gl.shaderSource(vertexShader, vertexShaderSc); gl.shaderSource(fragmentShader, fragmentShaderSc); gl.compileShader(vertexShader); if(!gl.getShaderParameter(vertexShader, gl.COMPILE_STATUS)) { console.error("Error compiling vertex shader", gl.getShaderInfoLog(vertexShader)); return; } gl.compileShader(fragmentShader); if(!gl.getShaderParameter(fragmentShader, gl.COMPILE_STATUS)) { console.error("Error compiling fragment shader", gl.getShaderInfoLog(fragmentShader)); return; } var program = gl.createProgram(); gl.attachShader(program, vertexShader); gl.attachShader(program, fragmentShader); gl.linkProgram(program); if(!gl.getProgramParameter(program, gl.LINK_STATUS)) { console.error('ERROR linking program!', gl.getProgramInfoLog(program)); return; } gl.validateProgram(program); if(!gl.getProgramParameter(program, gl.VALIDATE_STATUS)) { console.error('ERROR validating program!', gl.getProgramInfoLog(program)); return; } var vertex_data = [ // First triangle: 1.0, 1.0, -1.0, 1.0, -1.0, -1.0, // Second triangle: -1.0, -1.0, 1.0, -1.0, 1.0, 1.0]; var buffer0 = gl.createBuffer(); gl.bindBuffer(gl.ARRAY_BUFFER, buffer0); gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertex_data), gl.STATIC_DRAW); var positionAttrib = gl.getAttribLocation(program, "position"); gl.vertexAttribPointer(positionAttrib, 2, gl.FLOAT, gl.FALSE, 2 * Float32Array.BYTES_PER_ELEMENT, 0); gl.enableVertexAttribArray(positionAttrib); gl.useProgram(program); resolutionUniform = gl.getUniformLocation(program, "resolution"); var timeUniform = gl.getUniformLocation(program, "time"); // 初始化尺寸&监听窗口变化 updateCanvasSize(); window.addEventListener('resize', updateCanvasSize); // 初始化配置只执行一次 gl.clearColor(0.0, 0.0, 0.0, 1.0); function render(timeStamp) { gl.uniform1f(timeUniform, timeStamp*0.001); gl.clear(gl.COLOR_BUFFER_BIT); gl.drawArrays(gl.TRIANGLES, 0, 6); requestAnimationFrame(render); } requestAnimationFrame(render); } </script> </body> </html>
内容的提问来源于stack exchange,提问作者playbyan1453
相关产品推荐
相关产品推荐

