Transparency with Scene Textures
What I want to do is render an object to a scene and copy it to a texture using glCopyTexImage2D. That much is doable. The problem is that the clear color pixels are also copied to the texture and thusly end up in a subsequent scene when the texture is used. I want the extraneous pixels around the desired object to become transparent when used in a subequent scene.
For example, if the clear color is black and I draw, say, a rabbit, I can copy the image of that rabbit to a texture using glCopyTexImage2D. Then, let's say I draw a second scene where there's a 2D holographic projection of the rabbit in the middle of an advanced war room. If I use the texture as-is, the resulting render will show a black box with a rabbit in it.
The quandary is that I want only the rabbit, but not the blackness around it. Try as I may, however, I can't find any option to remove the unwanted pixels that take on the clear color. Is there an easy way to do this, or should I learn to live with the extra blackness?
Hello,
after your saved your frame buffer into the texture and before clearing your scene, you should keep the depth buffer, and use it as alpha channel in your texture. Indeed, untouched pixels are going to be at the maximum depth.
If it's not possible to inject alpha component, then use two texture, one with the frame buffer and the other with the depth buffer... and then just combine these two when rendering your hologram.
Hope it helps,
JFD
after your saved your frame buffer into the texture and before clearing your scene, you should keep the depth buffer, and use it as alpha channel in your texture. Indeed, untouched pixels are going to be at the maximum depth.
If it's not possible to inject alpha component, then use two texture, one with the frame buffer and the other with the depth buffer... and then just combine these two when rendering your hologram.
Hope it helps,
JFD
That would do the trick, but the idea of using the depth values as alpha is new to me. Is there an easy way to implement this with hardware accelleration?
If I understand your problem correctly then you should be able to filter out the black pixels by simply using the blending function. Maybe something like the following.
glEnable(GL_BLEND);glBlendFunc(GL_SRC_COLOR, GL_ONE);glColor4f(1,1,1,1);// Render texture hereglDisable(GL_BLEND);
Hope that helps
The problem is that the model I cast into a texture may very well have black pixels in it. Specifically, may include pixels the same color as the clear color. I need a solution that specifically removes any pixels where polygons aren't.
Also, GL_SRC_COLOR isn't a valid function for sfactor of glBlendFunc.
Also, GL_SRC_COLOR isn't a valid function for sfactor of glBlendFunc.
If you're copying into an RGBA texture (and the framebuffer has an alpha channel) then you will also be copying the alpha of the background color, which should be 0 for any pixel you haven't rendered to. Then you can use blending/alpha testing and/or the texture environment modes to ignore the texels with 0 alpha.
After some research and some experimentation, I'm still without satisfactory results. What I'm doing is the following:
Setup:
- Setting up an OpenGL Rendering Context in Win32 with PFD_TYPE_RGBA in both dwFlags and iPixelType of the pixel format descriptor
Each frame:
- Using glClearColor with values 0, 0, 0, 0
- Resetting the framebuffer with glClear; color and depth bits
- Rendering a textured cube to a viewport of 256×256 pixels
- Copying to a texture with glCopyTexImage2D; internal format of GL_RGBA
- Using glClearColor with values 0, 0.6, 1, 0
- Resetting the framebuffer with glClear; color and depth bits
- Enabling blending with GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA
- Drawing a triangle strip with the previously-copied texture mapped to it in a full-window viewport
- Disabling blending
- Swapping buffers
- Deleting temporary texture
The result is a textured square in the new scene with the textured cube from the previous scene within it. However, the black texels of the previous scene's clear color still exist and do not become transparent. It's as though blending were not enabled.
Could someone provide a working example that I can refer to?
Here is a screenshot to clarify:
Setup:
- Setting up an OpenGL Rendering Context in Win32 with PFD_TYPE_RGBA in both dwFlags and iPixelType of the pixel format descriptor
Each frame:
- Using glClearColor with values 0, 0, 0, 0
- Resetting the framebuffer with glClear; color and depth bits
- Rendering a textured cube to a viewport of 256×256 pixels
- Copying to a texture with glCopyTexImage2D; internal format of GL_RGBA
- Using glClearColor with values 0, 0.6, 1, 0
- Resetting the framebuffer with glClear; color and depth bits
- Enabling blending with GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA
- Drawing a triangle strip with the previously-copied texture mapped to it in a full-window viewport
- Disabling blending
- Swapping buffers
- Deleting temporary texture
The result is a textured square in the new scene with the textured cube from the previous scene within it. However, the black texels of the previous scene's clear color still exist and do not become transparent. It's as though blending were not enabled.
Could someone provide a working example that I can refer to?
Here is a screenshot to clarify:
Hello again :)
why don't you give a try to what i said you? i think it could be easy to implement it.
when you clear tour scene, the depth buffer gets cleared (by default) by 1.0
after your first scene is drawed the pixels with 1.0 in the depth buffer are those you want invisible, its just a lookup in a shader.
hope it helps,
JFD
why don't you give a try to what i said you? i think it could be easy to implement it.
when you clear tour scene, the depth buffer gets cleared (by default) by 1.0
after your first scene is drawed the pixels with 1.0 in the depth buffer are those you want invisible, its just a lookup in a shader.
hope it helps,
JFD
Take a look at my prevoius post to see the order in which I am doing things. 0 or 1 for the fourth parameter of glClearColor, it doesn't change the results. Can you provide a full-source example of a working scene texture with transparency?
Quote:Original post by Guy PerfectHere is the source for an extremely simple GLUT app rife with bad coding practices...
Take a look at my prevoius post to see the order in which I am doing things. 0 or 1 for the fourth parameter of glClearColor, it doesn't change the results. Can you provide a full-source example of a working scene texture with transparency?
#include <iostream>#include <gl\glut.h>GLsizei winW = 512;GLsizei winH = 512;GLuint tex = 0;GLsizei texW = 256;GLsizei texH = 256;void Init(){ //Create empty texture to copy to glGenTextures(1, &tex); glBindTexture(GL_TEXTURE_2D, tex); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, texW, texH, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);}void DrawObject(){ glBegin(GL_QUADS); glColor4f(1.0f, 0.0f, 0.0f, 1.0f); glVertex3f(-0.5f, -0.5f, 0.5f); glVertex3f(0.5f, -0.5f, 0.5f); glVertex3f(0.5f, 0.5f, 0.5f); glVertex3f(-0.5f, 0.5f, 0.5f); glColor4f(0.0f, 1.0f, 0.0f, 1.0f); glVertex3f(0.5f, -0.5f, 0.5f); glVertex3f(0.5f, -0.5f, -0.5f); glVertex3f(0.5f, 0.5f, -0.5f); glVertex3f(0.5f, 0.5f, 0.5f); glColor4f(0.0f, 0.0f, 1.0f, 1.0f); glVertex3f(-0.5f, 0.5f, 0.5f); glVertex3f(-0.5f, 0.5f, -0.5f); glVertex3f(0.5f, 0.5f, -0.5f); glVertex3f(0.5f, 0.5f, 0.5f); glEnd();}void display(){ glMatrixMode(GL_MODELVIEW); glLoadIdentity(); //Render object and copy to texture { glViewport(0, 0, texW, texH); glClearColor(0.0f, 0.0f, 0.0f, 0.0f); glClear(GL_COLOR_BUFFER_BIT); glPushMatrix(); glRotatef(20.0f, 1.0f, 0.0f, 0.0f); glRotatef(-30.0f, 0.0f, 1.0f, 0.0f); DrawObject(); glPopMatrix(); glBindTexture(GL_TEXTURE_2D, tex); glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, texW, texH); } //Clear framebuffer and render the texture to the screen { glViewport(0, 0, winW, winH); glClearColor(0.1f, 0.2f, 0.3f, 0.0f); glClear(GL_COLOR_BUFFER_BIT); glEnable(GL_BLEND); glEnable(GL_TEXTURE_2D); glBegin(GL_QUADS); glTexCoord2f(0.0f, 0.0f); glVertex2f(-0.5f, -0.5f); glTexCoord2f(1.0f, 0.0f); glVertex2f(0.5f, -0.5f); glTexCoord2f(1.0f, 1.0f); glVertex2f(0.5f, 0.5f); glTexCoord2f(0.0f, 1.0f); glVertex2f(-0.5f, 0.5f); glEnd(); glDisable(GL_TEXTURE_2D); glDisable(GL_BLEND); } glutSwapBuffers(); GLenum err = glGetError(); if(err != GL_NO_ERROR) { std::cout << "GL ERROR (" << std::hex << std::showbase << err << "): " << gluErrorString(err) << std::endl; }}void reshape(int w, int h){ winW = w; winH = h; glViewport(0, 0, winW, winH); glMatrixMode(GL_PROJECTION); glLoadIdentity();}void keyboard(unsigned char key, int x, int y){ switch(key) { case 27: exit(0); break; default: break; }}void idle(){ glutPostRedisplay();}int main(int argc, char **argv){ glutInit(&argc, argv); glutInitDisplayMode(GLUT_DOUBLE | GLUT_ALPHA); glutInitWindowSize(winW, winH); glutInitWindowPosition(100, 100); glutCreateWindow("test"); glutDisplayFunc(display); glutReshapeFunc(reshape); glutKeyboardFunc(keyboard); glutIdleFunc(idle); Init(); glutMainLoop(); return 0;}
If you don't enable blending in the second pass or you set the clear color's alpha to 1.0f in the first pass, you get the black border. Otherwise it works just like it should. Note that you have to get a framebuffer with an alpha component (ie: in GLUT this is done by passing the GLUT_ALPHA bit to glutInitDisplayMode).
EDIT: For binary (on/off) transparency it's "better" to use alpha testing instead of blending.
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement