0
votes

so this is a somewhat vague question, probably due to my still limited (but improving) knowledge of the internals of WebGL (OpenGL), in particular the way the state is managed inside the GL context. please ask me to clarify or/and add additional detail. Because I dont know exactly where the issue is, Im including as much information as possible.

Im having a situation where Im implementing picking into a tiny rendering engine. Everything work fine when I have a simple shader where every object is rendered with a constant color. I have 2 buffers per object, one ARRAY_BUFFER and one ELEMENT_ARRAY_BUFFER. The picking aspect is implemented via an additional FrameBuffer, where the scene is rendered to it with a 'picking' shader. when I need to render the picking frame, I switch to the alternative FrameBuffer,then switch to the picking shader (gl.useProgram()), render the scene, and then switch back to the default canvas FrameBuffer. then I read out the pixel value at the clicked canvas coordinate, and use that value to look up the ID of the particular element... I even render the whole FrameBuffer to a separate canvas, as a debugging step, and display that canvas in the DOM, to see that in does indeed render things properly.

The trouble comes when I turn vertex coloring on. color values are specified per vertex, and passed into the shader as VertexAttribArray (same as the vertex coordinates). however when the coloring is turned on, the picking rendering does not render anything (a blank white screen is the output).

I've isolated the part of the coloring function that causes this error too appear (blank rendering of the picking frame):

Buffer vertex_color_buffer = gl.createBuffer();
gl.bindBuffer(RenderingContext.ARRAY_BUFFER,vertex_color_buffer);

gl.bufferData(RenderingContext.ARRAY_BUFFER,
              new Float32List.fromList(unpacked_colors_lst), 
              RenderingContext.STATIC_DRAW); 

int color_attr_location = gl.getAttribLocation(p_shader, 
                                               "a_vertex_color");
gl.enableVertexAttribArray(color_attr_location);    
gl.vertexAttribPointer(color_attr_location,
                       4,
                       RenderingContext.FLOAT, 
                       false, 
                       4*Float32List.BYTES_PER_ELEMENT, //stride
                       0);                              //offset within the buffer

so obviously some GL state is being set in these lines that is then, when the shader is switch from the vertex coloring shader (which displays things properly) to the picking shader, causing the scene to not be rendered. I thought that something might be wrong with my vertex transformations, but they are identical between the coloring shader and the picking shader, and yet the coloring shader displays things fine, whereas the picking shader does not.

Please let me know what else I need to include to make this question more clear. I've spent days trying to debug this and still dont have any ideas. (Ps. the code is written in Dart).

1
so stackoverflow.com/questions/9261258/… is ringing right to me... I will change things up a little bit to follow advice from this questions answer, and will post the outcome here... (in particular the conclusion of the answer "Basically, you want to treat every time you change programs as if it's the first time you're setting up a draw call.")deepblue
yes, this was indeed the issue. I am now setting the vertex array attribute each time I change the shaderdeepblue

1 Answers

1
votes

It's possible that 'color_attr_location' and some attribute in your picking shader share the same location (it's hard to tell from just that code) so one is replaceing the the other when you specify the array. If you are only setting up the arrays once then switching programs without setting them up again, that's most likely the issue.

AFAIK in WebGL you need to manually set up the vertex arrays before each draw call (as opposed to using Vertex Array Objects), which means it's probably best practice to disable them all again afterwards.

Use Program -> Setup Arrays -> Render -> Disable Arrays -> Use other program -> Setup Arrays