Suppose I have previously rendered some set of pixels on the screen that each contain one of the following RGB values:
0.0 0.0 0.0 in other words, black 1.0 0.0 0.0 in other words, red 0.0 0.0 1.0 in other words, blue 1.0 0.0 1.0 in other words, purple
Now I want to be able to selectively toggle the red or blue components of what's on the screen to 1.0 or 0.0, without affecting the other color components of what's on the screen.
For instance, say some pixel contains 1.0, 0.0, 1.0, purple, and I want to turn off the red in that pixel without changing the value of blue.
Assumption here is at this point I don't know if the blue in that pixel is 0.0 or 1.0. I just want to turn the red part of it off.
Also, I don't want to have to segregate the red changes from the blue changes into separate sets of vertex attributes, i.e. I'd like to be able to set just the red component of one set of pixels and set the blue component of another set of pixels in one call to glDrawArrays(). Also, within each set of pixels some of the reds I want to be able to set to 1.0 while others I want to set to 0.0 and likewise for the blue.
I have a hunch this would involve some creative usage of glBlendFunc(), but dang if I can figure out how to do it.
Note that what I am trying to accomplish here is a poor man's 3D rendering on a typical PC screen using a homemade set of goggles with a red lens for the right eye and a blue lens for the left eye. Think how they did 3D for black and white movies back in the 1950s.
Anybody got some suggestions?
To answer gilgamec's questions:
"where are the pixels coming from? A texture map? An image? Rendered triangles?"
The GLSL part of the application consists of a vertex shader and a fragment shader in one GLSL program and a vertex shader that does transform feedback in a second GLSL program. Pairs of vertices are encoded by the host CPU into a vertex attribute array and passed to the first GLSL program for rendering to the screen via a call to glDrawArrays(GL_LINES,...). The same set of vertices is then passed to the second GLSL program whose vertex shader does the same transformations as the first's but then feeds them back to the host CPU.
"Why can't you alter the input directly?"
Well, I can. The problem is algorithm running in the host CPU code that generates the vertex pairs is very CPU intensive and thus gets delivered to the GPUs rather slowly. Slow enough that there is a visible delay and there's really no way to speed that up much. It's modelling reflections of images off of sets of mirrors as viewed by some observer that moves around virtually among the set of mirrors. Imagine a big polyhedron made of mirrors with their reflective surfaces facing inward and the observer is standing inside of it along with a light source consisting of a collection of line segments. I've copied a non-steroscopic rendering of it as an example below. Here the mirrored polyhedron is a cube that the observer is standing in. The big red triangle is the single light source and everything else is reflections of reflections of the triangle plus reflections of the edges of the cube in blue. The observer himself is transparent so his head doesn't get in the way of the reflections. 8)
I can run this program in the usual manner in which on each pass through the main loop the screen is first cleared via glClear(), transform matrices are computed and vertices are rendered via glDrawArrays(GL_LINES...). The problem there is the vertices representing the reflections get generated slowly with large models, so it takes a visible while for rendering to complete. So I've implemented a second mode of operation in which I only clear the screen once at program start up. On each pass through the main loop after glDrawArrays() and the screen buffer swap I copy the front frame buffer to the back buffer. On the next pass through the loop as new reflections come out of the algorithm I use the feed back data from the second GLSL program to "erase" the old reflections from the screen by painting them black in the fragment shader before each new reflection is painted in red or blue. The effect isn't perfect, there's still lag, but the old reflections get sort of dragged along as the observer moves around until they finally get erased and replaced by new reflections once the observer sits still long enough. It's pretty, which is the whole point of this exercise.
So I've got this second "incremental screen update" mode implemented for non-stereoscopic (1 eyed observer) mode and it works. And I have non-incremental screen mode implemented for red-blue stereoscopic mode, see below:
If you happen to have some red and blue transparent sheets lying around, get in a dark room and look at the above with the red in front of your right eye and the blue in front of your left eye. Relax your eyes a bit and you should be able to perceive the reflections in 3D (at least I can see it and my eyes are 65 years old, 8).
But to get incremental screen mode to work in 3D, I need to be able to write 0.0 (to erase to black) or 1.0 to the blue component of pixels on the screen without affecting the red and vis-versa. I think I can do that with glColorMask() but that means segregating the vertex attributes corresponding to left eye (blue) perspective from those corresponding to right eye (red) perspective.
"You mention OpenGL functions, so have you just tried modifying the fragment shader?"
That's what the question is about. Is there a way to write to only the red or blue components of existing pixels in the frame buffer from a fragment shader?