PDA

View Full Version : Need help drawing coplanar polygons

dmats
11-07-2008, 10:54 AM
Hello,
I'm new to OpenGL and I'm hoping someone can help me out with this.

I have a red rectangle and I want to be able to draw triangles on either side of it. I have a set of data points that give me the vertices of the triangles that I want to draw. The problem is that they lie on the same plane as the red rectangle.

I've read up on z-fighting and I understand that, but I don't think it fixes my problem. I want to draw the triangles on one side of the rectangle and have the other side remain the red rectangle. Basically, it's like having a piece of paper and I want to write on one side of it but not be able to see that writing from the other side.

I'm not sure what kind of problem I'm dealing with. Is it a blending problem, a depth problem, or maybe even a texturing problem? Maybe it's a simple as just adding a slight offset to my triangles so they don't reside in the same plane (the problem is, when I zoom in, I don't want to see a gap between the triangles and rectangle)? I'd appreciate any help anyone could give me.

Thank you!

trinitrotoluene
11-07-2008, 12:01 PM
If your triangles is entirely inside your rectangle, you can use the stencil buffer to do that. I will try it and if it works, I will post the algorithm.

trinitrotoluene
11-07-2008, 01:14 PM
There is a first solution. When I draw the triangles over the rectangle I use the counter clock wise winding to view it on recto and clock wise winding on verso.

#include <iostream>

#include <GL/glut.h>
#include <GL/glu.h>

static float angle = 0.0;

static void draw(void);
static void drawQuads(void);
static void init(void);
static void redraw(void);
static void reshape(int w,int h);

int main(int argc,char **argv)
{
glutInit(&amp;argc,argv);

glutInitDisplayMode(GLUT_RGBA|GLUT_DEPTH|GLUT_STEN CIL|GLUT_DOUBLE);
glutInitWindowSize(640,480);
glutCreateWindow("Ortho");

glutReshapeFunc(reshape);
glutDisplayFunc(draw);
glutIdleFunc(redraw);

init();
glutMainLoop();

return(EXIT_SUCCESS);
}

void draw(void)
{
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL _STENCIL_BUFFER_BIT);
glLoadIdentity();
angle+=1.0f;
glRotatef(angle,0.0,1.0,0.0);
drawQuads();

glutSwapBuffers();
}

void drawQuads(void)
{

glEnable(GL_STENCIL_TEST);
glStencilFunc(GL_ALWAYS, 0x1, 0x1);
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);

glColor4f(1.0,1.0,1.0,1.0);

glBegin(GL_QUADS);
glVertex4f(-100.0,-100.0,0.0,1.0);
glVertex4f(100.0,-100.0,0.0,1.0);
glVertex4f(100.0,100.0,0.0,1.0);
glVertex4f(-100.0,100.0,0.0,1.0);
glEnd();

glStencilFunc(GL_EQUAL, 0x1, 0x1);
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);

glDepthMask(GL_FALSE);
glEnable(GL_CULL_FACE);
glDepthFunc(GL_ALWAYS);

glColor4f(1.0,0.0,0.0,1.0);
glBegin(GL_TRIANGLE_STRIP);
glVertex4f(-50.0,-50.0,0.0,1.0);
glVertex4f(50.0,-50.0,0.0,1.0);
glVertex4f(0.0,50.0,0.0,1.0);
glEnd();

glColor4f(0.0,1.0,0.0,1.0);
glBegin(GL_TRIANGLE_STRIP);
glVertex4f(-50.0,-50.0,0.0,1.0);
glVertex4f(0.0,50.0,0.0,1.0);
glVertex4f(50.0,-50.0,0.0,1.0);
glEnd();

glDepthMask(GL_TRUE);
glDepthFunc(GL_LESS);
glDisable(GL_CULL_FACE);
glDisable(GL_STENCIL_TEST);

}

void init(void)
{
glEnable(GL_DEPTH_TEST);
glEnable(GL_CULL_FACE);
}

void reshape(int w,int h)
{
glViewport(0,0,w,h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
// gluPerspective(65.0,(GLfloat)width/(GLfloat)height,1.0,100.0);
glOrtho(-200,200,-200,200,-1000.0,1000.0);
// glOrtho(0.0,(GLdouble)width,0,(GLdouble)height,-1.0,100.0);
glMatrixMode(GL_MODELVIEW);
}

void redraw(void)
{
glutPostRedisplay();
}

So the next thing to do is try to reset the stencil buffer where I draw the rectangle without the need of clearing the entire stencil buffer and make it work in a complex scene.

trinitrotoluene
11-07-2008, 02:02 PM
This is my final solution that seem to work but is unoptimized.

void drawQuads(void)
{

glEnable(GL_STENCIL_TEST);
glStencilFunc(GL_ALWAYS, 0x1, 0x1);
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);

glColor4f(1.0,1.0,1.0,1.0);
//Draw "paper"
glBegin(GL_QUADS);
glVertex4f(-100.0,-100.0,0.0,1.0);
glVertex4f(100.0,-100.0,0.0,1.0);
glVertex4f(100.0,100.0,0.0,1.0);
glVertex4f(-100.0,100.0,0.0,1.0);
glEnd();

glStencilFunc(GL_EQUAL, 0x1, 0x1);
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);

glDepthMask(GL_FALSE);
glEnable(GL_CULL_FACE);
glDepthFunc(GL_ALWAYS);

//Draw recto triangle
glColor4f(1.0,0.0,0.0,1.0);
glBegin(GL_TRIANGLE_STRIP);
glVertex4f(-50.0,-50.0,0.0,1.0);
glVertex4f(50.0,-50.0,0.0,1.0);
glVertex4f(0.0,50.0,0.0,1.0);
glEnd();

//Draw verso triangle
glColor4f(0.0,1.0,0.0,1.0);
glBegin(GL_TRIANGLE_STRIP);
glVertex4f(-50.0,-50.0,0.0,1.0);
glVertex4f(0.0,50.0,0.0,1.0);
glVertex4f(50.0,-50.0,0.0,1.0);
glEnd();

glDepthMask(GL_TRUE);
glDepthFunc(GL_LESS);
glDisable(GL_CULL_FACE);
// glClear(GL_STENCIL_BUFFER_BIT);
//clear the portion of stencil buffer we just write
glDepthMask(GL_FALSE);
glDepthFunc(GL_EQUAL);
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
glStencilOp(GL_KEEP,GL_KEEP,GL_ZERO);

glBegin(GL_QUADS);
glVertex4f(-100.0,-100.0,0.0,1.0);
glVertex4f(100.0,-100.0,0.0,1.0);
glVertex4f(100.0,100.0,0.0,1.0);
glVertex4f(-100.0,100.0,0.0,1.0);
glEnd();

glDepthMask(GL_TRUE);
glDepthFunc(GL_LESS);
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);

glDisable(GL_STENCIL_TEST);

}

IneQuation.pl
11-08-2008, 09:00 AM
You're talking about decals, right? Google up polygon offset.

dmats
11-10-2008, 08:36 AM
Thank you for your help! That seems to work except that I'm having a depth problem. But that's ok. Now that I'm on the right track I should be able to figure it out.

Also, I have tried polygon offset. The problem is that I can't seem to distinguish which side of the plane I want the lines to show up on. The lines come out clear, but they are visible from both sides. Unless I'm doing something wrong?

trinitrotoluene
11-10-2008, 09:21 AM
The problem is that I can't seem to distinguish which side of the plane I want the lines to show up on. The lines come out clear, but they are visible from both sides. Unless I'm doing something wrong? Unlike polygon, line have no winding so one solution is to use for your rectangle glStencilOpSeparate (http://www.opengl.org/sdk/docs/man/xhtml/glStencilOpSeparate.xml) with glStencilFuncSeparate (http://www.opengl.org/sdk/docs/man/xhtml/glStencilFuncSeparate.xml). if your graphic cars support this extension (http://www.opengl.org/registry/specs/EXT/stencil_two_side.txt). I think all cards that support OpenGL 2.0 and greater have this extension supported. Unfortunately, my video card is very old and I cannot post a sample code to prove it. Another solution that will work well for all graphic cards is to emulate lines with polygon so now you can use the right winding to be able to view it on a single side of the rectangle.

That seems to work except that I'm having a depth problem. Do the problem appear with my sample code? Do you use shader? I read somewhere that when using shaders with multi pass rendering algorithm care must be taken to achieve positional invariance => using gl_Position = ftransform() in place of gl_Position = gl_ModelviewProjectionMatrix * gl_Vextex.