WebGL双着色器程序问题:点击绘三角形后圆形消失求助
WebGL圆形消失问题的修复方案
问题根源
WebGL采用即时渲染模式,画布内容不会自动持久保留,每次绘制操作仅在当前帧生效。你的代码在点击三次后直接绘制三角形,但没有重新绘制圆形,且渲染流程未整合所有元素的绘制逻辑,导致圆形被覆盖后无法重新显示。
具体修复步骤
1. 重构渲染逻辑,统一绘制所有元素
将圆形和三角形的绘制逻辑整合到持续运行的渲染循环中,确保每一帧都重新绘制所有需要显示的内容。点击事件仅负责收集顶点数据,不直接执行绘制命令。
2. 优化程序切换与状态管理
绘制不同元素时明确切换对应的着色器程序,避免程序状态混乱导致的绘制异常。
3. 复用缓冲区提升性能
提前创建三角形的缓冲区,点击后仅更新缓冲区数据,无需重复创建。
修改后的完整代码示例
全局变量调整
var circlevertices_length; var gl = null; var program1 = 0; // 修正变量名与主函数一致 var program2 = 0; var divisions = 0; var tcount = 0; var tmax = 3; var drawTriangle = false; // 标记是否需要绘制三角形 var triBuffer = null; // 提前创建三角形缓冲区 var trivert = [ 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 ]; // 着色器代码保持不变 var VSHADER_SOURCE = ` precision highp float; attribute vec3 coordinates; void main(){ gl_Position = vec4(coordinates, 1.0); } `; var VSHADER_SOURCE_TRIANGLE = ` precision highp float; attribute vec3 coordinates2; void main() { gl_Position = vec4(coordinates2, 1.0); } `; var FSHADER_SOURCE = ` precision highp float; uniform vec4 color; void main(){ gl_FragColor = color; } `;
主函数修改
function main(){ var canvas = document.getElementById("MyCircle"); gl = getWebGLContext(canvas); program1 = createProgram(gl, VSHADER_SOURCE, FSHADER_SOURCE); program2 = createProgram(gl, VSHADER_SOURCE_TRIANGLE, FSHADER_SOURCE); // 初始化三角形缓冲区 triBuffer = gl.createBuffer(); // 注册点击事件 canvas.onmousedown = function(ev){ click(ev, gl, canvas) }; // 启动持续渲染循环 function renderLoop() { // 清屏(可自定义背景色) gl.clearColor(0.0, 0.0, 0.0, 1.0); gl.clear(gl.COLOR_BUFFER_BIT); // 绘制圆形(请补充你原本的圆形绘制逻辑) gl.useProgram(program1); // 示例:绑定圆形缓冲区、设置属性和颜色、执行绘制 // const circlePosLoc = gl.getAttribLocation(program1, "coordinates"); // gl.bindBuffer(gl.ARRAY_BUFFER, circleBuffer); // gl.enableVertexAttribArray(circlePosLoc); // gl.vertexAttribPointer(circlePosLoc, 3, gl.FLOAT, false, 0, 0); // const circleColorLoc = gl.getUniformLocation(program1, 'color'); // gl.uniform4f(circleColorLoc, 0.0, 1.0, 0.0, 1.0); // gl.drawArrays(gl.LINE_LOOP, 0, circlevertices_length); // 若三角形数据已准备好,绘制三角形 if (drawTriangle) { gl.useProgram(program2); gl.bindBuffer(gl.ARRAY_BUFFER, triBuffer); const position_loc = gl.getAttribLocation(program2, "coordinates2"); gl.enableVertexAttribArray(position_loc); gl.vertexAttribPointer(position_loc, 3, gl.FLOAT, false, 0, 0); const color_loc2 = gl.getUniformLocation(program2, 'color'); gl.uniform4f(color_loc2, 1.0, 1.0, 1.0, 1.0); gl.drawArrays(gl.LINE_LOOP, 0, tmax); } requestAnimationFrame(renderLoop); } renderLoop(); }
点击事件修改
function click(ev, gl, canvas){ var x = ev.clientX; var y = ev.clientY; var rect = ev.target.getBoundingClientRect(); if(tcount < tmax){ x = ((x - rect.left) - canvas.width/2)/(canvas.width/2); y = (canvas.height/2 - (y-rect.top))/(canvas.height/2); z = 0.0; trivert[tcount * 3 + 0] = x; trivert[tcount * 3 + 1] = y; trivert[tcount * 3 + 2] = z; tcount++; } if(tcount == tmax){ // 更新三角形缓冲区数据 gl.bindBuffer(gl.ARRAY_BUFFER, triBuffer); gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(trivert), gl.STATIC_DRAW); // 标记需要绘制三角形 drawTriangle = true; tcount = 0; } }
内容的提问来源于stack exchange,提问作者QuinnB
相关产品推荐
相关产品推荐

