I'm working on a WebGL project that resembles a particle system. For aesthetic purposes, my single rendering pass is configured to blend additively, and I've disabled depth testing. I'm also clearing my viewport buffer to 50% gray, for the sake of argument.
gl.enable(gl.BLEND);
gl.blendFunc(gl.ONE, gl.ONE);
gl.disable(gl.DEPTH_TEST);
gl.clearColor(0.5, 0.5, 0.5, 1.0);
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
I've uploaded a vertex buffer and index buffer to the GPU representing two partially overlapping triangles. Their vertices have a vec3 color attribute. I've assigned each vertex a color of 50% gray (0.5, 0.5, 0.5).
When I draw the triangles with my shaders, I'm relieved to report that my viewport buffer now looks 50% gray with two overlapping triangular regions that are white. The triangles are white because their fragments' color values were additively blended with those already in the color buffer.
Now, I re-upload the vertex buffer with the following change: the color of the vertices of the second triangle are now -50% gray (-0.5, -0.5, -0.5).
What I hope to accomplish is that my viewport buffer would look 50% gray with two overlapping triangular regions– one white, one black– which intersect, and produce 50% gray at their intersection. After all, adding a negative number should be the same as subtracting a positive number of the same magnitude.
What I see instead is a 50% gray viewport with only one triangular region– the white one.
I assume that this is because the output of my fragment shader is being clamped to a range whose lower bound is zero, before it's blended with the color buffer. I would like to know how to circumvent this clamping– ideally in WebGL, without requiring multiple render passes.
I'll be testing solutions in the source of the page at this URL: http://rezmason.net/scourge/issues/positive_negative_fragments.html
UPDATE
As an investigation, I've experimented with performing my additive blending in a frame buffer, and then drawing the frame buffer to the viewport buffer by texturing it to a unit quad– that's two separate draw calls, of course, which ideally I'd like to avoid.
That said, because I can explicitly set the format of the frame buffer to floating point, no clamping occurs with any value while I perform operations within that buffer. When I draw the buffer to the viewport, I assume that clamping finally occurs, but by then all the blending is already done.
My question is now substantially simpler: is there any way to initialize a WebGL or OpenGL context, so that its viewport is formatted as a floating point buffer?