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

WebGL曼德博集合程序报错:无有效着色器程序(编译链接验证正常)

WebGL曼德博集合程序报错:drawArrays时无有效着色器程序使用

我在编写一个生成曼德博集合的WebGL程序,使用Chrome浏览器,GPU为GTX 1660 Ti。着色器编译、链接、验证均成功,但调用drawArrays时出现错误:

mandelbrot.js:33 WebGL: INVALID_OPERATION: drawArrays: no valid shader program in use

排查1小时未找到问题,相关代码如下:

顶点着色器

precision mediump float;

attribute vec2 position;
varying vec2 fragPosition;

void main() {
    gl_Position = vec4(position, 0.0, 1.0);
    fragPosition = position;
}

片元着色器

precision mediump float;
#define ITERATIONS 50

varying vec2 fragPosition;

vec2 cx_mul(vec2 a, vec2 b) {
    return vec2(a.x*b.x-a.y*b.y, a.x*b.y+a.y*b.x);
}

void main() {
    int itr = 0;
    vec2 z = fragPosition, c = fragPosition;
    for(int i = 0; i < 50; i++) {
        itr = i;
        z = cx_mul(z, z) + c;
        if(length(z) > 2.0) break;
    }
    gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
}

JavaScript代码(mandelbrot.js)

var gl;
var canvas;
var program;
const address = '127.0.0.1';
import {initGL, compileShaders, bindVAO, loadFile} from './util.js';

window.onload = function() {
    canvas = document.getElementById('canvas');
    gl = canvas.getContext('webgl');
    if(!gl)
        gl = canvas.getContext('experimental-webgl');
    
    initGL(gl);

    var vertexCode = loadFile('http://' + address + '/mandelbrot.vert');
    var fragmentCode = loadFile('http://' + address + '/mandelbrot.frag');

    var vertexShader = gl.createShader(gl.VERTEX_SHADER);
    var fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
    
    gl.shaderSource(vertexShader, vertexCode);
    gl.shaderSource(fragmentShader, fragmentCode);
    
    compileShaders(vertexShader, fragmentShader);
    bindVAO();
    gl.useProgram(program);
    
    update();
}

function update() {
    gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
    gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
}

工具代码(util.js)

export {initGL, compileShaders, bindVAO, loadFile};

var gl;

function initGL(glContext) {
    gl = glContext;
}

function compileShaders(vertexShader, fragmentShader) {
    gl.compileShader(vertexShader);
    if(!gl.getShaderParameter(vertexShader, gl.COMPILE_STATUS))
        throw ("compilation error: " + gl.getShaderInfoLog(vertexShader));
    gl.compileShader(fragmentShader);
    if(!gl.getShaderParameter(fragmentShader, gl.COMPILE_STATUS))
        throw ("compilation error: " + gl.getShaderInfoLog(fragmentShader));
    
    var program = gl.createProgram();
    gl.attachShader(program, vertexShader);
    gl.attachShader(program, fragmentShader);
        
    gl.linkProgram(program);
    if(!gl.getProgramParameter(program, gl.LINK_STATUS))
        throw ("linking error: " + gl.getProgramInfoLog(program));
        
    gl.validateProgram(program);
    if(!gl.getProgramParameter(program, gl.VALIDATE_STATUS))
        throw ("validation error: " + gl.getProgramInfoLog(program));
    
    return program;
}

function bindVAO() {
    var vertices = new Float32Array([-1, 1, -1, -1, 1, 1, 1, -1]);
    var vao = gl.createBuffer();
    gl.bindBuffer(gl.ARRAY_BUFFER, vao);
    gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);
    gl.vertexAttribPointer(0, 2, gl.FLOAT, gl.FALSE, 2 * Float32Array.BYTES_PER_ELEMENT, 0);
    gl.enableVertexAttribArray(0);
}

function loadFile(url) {
    var xmlHttp = new XMLHttpRequest();
    xmlHttp.open("GET", url, false);
    xmlHttp.send(null);
    return xmlHttp.responseText;
}

问题原因与修复方案

核心错误:着色器程序未赋值给全局变量

util.js中的compileShaders函数会返回编译链接完成的着色器程序,但你在mandelbrot.js中调用该函数时,没有将返回值赋值给全局的program变量,导致gl.useProgram(program)传入的是undefined(无效程序),触发报错。

修复代码:修改mandelbrot.js中的调用逻辑:

// 原代码
compileShaders(vertexShader, fragmentShader);
// 修复后
program = compileShaders(vertexShader, fragmentShader);

额外优化建议

  1. 修正bindVAO函数名:WebGL 1.0不支持顶点数组对象(VAO),此处创建的是顶点缓冲区对象(VBO),建议将函数名改为bindVertexBuffer,避免概念混淆。
  2. 使用宏定义的迭代次数:片元着色器中定义了ITERATIONS宏,但循环硬编码了50,可改为i < ITERATIONS,提升代码可维护性:
for(int i = 0; i < ITERATIONS; i++) {

内容的提问来源于stack exchange,提问作者imlol69420

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.24 19:54:26