Polygons and (non-tube) lines in JOGL

Have jReality programming problems or questions? Post them here.
Post Reply
olaf
Posts: 16
Joined: Mon 16. Feb 2009, 05:24
Location: Australia
Contact:

Polygons and (non-tube) lines in JOGL

Post by olaf » Mon 23. Feb 2009, 03:26

Hi!

I'm trying to render relatively large polygonal meshes (~40k quadrangles) with both faces and edges shown. Tubes do of course display fine, but at that complexity start to hurt performance. When I set 'TUBES_DRAW' to false, I see lines disappear behind incident polygons at certain angles. I know there's a way to solve this with OpenGL - and other applications on the same machines display the same kind of thing fine - but I can't figure out the correct attribute settings for jReality.

Here's a little example that shows the problem:

Code: Select all

import java.awt.Color;

import de.jreality.geometry.IndexedFaceSetFactory;
import de.jreality.scene.Appearance;
import de.jreality.scene.SceneGraphComponent;
import de.jreality.shader.CommonAttributes;
import de.jreality.ui.viewerapp.ViewerApp;
import de.jreality.util.CameraUtility;

public class FacesAndLines {
  
  public static void main(String[] args) {
    
    IndexedFaceSetFactory ifsf = new IndexedFaceSetFactory();
    
    double [][] vertices  = new double[][] {
        {-1, -1, 0}, {0, -1, 0}, {1, -1, 0},
        {-1,  0, 0}, {0,  0, 0}, {1,  0, 0},
        {-1,  1, 0}, {0,  1, 0}, {1,  1, 0}
    };
    
    int [][] faceIndices = new int [][] {
        {0, 1, 4, 3}, {1, 2, 5, 4}, {3, 4, 7, 6}, {4, 5, 8, 7}
    };
    
    ifsf.setVertexCount( vertices.length );
    ifsf.setVertexCoordinates( vertices );
    ifsf.setFaceCount( faceIndices.length);
    ifsf.setFaceIndices( faceIndices );
    
    ifsf.setGenerateEdgesFromFaces( true );
    ifsf.setGenerateFaceNormals( true );

    ifsf.update();
    
    SceneGraphComponent sc = new SceneGraphComponent();
    sc.setGeometry(ifsf.getIndexedFaceSet());
    Appearance a = new Appearance();
    a.setAttribute(CommonAttributes.TUBES_DRAW, false);
    a.setAttribute(CommonAttributes.VERTEX_DRAW, false);
    a.setAttribute(CommonAttributes.POLYGON_SHADER +
    		'.' + CommonAttributes.DIFFUSE_COLOR, Color.WHITE);
    sc.setAppearance(a);
    
    ViewerApp va = ViewerApp.display(sc);
    CameraUtility.encompass(va.getCurrentViewer());
 }
}
When I start this, I see a single white square. Using the rotate tool reveals that there are actually four smaller squares.

Cheers,
Olaf

STRESS
Posts: 141
Joined: Mon 19. Jan 2009, 12:10

Re: Polygons and (non-tube) lines in JOGL

Post by STRESS » Mon 23. Feb 2009, 11:21

olaf wrote:Hi!

I'm trying to render relatively large polygonal meshes (~40k quadrangles) with both faces and edges shown. Tubes do of course display fine, but at that complexity start to hurt performance. When I set 'TUBES_DRAW' to false, I see lines disappear behind incident polygons at certain angles. I know there's a way to solve this with OpenGL - and other applications on the same machines display the same kind of thing fine - but I can't figure out the correct attribute settings for jReality.
There are several ways to attack this in OpenGL:

First changing the drawing order might work depending on the depth test behaviour either the lines or the polygons will win. Additionally changing the depth test from less to less_equal might work.

Second increase the line width this might help that parts of the line will end up with different depth values compared to the underlying polygon and therefore win the z test

Third use polygonOffset but not sure if that is actually deprecreated since OpenGL3.

I think in jReality unless you change the backend code you're only chance is to use option 2

User avatar
gunn
Posts: 323
Joined: Thu 14. Dec 2006, 09:56
Location: TU Berlin
Contact:

Post by gunn » Mon 23. Feb 2009, 13:30

There is a fix in the JOGL backend for this problem.

Simply add this line when setting the appearance attributes:

Code: Select all

   a.setAttribute(CommonAttributes.DEPTH_FUDGE_FACTOR, .995); 

In the jReality Navigator, you can set the value of this attribute by inspecting the DefaultRenderingHintsShader field of the Appearance object.

When it is drawing (non-tubed) lines, the JOGL backend calls the OpenGL function glDepthRange() with the near value set to 0 and the far value to the value of the DEPTH_FUDGE_FACTOR attribute, whose default is 1.0.

Using a value slightly less than 1 will have the effect of ''pulling'' the rendered geometry towards the viewer. When this is applied in the JOGL backend when lines are drawn, they appear ever-so-slightly in front of the polygons which share the same vertices.

If you set the depth fudge factor too low, then edges start to appear when they shouldn't (i.e., they should be hidden but they are brought forward so they are visible).

If you set the depth fudge factor too low, then edges start to appear when they shouldn't (i.e., they should be hidden but they are brought forward so they are visible)The question of how to calculate the ''correct'' value of this attribute, given the near and far clipping planes of the camera and the position of the object in world space, is one which I have never carried out. If you do so, please share your results here!
jReality core developer

olaf
Posts: 16
Joined: Mon 16. Feb 2009, 05:24
Location: Australia
Contact:

Post by olaf » Mon 23. Feb 2009, 16:48

Thank you so much! That helped a lot.

I suspected the DEPTH_FUDGE_FACTOR played a role, but didn't understand how to use it correctly.

Finding the best value does indeed seem tricky. If I come up with a good strategy, I'll let you know.

STRESS
Posts: 141
Joined: Mon 19. Jan 2009, 12:10

Post by STRESS » Mon 23. Feb 2009, 18:24

olaf wrote:Thank you so much! That helped a lot.

I suspected the DEPTH_FUDGE_FACTOR played a role, but didn't understand how to use it correctly.

Finding the best value does indeed seem tricky. If I come up with a good strategy, I'll let you know.
That will be really hard for the general case. Since the depth buffer in hardware is hyperbolic not linear so you get z compression for very far away objects. Your values will have to at least consider scene/world scale and camera perspective projection.

olaf
Posts: 16
Joined: Mon 16. Feb 2009, 05:24
Location: Australia
Contact:

Post by olaf » Tue 24. Feb 2009, 07:51

Hmm, if I understand correctly what glDepthRange does, wouldn't it be best to draw lines with glDepthRange(0.0d, 1.0d - OFFSET) and everything else with glDepthRange(OFFSET, 1.0d), where OFFSET is close to the depth buffer resolution?

User avatar
gunn
Posts: 323
Joined: Thu 14. Dec 2006, 09:56
Location: TU Berlin
Contact:

Post by gunn » Thu 26. Feb 2009, 13:04

It's tempting to think that this should work. And it would work if the mapping from camera coordinates to NDC coordinates (specifically the z-coordinate) was linear. But it isn't. It's basically the multiplicative inverse. I can't go into all the details here, but essentially the perspective transformation (in OpenGL, and up to a linear transformation) in homogeneous coordinates looks like (x,y,z,1) -> (x/z, y/z, -1/z) so that the z-values are flipped and negated, so they are in the same front-to-back order, but non-linearly transformed.

The result is that the right value for glDepthRange is very sensitive to where the object is (close to the near clipping plane or close to the far). Additionally, the near and far should be as close together as possible.

For further discussions, google glDepthRange.

Of course for a specific application you can probably choose one value of glDepthRange and stick with it. I believe however that I once had a default value of something like .99995 and had to remove it because there were situations where it made the rendering worse rather than better.
jReality core developer

olaf
Posts: 16
Joined: Mon 16. Feb 2009, 05:24
Location: Australia
Contact:

Post by olaf » Thu 26. Feb 2009, 13:15

I understand. The thing is, from the OpenGL documentation I found online I couldn't quite figure out whether dlDepthRange was applied before or after the perspective transformation. It seemed to make more sense to me to do it after, but that was just a guess. If you happened to have a link that explained these things in a little more detail I would be very grateful.

User avatar
gunn
Posts: 323
Joined: Thu 14. Dec 2006, 09:56
Location: TU Berlin
Contact:

Post by gunn » Thu 26. Feb 2009, 21:54

The "final word" for OpenGL questions is the official specification. We're working with OpenGL 2.1 (3.0 exists but I don't know its status).

YOu can get it at here.

On about page 42 (section 2.11.1 "Controlling the Viewport") it describes the role of glDepthRange. And from what it says, it looks like it does in fact get applied after the perspective divide. So I don't understand what's going on. It would seem your original suggestion makes sense: a single constant "nudge" should push a given "line" fragment in front of a corresponding "face" fragment and fix the problem, regardless of where the original samples were.
jReality core developer

olaf
Posts: 16
Joined: Mon 16. Feb 2009, 05:24
Location: Australia
Contact:

Post by olaf » Fri 27. Feb 2009, 07:24

Thanks for the link.

So if I understand you correctly, the method I suggested has been tried, and didn't work?

User avatar
gunn
Posts: 323
Joined: Thu 14. Dec 2006, 09:56
Location: TU Berlin
Contact:

Post by gunn » Fri 27. Feb 2009, 10:20

I just remember being surprised by how difficult it was to find a reasonable value that worked "across the board" so I gave up. But it might be worth looking into it again just to have a confirmation. Anyone interested in running some tests to see if a fixed value of depthRange, close to (1-resolution of frame buffer) works in a variety of settings of near/far clipping planes and position of the geometry wrt these planes? Please share results here!
jReality core developer

STRESS
Posts: 141
Joined: Mon 19. Jan 2009, 12:10

Post by STRESS » Fri 27. Feb 2009, 12:06

gunn wrote:The "final word" for OpenGL questions is the official specification. We're working with OpenGL 2.1 (3.0 exists but I don't know its status).
3.0 is now supported from all relevant IHVs in their latest drivers. JOGL seems to be a bit slow moving when it comes to updating. But I think I heard that the other popular OpenGL binding, LWGL has upgrated to 3.0 some months ago.

Oh yes beware that using glDephRange will have performance implications on modern graphics card since it is very likely to destroys early deph test and depth buffer compression.

Post Reply