Hidden Line Removal techniques

Started by
3 comments, last by JBourrie 17 years, 5 months ago
Hi all, I've bumped into the problem of Hidden Line Removal (HLR). Of course, it should be perfect (no Z-fighting) and fast (realtime for large scenes too). First, I've tried the naive approach, render object, then render the lines with z-check still on, so the lines that are occluded are killed by the z-check. Of course, the lines flicker heavily. Then comes the play with the depth bias, (either manually or through the D3DRS_DEPTHBIAS and D3DRS_SLOPESCALEDEPTHBIAS render states). Here, if the bias is too small, then it flickers, if too large, then small parts of the lines that should be occluded become visible. The main problem is that it needs continous adjustment, moreover, since the mapping of z-values to the z-buffer is not linear, I would need different biases for objects that are near and those that are far away (not even speaking about long objects that have parts in my face and in the distant also). So I've tried creating a vertex shader which adjusts the Z-value after the division by W, so that the offsetting I make there is linear. This is how it roughly looks like:
float4x4 mWorldViewProj;  // World * View * Projection transformation

struct VS_INPUT
{
    float4 Position	: POSITION;
    float4 Diffuse    : COLOR0;
};

struct VS_OUTPUT
{
    float4 Position   : POSITION;   // vertex position 
    float4 Diffuse    : COLOR0;     // vertex diffuse color
};

VS_OUTPUT main(VS_INPUT In)
{
	VS_OUTPUT Output;
	
    Output.Position = mul( In.Position, mWorldViewProj );
	Output.Position.x /= Output.Position.w;
	Output.Position.y /= Output.Position.w;
	Output.Position.z /= Output.Position.w;
	Output.Position.w = 1.0;
	
	Output.Position.z -= (1.0 / 65536.0);
    
    Output.Diffuse = In.Diffuse;
    
    return Output;
}

I've tried it with a D24X8 depth buffer, so the adjustment I need (at least I think so) is (1.0 / 2^24). I imagine that this shifts one "Z unit". If I use this offset on Z, nothing happens (it flickers just like before). It starts to make some difference when I use quite large values like (1.0 / 65536.0), but that value is huge if I think about the Z-values with this shift. Any idea why this does not work as I expect? What did I miss here? Then, I've implemented "the 3 pass technique" which does the following: -Render filled polygon --Disable depth buffer writes (leave depth test on) --Enable color buffer writes -Render polygon edges polygon --Normal depth & color buffering -Render filled polygon again --Enable depth buffer writes --Disable color buffer writes Which works prefectly, but it requires drawing each polygon one by one! This is a real batch killer.. I didn't try it on large scenes, but I can imagine the speed... :( Now I'm thinking about implementing a real (I mean non-image space) HLR algorithm and rendering the resulting lines in a single batch :) So, does anybody know about a nice method, which does not force me to render polygons one by one? Thanks for your help in advance, kp [Edited by - kovacsp on November 7, 2006 2:53:34 PM]
------------------------------------------------------------Neo, the Matrix should be 16-byte aligned for better performance!
Advertisement
I'm confused. It sounds like all you are trying to do is wireframe, with front-facing polygons only (as opposed to more complex operations like feature edge extraction).

Does IDirect3D9Device::SetRenderState() with the D3DRS_FILLMODE flag and the D3DFILL_WIREFRAME and, perhaps, some appropriate combination of cull-related flags not work for you?
Hi jpetrie,

thanks for your answer!
Wireframe is not exactly what I want, as the edges are specified too. I mean, I don't want to render the edges of all triangles, like I don't want to see the diagonal lines on the sides of a cube. (I use a line list for rendering the lines now)

Moreover, if I would do a wireframe on the top of the shaded object, I think I'd get the same Z-fighting issues between the surfaces and the lines just like before.

I can post some screenshots of the problems if that helps.

Best regards,
kp
------------------------------------------------------------Neo, the Matrix should be 16-byte aligned for better performance!
I'm still a bit confused about what exactly you want to do.

First off, I'd recommend you have a look at the DX SDK's post-processing sample. It contains an "Edge Detection", which might be what you're looking for (unless I misunderstood). It also includes the source, which is handy [smile].

As for drawing the wireframe over the solid mesh, that should work out fine, since the default z-function is LessEqual and the z values should be identical for any pixels drawn.

If you don't want the mesh to show, you could "hide" the mesh itself by drawing it with color-writes disabled (which would still write to the z-buffer), and thus make it occlude as it's supposed to, without being actually seen.

The last two techniques I mentioned would still draw the line in the side of a cube. Hiding it would require edge detection (that I mentioned earlier) or some kind of cell-shading type thing.

[EDIT] If this still isn't what you're looking for, maybe a simple drawing of how you do want it to look like might help [smile]

Hope this helps.
Sirob Yes.» - status: Work-O-Rama.
I think I know what you are looking for, since I have done this same thing at one point ( and if I remember right, JPetrie, you were the grader for the project I did it on, the spring-mesh CS460... I think it was CS460... :) )

You can outline a quad by rendering it normally with a texture map that is an outline (we did this in Rumble Box, where the "cel shading" on the boxes is really just a white square with a black outline mapped to each side).

If you use a texture that is an outline with a transparent inside, it will give you the look of wireframe. Draw the object front-to-back with Z-Buffering and you have a wireframe object that occludes the rear lines perfectly with no flicker.

If for some reason you are using a solid-color background (like I was) this is even easier, because you don't have to sort. You just use the background color in place of the transparency.

Check out my new game Smash and Dash at:

http://www.smashanddashgame.com/

This topic is closed to new replies.

Advertisement