javascript - WebGL 多个着色器

标签 javascript webgl

我已阅读有关此问题的先前 StackOverflow 帖子,但在让两个不同的着色器集在一个 WebGL 程序中正常工作时仍然遇到问题。

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

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

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();
    }

最佳答案

gl.useProgram(shaderProgram);基本上说:“好吧,从这一刻起,我将使用这种 Material 来为物体着色”。

话虽这么说,你正在做的是在webGLStart()即:initGL,使用A Material ,使用B Material ,创建对象,用当前 Material (也就是 Material B)绘制对象。

OpenGL/webGL 作为状态机工作。当您尝试渲染某些东西时,它会使用当前设置的该状态机的参数进行绘制。例如,您说 draw到OpenGL,但该方法正在寻找绑定(bind)到状态机的缓冲区,它还寻找当前使用的 Material (着色器)......等等。所以你设置了所有东西并启动一些 Action 。

所以,如果你想用两个不同的着色器渲染两个对象,你应该绑定(bind)一个对象(实际上是缓冲区),使用第一个 Material ( gl.useProgram(shaderProgramA) )并调度绘图。然后绑定(bind)第二个对象,设置第二个 Material ( gl.useProgram(shaderProgramB) )并调度另一个调用。这就是 OpenGL/WebGL 的工作原理。

另外,一个建议。尝试以不同的方式命名函数。 initShadersA应该做一些事情,比如获取源字符串,创建顶点和片段着色器,创建程序和链接所有东西,而一些函数像 useShadersA应该将当前 Material 设置为精确的着色器程序。

我希望这有帮助!

关于javascript - WebGL 多个着色器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29355582/

相关文章:

javascript - 类型错误 : object is not a function when using csv module

javascript - 如何将像这样交叉的 webGL Canvas 分成四等分?

javascript - 使用 Three.js 加载 Maya 模型

javascript - 在 html 页面上嵌入 Web-GL 沙箱的效果

javascript - 了解 JavaScript 中的标记和清除算法

javascript - 为什么相同的日期有不同的时间?

javascript - 如何使用javascript创建匹配元素的对象

javascript - 下拉菜单仅单击选定的行

javascript - WebGL:在带有深度模板纹理附件的帧缓冲区上未清除颜色

javascript - 在 HTML5 <canvas> 上绘制不同视角的模型