You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 05:55:05