OpenGL non-square textures - opengl

I'm a little new to OpenGL. I am making a 2D application, and I defined a Quad class which defines a square with a texture on it. It loads these textures from a texture atlas, and it does this correctly. Everything works with regular textures, and the textures display correctly, but doesn't display correctly when the texture image is not a square.
For example, I want a Quad to have a star texture, and have the star to show up, and the area around the star image that still lies in the Quad to be transparent. But what ends up happening is that the star shows up fine, and then behind it is another texture from my texture atlas that fills the Quad. I assume the texture behind it is just the last texture I loaded into the system? Either way, I don't want that texture to show up.
Here's what I mean. I want the star but not the cloud-ish texture behind it showing up:
The important part of my render function is:
glDisable(GL_CULL_FACE);
glVertexPointer(vertexStride, GL_FLOAT, 0, vertexes);
glEnableClientState(GL_VERTEX_ARRAY);
glColorPointer(colorStride, GL_FLOAT, 0, colors);
glEnableClientState(GL_COLOR_ARRAY);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, textureID);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glTexCoordPointer(2, GL_FLOAT, 0, uvCoordinates);
//render
glDrawArrays(renderStyle, 0, vertexCount);

It seems like the obvious choice would be to use an RGBA texture, and make everything but the star transparent by setting the alpha channel to zero for those pixels (and enable alpha blending for the texture unit).

Use an image manipulation program. Photoshop is a great one, gimp is a free one. You don't really use OpenGL to crop your textures. Rather, your textures need to be prepared beforehand for your program.
There should be some sort of very easy tool to remove everything outside of the star. By remove, I mean make it transparent, which will require an alpha channel. This means you need to make sure that the way you load your textures in your program takes into account 32-bit colors (RGBA - red, green, blue, alpha), not just 24-bit colors (RGB - red, green, blue).
This will make everything behind your star see-through, or transparent.
Also, just an afterthought, it looks like you could be taking a copyrighted image off the internet and using it in your game/program. If you're doing anything commercial, I'd strongly recommend creating your own textures.

You want to make a call to glBindTexture(GL_TEXTURE_2D,0); after you have mapped your texture
here is an example from some code ive written
// Bind the texture
glBindTexture(GL_TEXTURE_2D, image.getID());
// Draw a QUAD with setting texture coordinates
glBegin(GL_QUADS);
{
// Top left corner of the texture
glTexCoord2f(0, 0);
glVertex2f(x, y);
// Top right corner of the texture
glTexCoord2f(image.getRelativeWidth(), 0);
glVertex2f(x+image.getImageWidth(), y);
// Bottom right corner of the texture
glTexCoord2f(image.getRelativeWidth(), image.getRelativeHeight());
glVertex2f(x+image.getImageWidth()-20, y+image.getImageHeight());
// Bottom left corner of the texture
glTexCoord2f(0, image.getRelativeHeight());
glVertex2f(x+20, y+image.getImageHeight());
}
glEnd();
glBindTexture(GL_TEXTURE_2D, 0);
I am no expert but this certainly solved what you are experiencing for me.

Related

OpenGL: Draw color with mask on a background image

I need to draw a color with some shape onto an image. My thought was to supply a mask with the given shape (say, hearts), then fill the rectangular area with the color and use the mask to render it over the final image.
Masked by:
PLUS
EQUALS:
The rectangle color is decided at runtime - that's why I don't draw the colored heart on my own.
The black heart image is transparent (alpha is 0) anywhere except for the heart (alpha is 255).
I tried using:
glBlendFunc(GL_DST_ALPHA, GL_ZERO)
where the source is the solid color, and the destination is the alpha channel image.
I used https://www.andersriggelsen.dk/glblendfunc.php for help.
However the bottom image (tree) is being used as the DST image...
Seems like I need an intermediate buffer to first render the blue heart, then do a second render onto the tree.
What is the way to do it?
If the tree is drawn before, it will appear in the dest Color and change your final result.
You are right, you need an intermediate buffer to store which part of the quand should be rendered, with the shape of your heart.
OpenGL provide a perfect tool for this, it's called stencil buffer.
In your case i will render my scene like usual (the tree)
Then i will enable the stencil buffer glEnable(GL_STENCIL_TEST);
Disable the write to the colorBuffer glColorMask(false, false, false, false);,
Draw only the heart with the appropriate mask. glStencilMask(0xFF);
Then you draw your colored quad with stencil test enable with glStencilFunc(GL_EQUAL, 1, 0xFF)
Don't forget to clear your stencil buffer each frame glClear(GL_STENCIL_BUFFER_BIT);
You can find some good tutorials online: https://learnopengl.com/Advanced-OpenGL/Stencil-testing
Here's a very simple way to do this in legacy OpenGL (which I assume you're using) that does not require a stencil buffer:
public void render() {
glClearColor(0, 0, 0, 0);
glClear(GL_COLOR_BUFFER_BIT);
glLoadIdentity();
glOrtho(0, 1, 1, 0, 1, -1);
glEnable(GL_TEXTURE_2D);
glEnable(GL_BLEND);
// Regular blending
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_ALPHA_TEST);
// Discard transparent pixels. Not strictly necessary but good for performance in this case.
glAlphaFunc(GL_GREATER, 0.01f);
glColor3f(1,1,1);
glBindTexture(GL_TEXTURE_2D, treeTexture);
drawQuad();
glColor3f(1,0,1); // Your color goes here
glBindTexture(GL_TEXTURE_2D, maskTexture);
drawQuad();
}
private void drawQuad() {
glBegin(GL_QUADS);
glTexCoord2f(0,0);
glVertex2f(0,0);
glTexCoord2f(0,1);
glVertex2f(0,1);
glTexCoord2f(1,1);
glVertex2f(1,1);
glTexCoord2f(1,0);
glVertex2f(1,0);
glEnd();
}
Here, treeTexture is the tree texture, and maskTexture is the white-on-transparent heart shape.
Result:
The principle is that in the legacy OpenGL pipeline, you can use glColor* before glVertex* to specify a color that the texture color (in this case white or transparent) is multiplied by component-wise.
Note that with this method you can easily render multiple colored shapes in multiple different colors without needing any (relatively expensive) clears of the stencil buffer. I suggest cropping the mask texture to the boundaries of the actual mask shape, to save the GPU the small effort of discarding all the transparent fragments.

OpenGL bitmap alpha buffer

I have two RGBA images (simple 2D raster of type GL_UNSIGNED_BYTE, not textures or anything) of the same scene, one sharp, one blurred. With the blurred image displayed, I need to create an effect where the sharp image shows through in one or more (possibly overlapping) circular areas, smoothly blending with the background blurred image around the edges of the circles. I used to do the following.
Call this at the initialization:
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
For every circle, make a copy of the sharp image, assign new values for their alpha components, starting from 255 at the center of the circle, reducing it to 0 towards the edges. Then rendered them one by one with glDrawPixels(), starting from the blurred image. It works, but as the number of those circular areas grows, it is getting noticeably slow.
I was thinking of using some alpha buffers (don't know the correct term), so that I create a small image with a cut out alpha circle in the middle, render its alpha component at one or several places of the framebuffer, then somehow blend the blurred image and the sharp image with those pre-rendered alpha values. So I wrote this in my display() function:
//render the alpha-mask first, at one place for now
GLfloat rp[4];
glGetFloatv(GL_CURRENT_RASTER_POSITION, rp);
glRasterPos2f(0.2f, 0.2f); //just some arbitrary coordinates on the screen
glColorMask(false, false, false, true); //think I only need the alpha-channel
glBlendFunc(GL_ONE, GL_ZERO);
glDrawPixels(sharp_mask_width, sharp_mask_height, GL_RGBA, GL_UNSIGNED_BYTE, alpha_mask);
//render the blurred image, blending the the previously rendered alpha
glRasterPos2f(rp[0], rp[1]);
glColorMask(true, true, true, true); //all channels
glBlendFunc(GL_ONE_MINUS_DST_ALPHA, GL_DST_ALPHA); //make a hole where alpha mask had the maximum alpha
glDrawPixels(g_width, g_height, GL_RGBA, GL_UNSIGNED_BYTE, imageDataBlurred);
glBlendFunc(GL_DST_ALPHA, GL_ONE_MINUS_DST_ALPHA);
glDrawPixels(g_width, g_height, GL_RGBA, GL_UNSIGNED_BYTE, imageDataSharp);
glFlush();
It seems I don't understand something important about all this blending stuff, because nothing is rendered at all, all I get is an empty screen. All I got is an effect remotely similar to what I need, messing with glBlendFunc parameters and blending rgb-s instead of alpha-s.
How, if at all, can it be done?
I know I will probably burn in hell for using outdated OpenGL in the year 2015, when programmable shaders rule the world and cure cancer, but if possible I'd much prefer an answer describing how to do it in old style OpenGL, so I don't have to change that crap of a legacy program too much...

Aliasing issue with SDL + OpenGL masking

I've been trying to make Worms style destructible terrain, and so far it's been going pretty well...
Snapshot1
I have rigged it so that the following image is masked onto the "chocolate" texture.
CircleMask.png
However, as can be seen on Snapshot 1, the "edges" of the CircleMask are still visible (overlapping each other). I'm fairly certain it has something to do with aliasing, as mask image is being stretched before being applied (that, and the SquareMask.png does not have this issue). This is my problem.
My masking code is as follows:
void MaskedSprite::draw(Point pos)
{
glEnable(GL_BLEND);
// Our masks should NOT affect the buffers color, only alpha.
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE);
glBlendFunc(GL_ONE_MINUS_DST_ALPHA,GL_DST_ALPHA);
// Draw all holes in the texture first.
for (unsigned i = 0; i < masks.size(); i++)
if (masks.at(i).mask) masks.at(i).mask->draw(masks.at(i).pos, masks.at(i).size);
// But our image SHOULD affect the buffers color.
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
// Now draw the actual sprite.
Sprite::draw(pos);
glDisable(GL_BLEND);
}
The draw() function draws a quad with the texture on it to the screen. It has no blend functions.
If you invert the alpha channel on your mask image so that the inside of the circle has alpha 0.0, You can use the following blending mode:
glClearColor(0,0,0,1);
// ...
glBlendFunc(GL_DST_ALPHA, GL_ZERO);
This means, when the screen is cleared, each pixel will be set to alpha 1.0. Each time the mask is rendered with blending enabled, it will multiply the mask's alpha value with the current alpha at that pixel, so the alpha value will never increase.
Note that using this technique, any alpha channel in the sprite texture will be ignored. Also, if you are rendering a background before the terrain, you will need to change the blend function before rendering the final sprite image. Something like glBlendFunc(GL_DST_ALPHA, GL_ONE_MINUS_DST_ALPHA) would work.
Another solution would be to use your blending mode but set the mask texture's interpolation mode to nearest-neighbor to ensure that each value sampled from the mask is either 0.0 or 1.0:
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
My last bit of advice is this: the hard part about destructible 2D terrain is not getting it to render correctly, it's doing collision detection with it. If you haven't given thought to how you plan to tackle it, you might want to.

per pixel drawing in OpenGL

I used to write small games with 'per pixel' drawing,
I mean with some SetPixel(x,y,color) function or such.
I am also interested in OpenGL but do not know it much.
Is it a good (fast) way to do a per pixel drawing in OpenGL ?
It would be good for example to use textured quads as a sprites,
or whole application background screen, with possibility to
set distinct pixel with some kind of my own SetPixel routine
i would write... or any other way - but it should be efficient
as much as it cans
(especialy im interested in basic fundamenta 1.0 version of OGL)
You can set a projection that will map vertex coordinates 1:1 to pixel coordinates:
glViewport(0, 0, window_width, window_height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, window_width, 0, window_height, -1, 1);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
From here on, vertex X,Y coordinates are in pixels with the origin in the lower left corner. In theory you could use the immediate mode with GL_POINT primitives. But it's a much better idea to batch things up. Instead of sending each point indivisually create an array of all the points you want to draw:
struct Vertex
{
GLfloat x,y,red,green,blue;
};
std::vector<Vertex> vertices;
/* fill the vertices vector */
This you can OpenGL point to…
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);
/* Those next two calls don't copy the data, they set a pointer, so vertices must not be deallocated, as long OpenGL points to it! */
glVertexPointer(2, GL_FLOAT, sizeof(Vertex), &vertices[0].x);
glColorPointer(3, GL_FLOAT, sizeof(Vertex), &vertices[0].red);
…and have it access and draw it all with a single call:
glDrawArrays(GL_POINTS, 0, vertices.size();
You really don't want to do this.
Is it a good (fast) way to do a per pixel drawing in OpenGL ?
There is no good or fast way to do this. It is highly discouraged due to the speed.
The proper way, although not easy (or in some cases possible) in OGL 1, is to use pixel shaders or blend modes. That is the only correct way, anything else is hacking around the entire system.
Depending on how the data needs modified, vertex colors and blend modes may be able to solve the some uses. It won't tint each pixel individually, but you can modify the texture must faster.
To do it, you can draw single-pixel quads (although care must be taken to offset them and handle filtering to prevent blurring) or you can get texture data and manipulate it later. Both will be unbelievably slow, but could function.
Working with the texture data is probably simpler and may be slightly faster.

How to make fading-to-black effect with OpenGL?

Im trying to achieve fade-to-black effect, but i dont know how to do it. I tried several things but they fail due to how opengl works
I will explain how it would work:
If i draw 1 white pixel and move it around each frame for one pixel to some direction, each frame the screen pixels will get one R/G/B value less (of range 0-255), thus after 255 frames the white pixel will be fully black. So if i move the white pixel around, i would see a gradient trail going from white to black evenly 1 color value difference compared to previous pixel color.
Edit: I would prefer to know non-shader way of doing this, but if its not possible then i can accept shader-way too.
Edit2: Since there is some confusion around here, I would like to tell that i can do this kind of effect already by drawing a black transparent quad over my whole scene. BUT, this does not work as i want it to work; there is a limit on the darkness the pixels can get, so it will always leave some of the pixels "visible" (above zero color value) because: 1*0.9 = 0.9 -> rounded to 1 again, etc. I can "fix" this by making the trail shorter, but i want to be able to adjust the trail lenght as much as possible and instead of bilinear (if thats the right word) interpolation i want linear (so it would always reduce -1 from each r,g,b value in 0-255 scale, instead of using a percent value).
Edit3: Still some confusion left, so lets be clear: i want to improve the effect that is done by disabling GL_COLOR_BUFFER_BIT from glClear(), i dont want to see the pixels on my screen FOREVER, so i want to make them darker in time, by drawing a quad over my scene that will reduce each of the pixels color value by 1 (in 0-255 scale).
Edit4: I'll make it simple, i want OpenGL method for this, the effect should use as little power, memory or bandwidth as possible. this effect is supposed to work without clearing the screen pixels, so if i draw a transparent quad over my scene, the previous pixels drawn will get darker etc. But as explained above few times, its not working very well. The big NO's are: 1) reading pixels from screen, modifying them one by one in a for loop and then uploading back. 2) rendering my objects X times with different darknesses to emulate the trail effect. 3) multiplying the color values is not an option since it wont make the pixels into black, they will stay on the screen forever at certain brightness (see explanation somewhere above).
If i draw 1 white pixel and move it around each frame for one pixel to some direction, each frame the screen pixels will get one R/G/B value less (of range 0-255), thus after 255 frames the white pixel will be fully black. So if i move the white pixel around, i would see a gradient trail going from white to black evenly 1 color value difference compared to previous pixel color.
Before I explain how to do this, I would like to say that the visual effect you're going for is a terrible visual effect and you should not use it. Subtracting a value from each of the RGB colors will produce a different color, not a darker version of the same color. The RGB color (255,128,0), if you subtract 1 from it 128 times, will become (128, 0, 0). The first color is brown, the second is a dark red. These are not the same.
Now, since you haven't really explained this very well, I have to make some guesses. I am assuming that there are no "objects" in what you are rendering. There is no state. You're simply drawing stuff at arbitrary locations, and you don't remember what you drew where, nor do you want to remember what was drawn where.
To do what you want, you need two off-screen buffers. I recommend using FBOs and screen-sized textures for these. The basic algorithm is simple. You render the previous frame's image to the current image, using a blend mode that "subtracts 1" from the colors you write. Then you render the new stuff you want to the current image. Then you display that image. After that, you switch which image is previous and which is current, and do the process all over again.
Note: The following code will assume OpenGL 3.3 functionality.
Initialization
So first, during initialization (after OpenGL is initialized), you must create your screen-sized textures. You also need two screen-sized depth buffers.
GLuint screenTextures[2];
GLuint screenDepthbuffers[2];
GLuint fbos[2]; //Put these definitions somewhere useful.
glGenTextures(2, screenTextures);
glGenRenderbuffers(2, screenDepthbuffers);
glGenFramebuffers(2, fbos);
for(int i = 0; i < 2; ++i)
{
glBindTexture(GL_TEXTURE_2D, screenTextures[i]);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, SCREEN_WIDTH, SCREEN_HEIGHT, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glBindTexture(GL_TEXTURE_2D, 0);
glBindRenderbuffer(GL_RENDERBUFFER, screenDepthBuffers[i]);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, SCREEN_WIDTH, SCREEN_HEIGHT);
glBindRenderbuffer(GL_RENDERBUFFER, 0);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo[i]);
glFramebufferTexture(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, screenTextures[i], 0);
glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, screenDepthBuffers[i]);
if(glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
//Error out here.
}
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
}
Drawing Previous Frame
The next step will be drawing the previous frame's image to the current image.
To do this, we need to have the concept of a previous and current FBO. This is done by having two variables: currIndex and prevIndex. These values are indices into our GLuint arrays for textures, renderbuffers, and FBOs. They should be initialized (during initialization, not for each frame) as follows:
currIndex = 0;
prevIndex = 1;
In your drawing routine, the first step is to draw the previous frame, subtracting one (again, I strongly suggest using a real blend here).
This won't be full code; there will be pseudo-code that I expect you to fill in.
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbos[currIndex]);
glClearColor(...);
glClearDepth(...);
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
glActiveTexture(GL_TEXTURE0 + 0);
glBindTexture(GL_TEXTURE_2D, screenTextures[prevIndex]);
glUseProgram(BlenderProgramObject); //The shader will be talked about later.
RenderFullscreenQuadWithTexture();
glUseProgram(0);
glBindTexture(GL_TEXTURE_2D, 0);
The RenderFullscreenQuadWithTexture function does exactly what it says: renders a quad the size of the screen, using the currently bound texture. The program object BlenderProgramObject is a GLSL shader that does our blend operation. It fetches from the texture and does the blend. Again, I'm assuming you know how to set up a shader and so forth.
The fragment shader would have a main function that looks something like this:
shaderOutput = texture(prevImage, texCoord) - (1.0/255.0);
Again, I strongly advise this:
shaderOutput = texture(prevImage, texCoord) * (0.05);
If you don't know how to use shaders, then you should learn. But if you don't want to, then you can get the same effect using a glTexEnv function. And if you don't know what those are, I suggest learning shaders; it's so much easier in the long run.
Draw Stuff As Normal
Now, you just render everything you would as normal. Just don't unbind the FBO; we still want to render to it.
Display the Rendered Image on Screen
Normally, you would use a swapbuffer call to display the results of your rendering. But since we rendered to an FBO, we can't do that. Instead, we have to do something different. We must blit our image to the backbuffer and then swap buffers.
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
glBindFramebuffer(GL_READ_FRAMEBUFFER, fbos[currIndex]);
glBlitFramebuffer(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, 0, SCREEN_WDITH, SCREEN_HEIGHT, GL_COLOR_BUFFER_BIT, GL_NEAREST);
glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
//Do OpenGL swap buffers as normal
Switch Images
Now we need to do one more thing: switch the images that we're using. The previous image becomes current and vice versa:
std::swap(currIndex, prevIndex);
And you're done.
You may want to render a black rectangle with alpha going from 1.0 to 0.0 using glBlendFunc (GL_ONE, GL_SRC_ALPHA).
Edit in response to your comment (reply doesn't fit in a comment):
You cannot fade single pixels depending on their age with a simple fade-to-black operation. Usually a render target does not "remember" what has drawn to it in previous frames. I could think of a way to do this by alternatingly rendering to one of a pair of FBOs and using their alpha channel for it, but you needed a shader there. So what you would do is first render the FBO containing the pixels at their previous positions, decreasing their alpha value by one, dropping them when alpha == 0, otherwise darkening them whenever their alpha decreases, then render the pixels at their current positions with alpha == 255.
If you only have moving pixels:
render FBO 2 to FBO 1, darkening each pixel in it by a scale (skip during first pass)
render moving pixels to FBO 1
render FBO 1 to FBO 2 (FBO 2 is the "age" buffer)
render FBO 2 to screen
If you want to modify some scene (i.e. have a scene and moving pixels in it):
set glBlendFunc (GL_ONE, GL_ZERO)
render FBO 2 to FBO 1, reducing each alpha > 0.0 in it by a scale (skip during first pass)
render moving pixels to FBO 1
render FBO 1 to FBO 2 (FBO 2 is the "age" buffer)
render the scene to screen
set glBlendFunc (GL_ONE, GL_SRC_ALPHA)
render FBO 2 to screen
Actually the scale should be (float) / 255.0 / 255.0 to make the components equally fade away (and not one that started at a lower value become zero before the others do).
If you only have a few moving pixels, you could re-render the pixel at all previous positions up to 255 "ticks" back.
Since you need to re-render each of the pixels anyway, just render each one with the proper color gradient: Darker, the older the pixel is. If you have a real lot of pixels, the dual FBO approach
might work.
I am writing ticks, and not frames, because frames can take a varying amount of time depending on renderer and hardware, but you probably want to have the pixel trail fade away within a constant time. That means you need to dim each pixel only after so-and-so many milliseconds, keeping their color for the frames in between.
One non-shader way of doing this, especially if the fade to black is the only thing that is going on the screen is to grab the contents of the screen via readpixels iirc, pop those into a texture, and put a rectangle up onto the screen with that texture, then you can modulate the color of the rectangle to towards black to do the efect that you want to accomplish.
It is the drivers, Windows itself does not support OpenGL or only a low Version, I think 1.5. All newer versions come with drivers from ATI or NVIDIA, Intel etc.
Are you using different cards?
What version of OpenGL are you effectivly using?
It's situations like this that make it so I cannot use pure OpenGL. I am not sure if your project has room for it (which it may not if you're using another windowing API), or if the added complexity would be worth it, but adding a 2D library like SDL which works with OpenGL would allow you to directly work with the display surface's pixels in a reasonable fashion, as well as just pixels in general, which OpenGL generally doesn't make easy.
Then all you would need to do is run through the display surface's pixels before OpenGL renders it's geometry, and subtract 1 from each RGB component.
That's the easiest solution I can see anyway, if using additional libraries with OpenGL is an option.