3
\$\begingroup\$

Subject

I am creating a terrain map with triangle strips and I would like to make the bodies of the triangles black, but have their outlines be colored.


Problem

The solution appears to be to draw the triangles twice, once in solid black, using GL_FILL and once in color using GL_LINE.

The problem with this approach is that, since I am using depth testing and the vertices are at the same position each time, my color lines end up blending with the black lines


Attempted Solution

According to the OpenGL docs, and other sources, it looks like I should be able to utilize the glPolygonOffset() function to give polygons that are drawn with GL_LINE "precedence" in the depth buffer by offsetting their comparison value by the argument to the function. (so I would think 1.0 would be sufficient)

This, however, does not appear to be working for me.


My Code

I have placed glEnable(GL_POLYGON_OFFSET_LINE); in my init function.

Here is the code in my draw loop where I do the actual rendering. col is the array that hods the real colors, col2 is filled with black.

Please excuse the mess.

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 

glPolygonOffset(1.0,0.0);

glDeleteBuffers(1,&vertex_buffer);
vertex_buffer = createBuffer(GL_ARRAY_BUFFER, vert, sizeof(GLfloat)*(buffer_size), GL_STATIC_DRAW);
attributeBind(vertex_buffer, 0, 3); 

glDeleteBuffers(1,&color_buffer);
color_buffer = createBuffer(GL_ARRAY_BUFFER, col2, sizeof(GLfloat)*(buffer_size), GL_STATIC_DRAW);
attributeBind(color_buffer, 1, 3); 

glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
glDrawArrays(GL_TRIANGLE_STRIP,0,s);

glDeleteBuffers(1,&color_buffer);
color_buffer = createBuffer(GL_ARRAY_BUFFER, col, sizeof(GLfloat)*(buffer_size), GL_STATIC_DRAW);
attributeBind(color_buffer, 1, 3); 

glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);
glDrawArrays(GL_TRIANGLE_STRIP,0,s);  

I'm not sure if I need to call glPolygonOffset() each frame or not.

These are the attributeBind() and createbuffer() functions:

void attributeBind(GLuint buffer, int index, int points)
{
    glBindBuffer(GL_ARRAY_BUFFER, buffer);
    glVertexAttribPointer(
        index,              // position or color 
        points,             // how many dimensions?
        GL_FLOAT,           // type
        GL_FALSE,           // normalized?
        0,                  // stride
        (void*)0            // array buffer offset
    );
}


GLuint createBuffer(GLenum target, const void *buffer_data, GLsizei buffer_size, GLenum usageHint)
{
    GLuint buffer;
    glGenBuffers(1, &buffer);
    glBindBuffer(target, buffer);
    glBufferData(target, buffer_size, buffer_data, usageHint);
    return buffer;
}  
\$\endgroup\$
7
  • \$\begingroup\$ Just wondering, have you considered going with a shader or texture based approach? \$\endgroup\$
    – Alan Wolfe
    Apr 12, 2015 at 17:25
  • \$\begingroup\$ According to this site, you should have something more like glPolygonOffset(1.0f, 1.0f) \$\endgroup\$
    – user41442
    Apr 12, 2015 at 17:38
  • \$\begingroup\$ Have you tried applying a small offset/scale to the line vertexes themselves, so that they don't overlap with the tris? I have used this approach once with acceptable results. It is the simplest solution I can think of. \$\endgroup\$
    – glampert
    Apr 12, 2015 at 17:55
  • \$\begingroup\$ @Jason 1.0, 1.0 yeilds the same results \$\endgroup\$
    – Luke
    Apr 12, 2015 at 18:05
  • \$\begingroup\$ @AlanWolfe I have not considered that because I am not very familiar with the shaders yet. I would like to avoid that if possible, but I ultimately just want something that works \$\endgroup\$
    – Luke
    Apr 12, 2015 at 18:06

1 Answer 1

1
\$\begingroup\$

Edit:
We tried many combinations of the following and got many, many, equally-disappointing results. OP has resigned to using his backup plan of physically moving the geometry slightly toward the camera before drawing it as wireframe. Link to chat.

A typical use might be to set factor and units to 1.0 to offset primitives into positive Z (into the screen) and enable polygon offset for fill mode. Two passes are then made, once with the model's solid geometry and once again with the line geometry. Nearly edge-on filled polygons are pushed substantially away from the eyepoint, to minimize interference with the line geometry, while nearly planar polygons are drawn at least one depth buffer unit behind the line geometry.
Source

check out this link, waaaaaaaaay at the bottom; the very last thing is a code sample.
They just:

glDisable(GL_POLYGON_OFFSET_FILL);

before going to line mode

glLineWidth also covers anti-aliasing

A sample wireframe pixel shader:

return float4(0, 1, 0, 1);
\$\endgroup\$
8
  • \$\begingroup\$ this is a little confusing, because OpenGL uses a right handed coordinate system and +z is coming OUT of the screen. Regardless, whether positive or negative, I can not get glPolygonOffset to work for me. HOWEVER, I would like to thank you, because that source did provide me with a separate solution, which I will describe in my answer. \$\endgroup\$
    – Luke
    Apr 12, 2015 at 19:27
  • \$\begingroup\$ @LukeP, the code you posted shows you applying XX offset to both the polygons and the lines. Set it to whatever you want (should be 1,1) but turn it back off for the lines (0,0 I guess?)(I'm DirectX). \$\endgroup\$
    – Jon
    Apr 12, 2015 at 19:28
  • \$\begingroup\$ Turns out I was wrong, I do NOT have a solution yet. Jon, when you enable glPolygonOffset, you pass it an enum indicating what kinds of lines you want to offset, which is why I was under the impression that it would only offset polygons drawn with GL_LINE fill mode. Is this not correct? \$\endgroup\$
    – Luke
    Apr 12, 2015 at 19:36
  • \$\begingroup\$ I'm learning with you here but, reading the first link, it appears that it will NEVER affect points or lines, only "fillable" geometry. Also, screen space is left handed and object and world are only right-handed by default. \$\endgroup\$
    – Jon
    Apr 12, 2015 at 19:38
  • \$\begingroup\$ I am only rendering polygons, not lines, GL_LINE is just a fill mode for polygons that says not to fill them. Bear with me though, john, using negative values lower than 1.0 is yielding results that look hopeful, but I need to change somw other unrelated things to make it work, so it may be a while here. \$\endgroup\$
    – Luke
    Apr 12, 2015 at 19:44

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .