opengl stencil buffer multiple simultaneous uses - opengl

I've managed to successfully use OpenGL's stencil buffer for a single instance in a scene. However, I'm unsure of how to use it in two different places in the same scene. Defining two stencil shapes in sequence prevents either from working, and my attempts to nest one use inside of the other didn't work either. I've seen examples of multiple uses of stencil buffer in the same scene, but I was not able to understand or adapt the code. Here is what I've been able to get working so far.
void display(void) {
// store floor shape in stencil buffer
glClearStencil(0);
glClear(GL_STENCIL_BUFFER_BIT);
glEnable(GL_STENCIL_TEST);
glStencilMask(1);
glStencilFunc(GL_ALWAYS, 1, 1);
glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
floor->draw();
glBegin(GL_QUADS); //
glVertex3f(0.0, 0.0, 0.0); //
glVertex3f(0.0, 100.0, 0.0); //
glVertex3f(0.0, 100.0, 100.0); //
glVertex3f(0.0, 0.0, 100.0); //
glEnd(); //
// draw scene outside floor
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
scene();
// draw reflection of scene in floor
glStencilFunc(GL_EQUAL, 1, 1);
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
glPushMatrix();
glScalef(1.0, 1.0, -1.0);
scene();
glPopMatrix();
glDisable(GL_STENCIL_TEST);
// draw translucent floor
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glColor4f(1.0, 1.0, 1.0, 0.7);
floor->draw();
//windowHole();
glDisable(GL_BLEND);
glFlush();
glutSwapBuffers();
glutPostRedisplay();
}

Related

Colors disappear after drawing image

I am trying to draw a sphere and a cube at the same time on my screen. But the colors of my cube(which gets drawn first) dissapear. I don't understand why.
the sphere on the right is fine. But my cube on the left isn't.
I added texture to both:
I can perfectly draw both of them seperately, but when I try to draw both of them on one widget something goes wrong.
I tought the popping and pushing would solve this issue, but it doesn't.
code:
void MyGLWidget::drawCube()
{
glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
glLoadIdentity();
gluLookAt(position,0.5,-0.1,-0.5,-0.5,0,0,0,1);
glTranslatef( 0.5, 0, 0.0);
glRotatef(getCubeAngle(), 1.0f, 0.0f, 0.0f);
glTranslatef(0, 0, 0);
glDisable(GL_TEXTURE_GEN_S);
glDisable(GL_TEXTURE_GEN_T);
glPushMatrix();
glBindTexture(GL_TEXTURE_2D, texture[0]);
glBegin(GL_QUADS);
//back
glTexCoord2f(0.0, 1.0); glVertex3f(-0.1, 0.1,-0.1 );
glTexCoord2f(1.0, 1.0); glVertex3f(0.1, 0.1,-0.1);
glTexCoord2f(1.0, 0.0); glVertex3f(0.1,-0.1,-0.1);
glTexCoord2f(0.0, 0.0); glVertex3f(-0.1,-0.1,-0.1);
/*rest of cube gets drawn*/
glEnd();
glFlush();
glPopMatrix();
}
void MyGLWidget::drawSun()
{
glPushMatrix();
glLoadIdentity();
glBindTexture(GL_TEXTURE_2D, texturePlanet[0]);
glPushMatrix();
glScalef(1,1,1);
glLoadIdentity();
GLUquadricObj *quadric=gluNewQuadric();
gluQuadricTexture(quadric, GLU_TRUE);
gluQuadricNormals(quadric, GLU_SMOOTH);
glEnable(GL_TEXTURE_2D); //
glBindTexture(GL_TEXTURE_2D,texturePlanet[0]);//
gluSphere(quadric, 0.25, 360,360);
glDisable(GL_TEXTURE_2D);//
gluDeleteQuadric(quadric);
glPopMatrix();
}
void MyGLWidget::paintGL()
{
drawCube();
drawSun();
}
It is because In your cube drawing, you didn't enable texturing.
glEnable(GL_TEXTURE_2D); //ADD THIS TO ENABLE TEXTURING
glPushMatrix();
glBindTexture(GL_TEXTURE_2D, texture[0]);
glBegin(GL_QUADS);
//back
glTexCoord2f(0.0, 1.0); glVertex3f(-0.1, 0.1,-0.1 );
glTexCoord2f(1.0, 1.0); glVertex3f(0.1, 0.1,-0.1);
glTexCoord2f(1.0, 0.0); glVertex3f(0.1,-0.1,-0.1);
glTexCoord2f(0.0, 0.0); glVertex3f(-0.1,-0.1,-0.1);
/*rest of cube gets drawn*/
glEnd();
glFlush();
glPopMatrix();
glDisable(GL_TEXTURE_2D); // ADD THIS TO DISABLE TEXTURING

OpenGL texture with transparency (alpha)

I'm trying to render a texture with part opaque color and other part with transparency.
This is my draw function for the object:
void drawHighGrass(){
glDisable(GL_LIGHTING);
glClearColor(1.0, 1.0, 1.0, 1.0);
glColor4f(1.0, 1.0, 1.0, 1.0);
glDisable(GL_DEPTH_TEST);
glDepthMask(GL_FALSE);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, texturas[HIGH_GRASS]);
glPushMatrix();
//glTranslatef(1000, 0, 1000);
glBegin(GL_QUADS);
glTexCoord2f(0.0f, 0.0f); glVertex3f(0, 0, 0);
glTexCoord2f(1.0f, 0.0f); glVertex3f(100, 0, 0);
glTexCoord2f(1.0f, 1.0f); glVertex3f(100, 40, 0);
glTexCoord2f(0.0f, 1.0f); glVertex3f(0, 40, 0);
glEnd();
glPopMatrix();
glDisable(GL_TEXTURE_2D);
glEnable(GL_DEPTH_TEST);
glDisable(GL_BLEND);
glDepthMask(GL_TRUE);
glEnable(GL_LIGHTING);
}
The problem is that in the transparent part it's showing solid white. I can make the texture transparent by using glColor4f(1.0, 1.0, 1.0, 0.5) but that's not what I want because it makes the entire texture transparent and not only the transparent part.
I've checked, my texture files is a PNG with transparency.
Restating the solution here so others can find it easily.
Your rendering code seems to be correct, so what seems to have been the problem was the texture loading code. When loading a texture, you must be sure that you are passing in the correct flags for the internal texture pixel format (GL_RGBA8, GL_RGBA16, etc.) as well as the source image pixel format (GL_RGBA or GL_BGRA, etc.).

fastest way to set every pixel

I have programmed a little raytracer in c++,
and want to show the raytraced image in a window.
I tried using a pixel buffer object in opengl,
then map the buffer into memory and manipulate the pixels one by one,
but at fullscreen resolution 1920x1080, I only get 4 fps
without raytracing and without changing the pixels colors
just the mapping and unmapping!
so i'm basically looking for the fastest way to display a raytraced image in a window.
i'm currently doing this way:
glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, pbo);
glBufferDataARB(GL_PIXEL_UNPACK_BUFFER_ARB, width * height * 4, 0, GL_STREAM_DRAW_ARB);
if (pixels = (uint*)glMapBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, GL_WRITE_ONLY_ARB))
{
//modify pixels
glUnmapBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB);
}
else
return;
//copy from pbo to texture
glBindTexture(GL_TEXTURE_2D, pbo_texture);
glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, pbo);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_BGRA, GL_UNSIGNED_BYTE, 0);
glEnable(GL_TEXTURE_2D);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
//draw image
glColor4f(1.0, 1.0, 1.0, 1.0);
glBindTexture(GL_TEXTURE_2D, pbo_texture);
glBegin(GL_QUADS);
glTexCoord2f(0.0, 1.0); glVertex3f(-1.0, -1.0, 0.0);
glTexCoord2f(1.0, 1.0); glVertex3f( 1.0, -1.0, 0.0);
glTexCoord2f(1.0, 0.0); glVertex3f( 1.0, 1.0, 0.0);
glTexCoord2f(0.0, 0.0); glVertex3f(-1.0, 1.0, 0.0);
glEnd();
glutSwapBuffers();
glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0);
glBindTexture(GL_TEXTURE_2D, 0);
Check the memory traversal if you use loops. You should traverse your buffer in the right order, otherwise you may have cache miss at each iteration. If you use nested loops sometimes you only have to switch the x/y iteration order.
Also, don't read data from graphic memory. It tends to be slow. Only write to PBO.
It looks like a syncro issue. I'm not sure you need to map pbo at every frame. Check this link on OpenGL Pixel Buffer Object (PBO). There's also a workaround for stalls which could improve things

2D map render in opengl

I use some small chip picture to make up a map.
When it's static, it's all ok.But when I use the glTranslated to move it.
It always has some small shiver.
I use this to init
glEnable(GL_FLAT);
glEnable(GL_DEPTH_TEST);
glEnable(GL_TEXTURE_2D);
glEnable(GL_ALPHA_TEST);
glAlphaFunc(GL_GREATER , 0.5);
I use this in display function.
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glPushMatrix();
glTranslated(-_viewpos.x, _viewpos.y, 0);
if(_displayFunc)
{
_displayFunc(this, time0);
}
glPopMatrix();
and this to render a picture
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, _texture);
glBegin(GL_QUADS);
glTexCoord2d(0.0, 0.0);glVertex2d(p1.x, p1.y);
glTexCoord2d(0.0, 1.0);glVertex2d(p2.x, p2.y);
glTexCoord2d(1.0, 1.0);glVertex2d(p3.x, p3.y);
glTexCoord2d(1.0, 0.0);glVertex2d(p4.x, p4.y);
glDisable(GL_TEXTURE_2D);
glEnd();
I think the problem maybe is that when i change the coordinate from int to double,
It may have a pixel offset?
How to solve it?

Reflection and depth in OpenGL

I'm trying to create a mirror in OpenGL. Most references I've found recommend using the stencil buffer to define the boundaries of the mirror itself and using a combination of translation and scaling matrices for the actual reflection. I managed to get this to work when the scene is viewed so that no objects are in front of the mirror. However, when an object is in front of the mirror the overlapping part is not shown, making it look as if it's behind the mirror. There's a good chance that I'm misunderstanding how the stencil buffer works, as this is the first time I've tried using it, but I could also be making some mistake regarding depth or something else. I'd appreciate any suggestions. Here is the code.
#include <gl/glut.h>
// perspective
void view(void) {
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-2.0, 2.0, -2.0, 2.0, -2.0, 2.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glRotatef(-85.0, 1.0, 0.0, 0.0);
glScalef(0.25, 0.25, 0.25);
}
void init(void) {
glEnable(GL_DEPTH_TEST);
glClearStencil(0);
glEnable(GL_STENCIL_TEST);
}
void mirror(GLboolean inside, GLfloat vertSet[4][3]) {
GLint i;
if(inside)
glBegin(GL_QUADS); // draw inside of mirror
else
glBegin(GL_LINE_LOOP); // draw frame of mirror
for(i = 0; i < 4; i++)
glVertex3fv(vertSet[i]);
glEnd();
}
void scene(void) {
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glRotatef(90.0, 1.0, 0.0, 0.0);
glutSolidTeapot(1.0);
glPopMatrix();
}
void display(void) {
GLfloat vertSet1[4][3] = {{-3.0, 3.0, 0.0}, {2.0, 3.0, 0.0},
{2.0, 3.0, 2.0}, {-3.0, 3.0, 2.0}};
view();
// store mirror shape in the stencil buffer.
glClear(GL_STENCIL_BUFFER_BIT);
glStencilFunc(GL_ALWAYS, 1, 1);
glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
mirror(true, vertSet1);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// draw mirror frame.
glColor3f(0.0, 0.0, 0.0);
mirror(false, vertSet1);
// draw scene outside mirror
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
glStencilFunc(GL_NOTEQUAL, 1, 1);
scene();
// draw reflection of scene in mirror
glStencilFunc(GL_EQUAL, 1, 1);
glTranslatef(0.0, 3.0, 0.0);
glScalef(1.0, -1.0, 1.0);
glTranslatef(0.0, -3.0, 0.0);
scene();
glFlush();
glutSwapBuffers();
glutPostRedisplay();
}
int main (int argc, char **argv) {
glutInit(&argc, argv);
glutInitWindowSize(500, 500);
glutInitWindowPosition(0, 0);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_STENCIL | GLUT_DEPTH);
glutCreateWindow("");
glClearColor(1.0, 1.0, 1.0, 0.0);
init();
glutDisplayFunc(display);
glutMainLoop();
}
The idea of the stencil is, that you draw it when you'd normally render the mirror's glass within the scene. You want the drawing of the stencil to be depth tested. When you finished rendering your scene, you add a clip plane in the plane of the mirror, then you clear the depth buffer and redraw the scene. Since you clear the depth buffer you need the stencil to be depth tested first to make the mirror not overdraw already drawn objects in the world.
Note that drawing a mirror is essentially the same as drawing a portal.
This is my code for doing reflection in old opengl, hope this helps
Please note that most of the code comes from NeHe tutorial: http://nehe.gamedev.net/tutorial/clipping__reflections_using_the_stencil_buffer/17004/
double eqr[] = { 0.0f, -1.0f, 0.0f, 0.0f };
glColorMask(0, 0, 0, 0);
glEnable(GL_STENCIL_TEST);
glStencilFunc(GL_ALWAYS, 1, 1);
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
glDisable(GL_DEPTH_TEST);
DrawFloor(); // draw flor to the stencil buffer
glColorMask(1, 1, 1, 1);
glStencilFunc(GL_EQUAL, 1, 1);
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
glEnable(GL_CLIP_PLANE0);
glClipPlane(GL_CLIP_PLANE0, eqr);
glPushMatrix();
glScalef(1.0f, -1.0f, 1.0f);
//glLightfv(GL_LIGHT0, GL_POSITION, light_pos);
glFrontFace(GL_CW);
glTranslatef(0.0f, 0.3f, 0.0);
RenderScene();
glFrontFace(GL_CCW);
glPopMatrix();
glDisable(GL_CLIP_PLANE0);
glDisable(GL_STENCIL_TEST);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glColor4f(0.6f, 0.7f, 1.0f, 0.5f);
DrawFloor(); // draw floor second time
glDisable(GL_BLEND);
// draw normal scene
glPushMatrix();
glColor3f(1.0f, 1.0f, 1.0f);
glTranslatef(0.0f, 0.3f, 0.0);
RenderScene();
glPopMatrix();
For better result you might use RenderToTexture or use cube maps