Author Topic: What is the ideal way to omit hidden lines with OpenGL?  (Read 8691 times)

0 Members and 1 Guest are viewing this topic.

Offline Pixel_Outlaw

  • Pentium
  • *****
  • Posts: 1382
  • Karma: 83
    • View Profile
I'm working in OpenGL again (This time with C++) and for the upcomming competition I need a way to remove backfacing polygon lines.

I've heard of buffers and I've heard of drawing black shapes inside of a wire frame. Ideally I want to draw many triangles so speed is a concern.

A  code snippit might help a bit too. I'm still a bit green with OpenGL...


Right now I'm drawing a black solid shape inside a wireframe version. This works OK but it is probably slow since I have to double draw the shape.
« Last Edit: May 19, 2011 by Pixel_Outlaw »
Challenge Trophies Won:

Offline LittleWhite

  • Senior Member
  • Amiga 1200
  • ********
  • Posts: 418
  • Karma: 31
  • It's me!
    • View Profile
Hey,

I am not sure to get what you want.

Backface culling ? (not drawing planes depending on orientation)

Otherwise, in term of speed, it should be fine if you are using VBO (Vertex Buffer Objects) or a similar technique. Normally, you would have only one memory transfert (CPU -> GPU) since you are drawing two times the same.
The demoscene will never die, never!

Offline ferris

  • Pentium
  • *****
  • Posts: 841
  • Karma: 84
    • View Profile
    • Youth Uprising Home
I think the fastest solution would be to store all of your objects with edge (line) AND face (poly) information. Perform backface culling on the polygons (thus omitting the lines attached to those faces) on the CPU, as branching is cheap here, then draw the remaining lines on GPU. So, with a cube, for example, you have 8 vert's, 12 edges, and 6 faces. If you store the edge data per face, however, you're left with 6x4 = 24 lines for the cube. This is more to start out with, but you will cull half (or more) that don't face the camera, leaving you with a decent number of lines. You'd need to store the extra lines anyways, otherwise your edges disappear when you have a line attached to one face that's culled and one that isn't. Sorry if I'm a bit vague, here, but it should work just fine :) .
http://iamferris.com/
http://youth-uprising.com/

Where the fun's at.
Challenge Trophies Won:

Offline Pixel_Outlaw

  • Pentium
  • *****
  • Posts: 1382
  • Karma: 83
    • View Profile
Hey,

I am not sure to get what you want.

Backface culling ? (not drawing planes depending on orientation)

Otherwise, in term of speed, it should be fine if you are using VBO (Vertex Buffer Objects) or a similar technique. Normally, you would have only one memory transfert (CPU -> GPU) since you are drawing two times the same.

I'm trying to do something that looks a bit like this. I need the faces to be solid black with white edges.




Ferris, I don't know how I'd do that currently, my lines are being drawn dynamically rather than being stored in a class or structure.

I'm drawing the cube objects (yes I'm using cubes like your example) with the following routine.

I have a prebuilt cube drawing function that draws a 1x1x1 cube

***For each cube in my scene (It is all cubes actually!)***
0. Push the new transformation onto the stack glPushMatrix
1. I move to the location I want the cube glTranslate
2. Set the scale of the cube by calling glScale
3. call the draw function:
Code: [Select]
void draw_cube()
{
    glBegin(GL_QUADS);

glVertex3f( .5f, .5f,-.5f);
glVertex3f(-.5f, .5f,-.5f);
glVertex3f(-.5f, .5f, .5f);
glVertex3f( .5f, .5f, .5f);

glVertex3f( .5f,-.5f, .5f);
glVertex3f(-.5f,-.5f, .5f);
glVertex3f(-.5f,-.5f,-.5f);
glVertex3f( .5f,-.5f,-.5f);

glVertex3f( .5f, .5f, .5f);
glVertex3f(-.5f, .5f, .5f);
glVertex3f(-.5f,-.5f, .5f);
glVertex3f( .5f,-.5f, .5f);

glVertex3f( .5f,-.5f,-.5f);
glVertex3f(-.5f,-.5f,-.5f);
glVertex3f(-.5f, .5f,-.5f);
glVertex3f( .5f, .5f,-.5f);

glVertex3f(-.5f, .5f, .5f);
glVertex3f(-.5f, .5f,-.5f);
glVertex3f(-.5f,-.5f,-.5f);
glVertex3f(-.5f,-.5f, .5f);

glVertex3f( .5f, .5f,-.5f);
glVertex3f( .5f, .5f, .5f);
glVertex3f( .5f,-.5f, .5f);
glVertex3f( .5f,-.5f,-.5f);

        glEnd();
}

3. Pop the matrix off the stack glPopMatrix


Sorry, I don't fully understand your post. It is mostly my lack of time with OpenGL.
« Last Edit: May 19, 2011 by Pixel_Outlaw »
Challenge Trophies Won:

Offline hellfire

  • Sponsor
  • Pentium
  • *******
  • Posts: 1294
  • Karma: 466
    • View Profile
    • my stuff
I'm not quite sure if "backface-culling" even makes much sense for edges, so I guess Pixel_Outlaw doesn't want backface-culling but hidden line removal which is quite expensive for complex meshes.
The most gpu-oriented way is drawing solid polygons first (which means filling the zbuffer) and, in a second pass, drawing the lines with z-testing set to "less or equal".
To sort out z-fighting (eg if you're using bigger and/or anti-aliased lines) you'd use a small amount of polygon offset.

Alternatively, and if you want to have a look into shaders, you can store the normal-vectors of your geometry in the framebuffer (example) and apply a sobel filter.

If you're using lines make sure you're drawing each edge only once: If you're simply drawing every edge of every triangle you're effectively drawing every edge twice because each (non-boundary) edge is shared by two neighbouring triangles.

Edit:
Ok, for a cube it's all a bit simpler but requires some thoughts about data-structures to work efficiently.
You could store the normals of the two adjacent faces for each edge,
manually transform the z-value of both normals with the 3x3-part of the modelview- (aka normal-) matrix (or get the camera-position into object space),
the transformed z-component of the face-normal tells if the face is pointing to (>0) or away (<0) of the viewer,
if one (or both) z are positive, the edge is visible (otherwise hidden).
This is ideally done by a vertex shader.

Then again you probably want many cubes occluding each other (where you're back at the zbuffer approach)...
« Last Edit: May 19, 2011 by hellfire »
Challenge Trophies Won:

Offline padman

  • Senior Member
  • Pentium
  • ********
  • Posts: 990
  • Karma: 260
    • View Profile
I know very little about OpenGL, but maybe this'll help too: http://glprogramming.com/red/chapter14.html#name16
Challenge Trophies Won:

Offline LittleWhite

  • Senior Member
  • Amiga 1200
  • ********
  • Posts: 418
  • Karma: 31
  • It's me!
    • View Profile
I get it.

I think hellfire got the good thing with normals. If edge (lines / points) is in a face visible (not backface culled) ... you have to draw it. Otherwise you don't have to. This has to be done for each faces ... and each faces will add the lines to draw.

Now, the way to make the detection is using the normals, and the direction of the camera. Technically, I don't see why not directly making the cross dot between camera direction + position and the normal. I am certainly missing something.
And if angle < 0 ... not drawn
The demoscene will never die, never!

Offline hellfire

  • Sponsor
  • Pentium
  • *******
  • Posts: 1294
  • Karma: 466
    • View Profile
    • my stuff
I don't see why not directly making the cross dot between camera direction + position and the normal.
Vertex-normals are in object-space and the camera-position is in world-space, so you have to transform one to the other first.

Quote
This has to be done for each faces ... and each faces will add the lines to draw.
As pointed out earlier, extracting visible edges on a per-face basis will draw every edge twice.
That's quite undesirable when using fancy blending.
Instead I suggested to keep each edge only once with both adjacent faces.
If one of the faces is visible, the edge is visible, too.
« Last Edit: May 19, 2011 by hellfire »
Challenge Trophies Won:

Offline LittleWhite

  • Senior Member
  • Amiga 1200
  • ********
  • Posts: 418
  • Karma: 31
  • It's me!
    • View Profile
I don't see why not directly making the cross dot between camera direction + position and the normal.
Vertex-normals are in object-space and the camera-position is in world-space, so you have to transform one to the other first.
Yes, silly me ... I told you ... II was forgetting something so obvious ... as always.

Thanks for helping me :)
The demoscene will never die, never!

Offline Pixel_Outlaw

  • Pentium
  • *****
  • Posts: 1382
  • Karma: 83
    • View Profile

Thanks everyone for the help!

I seems like the developers who work on OpenGL might have thought about this common tecnique for drawing outlined polygons.
Then again maybe there is not much they can do without ruining the current structure of the library.
Challenge Trophies Won: