zufryy - 3 months ago 23

C++ Question

I success to generate the height map using VBO and IBO in openGL. The full picture of this data is shown in the figure below. What I want really show is only the data with non-black color. I put zero in z-value when the color is black.

Here is my code to generated the indexes

`void triangle::getIndices(QVector<double> minmaxX_, QVector<double> minmaxY_)`

{

indices.clear();

int numY = round((minmaxY_[1] - minmaxY_[0]) / minmaxY_[2]) + 1;

int numX = round((minmaxX_[1] - minmaxX_[0]) / minmaxX_[2]) + 1;

for (int row=0; row<numY-1; row++) {

if ((row&1) == 0 ) { // even rows

for ( int col=0; col<numX; col++ ) {

indices.append(col + row*numX);

indices.append(col + (row + 1)*numX);

}

}

else {

for ( int col=numX-1; col>=0; col-- ) {

indices.append(col + (row*numX));

indices.append(col + ((row + 1)*numX));

}

}

}

}

My Shader Code

`const char* const frgshdr_source =`

"uniform const float colorSize;\n"

"uniform vec3 colorTable[512];"

"varying float height;\n"

"uniform float heightSize;\n"

"uniform float heightMin;\n"

"void main() {\n"

" //vec3 colorTable2[int(colorSize)+1] = colorTable;\n"

" float h = (height - heightMin)/heightSize;\n"

" if (h < 0.0f || h > 1.0f) {\n"

" gl_FragColor = vec4(0.0f, 0.0f, 0.0f, 0.0f);}\n"

" else {"

" int i = 0;\n"

" while (h >= float(i + 1)/colorSize) {\n"

" i += 1;}\n"

" vec3 base = mix(colorTable[i], colorTable[i+1], colorSize*(h - (float(i)/colorSize)));\n"

" gl_FragColor = vec4(base, 1.0f);}\n"

"}\n";

Unfortunately after I clip the z-value using my projection matrix (orthographic). I still get some artifacts on the edge like in the picture below.

here is my orthographic projection matrix

`m_projection.ortho( minX, maxX, minY, maxY, minZ, maxZ);`

Look's like openGL recreate some triangles automatically so it makes artifacs around the edge (purple line).

Is there any method to make this edge artifacts disappear or I need to define my indexes again ?

Thank you in advance for your help.

Answer

Sorry to disappoint you, but this is how clipping is supposed to work. The clipping process of each primitive (triangle or line) does not end in a binary answer (i.e. throwing or retaining the entire primitive). Instead the primitive is replaced with one or more primitives which represent the part of the original primitive within the clipping volume. So if you have a triangle ABC:

```
A---------B
\ |
\ |
\ |
\ |
C
```

With heights 10, -1, -1 of A, B, C respectively, and you clip it against height = 0, then OpenGL replaces it with this smaller triangle Abc:

```
A---b B
\ |
c
C
```

With heights 10, 0, 0 of A, b, c respectively.

You can think of it as if by raising the clipping plane height you raise an imaginary water-level, and OpenGL correctly reconstructs the shore-line corresponding to that water-level.

Those small triangles are the result of this *desired* behavior.

See Vertex Post-Processing in the wiki, or the Primitive Clipping chapter in the OpenGL spec.

If you want to throw away entire edges that intersect at a vertex of height <= 0, then you can either generate a geometry in the VBO that skips those vertices, or if you cannot do that because your height-map is dynamic, then use a geometry shader to pass-through only those primitives which are entirely at height > 0.

If your hardware does not support geometry shaders (and heightmap is dynamic), then your only choice is to reduce the artifact. One option is to draw the lines with `GL_LINE_STRIP`

instead of `glPolygonMode`

(as it appears you're doing now). It will avoid generating those long lines at the edges, but those short clipped segments meeting at the vertices will still be seen.

This is unrelated to the artifact, but it may come in handy in the future. Your current index generating code seems to traverse the grid in a back-and-forth fashion. I don't know why you do this, but keep in mind that you can generate everything in sequence and use `GL_PRIMITIVE_RESTART`

to end one `GL_TRIANGLE_STRIP`

(or `GL_LINE_STRIP`

) and start a new one from a different vertex *within the same VBO*.