WebGL多个着色器

cad*_*ebe 1 javascript webgl

我已经阅读了有关此问题的先前StackOverflow帖子,并且在使两个不同的着色器集在一个WebGL程序中正常工作时仍然存在问题.

下面是代码的骨架框架.我有两组独立的着色器,具有不同的变量名称以防止交叉污染.我创建了两个initShader()函数,每个着色器一个,然后调用initBuffers()和draw()函数.结果是,只有第二个着色器生效,并且只显示使用此着色器绘制的项目,尽管单独标识着色器并在drawcene()中调用.

任何有关如何解决此问题的建议将不胜感激.

Declare: vertexShaderA
Declare: fragmentShaderA
Declare: vertexShaderB (use distinct variable names to that of vertexShaderA)
Declare: fragmentShaderB (use distinct variable names to that of fragmentShaderA)

// main script

initShadersA(){
…
    gl.useProgram(shaderProgramA);
…
}
initShadersB(){
…
    gl.useProgram(shaderProgramB);
…
}
…
setMatrixUniformsA();
setMatrixUniformsB();

function initBuffers(){
…
}

function drawScene(){
…
gl.bindBuffer(gl.ARRAY_BUFFER, vertexPositionBuffer);
gl.vertexAttribPointer(shaderProgramA.vertexPositionAttributeA, vertexPositionBuffer.itemSize, gl.FLOAT, false, 0, 0);
…
 gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, vertexIndexBuffer);
 gl.uniform1i(shaderProgramA.samplerUniform, 0);
 setMatrixUniformsA();
 gl.drawElements(gl.TRIANGLES, vertexIndexBuffer.numItems, gl.UNSIGNED_SHORT, 0);

…

gl.bindBuffer(gl.ARRAY_BUFFER, vertexPositionBuffer);
gl.vertexAttribPointer(shaderProgramB.vertexPositionAttributeB, vertexPositionBuffer.itemSize, gl.FLOAT, false, 0, 0);
…
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, vertexIndexBuffer);
gl.uniform1i(shaderProgramB.samplerUniform, 0);
setMatrixUniformsB();
gl.drawElements(gl.TRIANGLES, vertexIndexBuffer.numItems, gl.UNSIGNED_SHORT, 0);
}

 function draw() {
        requestAnimFrame(draw);
        animate(); 
        drawScene();
    }       
function animate() { 
    …
} 
function webGLStart() {
        initGL(canvas);
        initShadersA();
        initShadersB();
        initBuffers();
        gl.clearColor(0.0, 0.0, 0.0, 1.0);
        gl.enable(gl.DEPTH_TEST);
        draw();
    }
Run Code Online (Sandbox Code Playgroud)

Abs*_*thm 8

gl.useProgram(shaderProgram); 基本上说:"好的,从这一刻起,我将使用这种材料来遮蔽物体".

话虽这么说,你正在做的webGLStart()是:initGL,使用材料,使用B材料,创建对象,用当前材料绘制对象(这是材料B).

OpenGL/webGL用作状态机.当您尝试渲染某些内容时,会使用当前设置的状态机参数绘制它.例如,你draw对OpenGL 说,但是该方法正在寻找绑定到状态机的缓冲区,它还查找当前使用的材质(着色器)......等等.所以你设置了一切并启动了一些动作.

因此,如果要渲染具有两个不同着色器的两个对象,则应绑定一个对象(实际上是缓冲区),使用第一个材质(gl.useProgram(shaderProgramA))和分派绘制.然后绑定第二个对象,设置第二个材料(gl.useProgram(shaderProgramB))并分派另一个调用.这就是OpenGL/WebGL的工作原理.

还有一个建议.尝试以不同方式命名函数.initShadersA应该做一些事情,比如获取源字符串,创建顶点和片段着色器,创建程序和链接所有内容,而某些功能useShadersA应该将当前材质设置为精确着色器程序.

我希望这有帮助!