Conflict when using two or more shaders with diffe

2019-04-01 01:08发布

I'm trying to implement picking(using colors and readPixels) in a WebGL program of mine. When I start my program I create to seperate shaderProgram. One for phong shading and another that simply give shapes a color to be use to detect which shape has been clicked on.

The phong shader has 2 attributes. Vertex position and vertex normal. The picking one simply has the position.

Now I discovered that for some odd reason, when both of these shaders exist in the same program and I'm using the picking one, my drawArray call seems to fail. The last thing to happen is my gl.vertexAttribPointer call. I've been messing around and found out that when I check for active attrib arrays using: gl.getVertexAttrib(index,gl.VERTEX_ATTRIB_ARRAY_ENABLED);

both 0,1 return true (this is when the picking shader is active with gl.useProgram(picking))

Now if I disable 1 with gl.disableVertexAttribArray(1); Everything works again. Another fix is to draw with the phong shader first and then use the picking shader and somehow that magically makes it ok. I'm guessing that in that case when attaching my vertex normals buffer while using the phong shader, it somehow stays when I then switch to the picking shader and the drawArray call works.

I'd like to know if I'm using gl.enableAttribArray wrong and should disable them when switching shaders or something like that.

I've also tried creating the shader programs in different order with no success.

3条回答
一夜七次
2楼-- · 2019-04-01 01:28

As you've probably figured out, useProgram doesn't affect anything but the program (shader code) supposed to run in the next draw call. You have to make sure only attributes used by the current program is enabled.

If you've wrapped your WebGL code somehow, a tip is to keep the highest available attribute number for each program stored somewhere in your wrapper, then compare with the latest used program and enable/disable accordingly before the draw call.

查看更多
Evening l夕情丶
3楼-- · 2019-04-01 01:31

It's hard to tell without seeing your code but... WebGL requires that all attributes that will be accessed have enough data to satisfy the draw call. So, if you setup 2 attributes each with 3 vertices of data and draw 3 vertices, then switch shaders and setup 1 attribute with 6 vertices and leave the second attribute with only 3 vertices then attempt to draw with 6 vertices, if the shader you're currently drawing with accesses both attributes WebGL will fail the draw call.

If you run Chrome 19 it should tell you in the JavaScript console if this was the issue.

查看更多
贪生不怕死
4楼-- · 2019-04-01 01:37

OpenGL is a state machine. By selecting the picking shader you put OpenGL in a state where there's no longer the additional attributes of the phong shader.

A lot of people fall into the wrong and bad habbit to assume there was some kind of "one time initialization" with OpenGL. This is not the case. You're supposed to set all the state you need for some drawing operation, just right before that drawing operation, and ideally also to revert the settings once you're done. This means: After binding a shader, you're also supposed to enable and bind the required shader inputs aka vertex attributes.

查看更多
登录 后发表回答