在WebGL中切换着色器程序

时间:2012-02-05 03:48:38

标签: javascript glsl shader webgl

我有一个现有的WebGL渲染器(太多代码可用于共享),这曾经非常简单:它只有一个顶点着色器,一个片段着色器和一个着色器程序。这是为了渲染四边形。

我正在尝试将其扩展为具有第二个着色器程序,它可以切换到和来自渲染点精灵。它有自己的顶点属性数组,第二个顶点着色器,片段着色器和着色器程序。

我似乎无法在两者之间正确切换:我不断收到显示故障,随机消失的物体等。这是我必须在它们之间切换的两个功能。知道我错过了什么吗?

GLWrapProto.switchQuadProgram = function ()
{
    var gl = this.gl;

    gl.useProgram(this.shaderProgramPoint);

    gl.disableVertexAttribArray(this.locAPosPoint);

    gl.useProgram(this.shaderProgram);

    gl.enableVertexAttribArray(this.locAPos);
    gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexBuffer);
    gl.vertexAttribPointer(this.locAPos, 2, gl.FLOAT, false, 0, 0);

    gl.enableVertexAttribArray(this.locATex);
    gl.bindBuffer(gl.ARRAY_BUFFER, this.texcoordBuffer);
    gl.vertexAttribPointer(this.locATex, 2, gl.FLOAT, false, 0, 0);
};

GLWrapProto.switchPointProgram = function ()
{
    var gl = this.gl;

    gl.useProgram(this.shaderProgram);

    gl.disableVertexAttribArray(this.locAPos);
    gl.disableVertexAttribArray(this.locATex);

    gl.useProgram(this.shaderProgramPoint);

    gl.enableVertexAttribArray(this.locAPosPoint);
    gl.bindBuffer(gl.ARRAY_BUFFER, this.pointBuffer);
    gl.vertexAttribPointer(this.locAPosPoint, 4, gl.FLOAT, false, 0, 0);
};

1 个答案:

答案 0 :(得分:3)

很难说出这段代码的问题是什么,但是让我在那里提出一些建议来帮助你找到问题。

首先,每次切换着色器时都不必过于担心执行disableVertexAttribArray。启用/禁用数组是与着色器关联的状态,因此更改绑定程序会使先前启用的数组无效。

(实际上,有没有人知道这方面有一个不错的引用,我试图找到一个但目前不能。)

考虑到这一点,您可以将上述代码简化为:

GLWrapProto.switchQuadProgram = function ()
{
    var gl = this.gl;

    gl.useProgram(this.shaderProgram);

    gl.enableVertexAttribArray(this.locAPos);
    gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexBuffer);
    gl.vertexAttribPointer(this.locAPos, 2, gl.FLOAT, false, 0, 0);

    gl.enableVertexAttribArray(this.locATex);
    gl.bindBuffer(gl.ARRAY_BUFFER, this.texcoordBuffer);
    gl.vertexAttribPointer(this.locATex, 2, gl.FLOAT, false, 0, 0);
};

GLWrapProto.switchPointProgram = function ()
{
    var gl = this.gl;

    gl.useProgram(this.shaderProgramPoint);

    gl.enableVertexAttribArray(this.locAPosPoint);
    gl.bindBuffer(gl.ARRAY_BUFFER, this.pointBuffer);
    gl.vertexAttribPointer(this.locAPosPoint, 4, gl.FLOAT, false, 0, 0);
};

我对你在“显示故障”中提到的问题感到好奇。我无法想到为什么切换着色器会导致对象随机停止并开始渲染。首先尝试使用一个着色器仅渲染几何体,然后仅切换和渲染使用另一个着色器的几何体。如果他们中的任何一个有问题,那么你知道它不是导致问题的着色器切换。如果仅在将两组几何体一起渲染时才出现问题,则两者之间的状态管理可能会出现一些错误。