最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - WebGL multiple Shaders - Stack Overflow

programmeradmin1浏览0评论

I have read a previous StackOverflow post regarding this issue and am still having issues in getting two different shader sets to work correctly in one WebGL program.

Below is a skeleton framework of the code. I have two separate sets of shaders, with different variable names to prevent cross-contamination. I create two initShader() functions, one for each set of shaders, and then call the initBuffers() and the draw() functions. The result is that only the second shader takes effect and only the item draw with this shader is shown, despite the shaders being separately identified and called within drawscene().

Any suggestions for how to fix this issue will be appreciated.

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

I have read a previous StackOverflow post regarding this issue and am still having issues in getting two different shader sets to work correctly in one WebGL program.

Below is a skeleton framework of the code. I have two separate sets of shaders, with different variable names to prevent cross-contamination. I create two initShader() functions, one for each set of shaders, and then call the initBuffers() and the draw() functions. The result is that only the second shader takes effect and only the item draw with this shader is shown, despite the shaders being separately identified and called within drawscene().

Any suggestions for how to fix this issue will be appreciated.

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();
    }
Share Improve this question asked Mar 30, 2015 at 20:22 cadebecadebe 6912 gold badges13 silver badges37 bronze badges 1
  • You might find this helpful? – user128511 Commented Mar 31, 2015 at 5:14
Add a comment  | 

1 Answer 1

Reset to default 19

gl.useProgram(shaderProgram); basically says: "okay, from this moment on, I will use this material to shade objects".

That being said, what you are doing is in the webGLStart() is: initGL, use A material, use B material, create objects, draw objects with current material (and that is material B).

OpenGL/webGL works as a state machine. When you try to render something, it's drawn with the parameters of that state machine that are currently set. For example, you say draw to OpenGL, but that method is looking for a buffer that is bound to the state machine, it also looks for material (shader) currently used... etc. So you set everything up and that initiate some action.

So, if you want to render two objects with two different shaders, you should bind one object (it's buffers actually), use first material (gl.useProgram(shaderProgramA)) and dispatch draw. Then bind second object, set second material (gl.useProgram(shaderProgramB)) and dispatch another call. It's how OpenGL/WebGL works.

Also, one suggestion. Try naming functions differently. initShadersA should do things like taking source string, creating vertex and fragment shader, creating program and linking everything, whilst some function like useShadersA should set current material to exact shader program.

I hope this helps!

发布评论

评论列表(0)

  1. 暂无评论