3
\$\begingroup\$

A gallery of my problem can be found here. I had to do it this way as it won't let me post more than 2 links due to my reputation.

I'm trying to use 3D cubes to generate an isometric cube world.

I got that working great and I merge only the visible vertices/indices into a buffer and draw from that.

Only problem is, as with any isometric game, it becomes difficult to differentiate between heights. For example in the first image: this archways top merges with the cubes below.

I ended up finding this shader and got it working by using it against a rendered normal map (second image) of the cubes.

You may be able to guess my problem from that image. The final result looks like the third image. The back edges are not draw with an outline, which are the most important. Which based on the normal map also means that diagonals also have the same problem on their sides (fourth image).

Is there any solution I can do for this? Either in the shader itself or perhaps when calculating the normals? I almost need to add something to the normal to distinguish their depth/height so faces on similar planes don't merge on edge detection. Or maybe there's a totally different option I could use.

Ideally I was aiming more for only edges to the air to be outlined so the archways bottom edges would not be outlined like they are now =/

\$\endgroup\$
  • 2
    \$\begingroup\$ Have you tried to increase DepthSensitivity or lower DepthThreshold? Oh and if you want to introduce more complicated rules like not drawing the edges around the base of your pillars then you might need to take another approach. Probably something involving tagging the edges that you want an outline on and then drawing the lines. \$\endgroup\$ – PeterT Aug 4 '13 at 13:33
  • \$\begingroup\$ I would follow Peter's second suggestion and strongly encourage taking another approach - shaders will of necessity be primarily 'screen-space', but what you really want is a 'world-space' approach; essentially you want to add 'edge markers' (little cylinders/black billboards/what-have-you) to some class of edges; either those that have a 'sharp' edge (i.e., a 90-degree bend) or those where the edge is 'reflex' (that is, the two faces on either side of it have one normal pointing towards the camera and one pointing away). The algorithmic approach will be much more flexible in the long run. \$\endgroup\$ – Steven Stadnicki Aug 4 '13 at 20:00
  • \$\begingroup\$ @StevenStadnicki In the world array for the blocks, I already store the connections that the block has. On my 2D approach I used this as a bit mask to determine what outlines to draw per cube. As I still have that bit mask, I could still use it. The question is how would I go about rendering/drawing the outline? I have no idea how to draw a thin outline when it comes to vertices. I'm very new to 3D programming. \$\endgroup\$ – MattMcg Aug 4 '13 at 20:09
  • \$\begingroup\$ And @PeterT, I tried to play with the parameters on the shader, none give the desired results still as it's strictly based off colour difference on the normal image, which there is none when one face exists inside the view area of a the same face. \$\endgroup\$ – MattMcg Aug 4 '13 at 20:10
  • \$\begingroup\$ If you have a deferreed renderer where you have the pixels depth, then you can evaluate the depth different among two pixels and obscure them if its too large... \$\endgroup\$ – Blau Aug 4 '13 at 20:14
0
\$\begingroup\$

(Answering from my comments to get this off the unanswered list)

My strong preference would be for a 'world-space' solution over a 'screen-space' one; that is, rather than trying to do the work of outlining in a shader, instead do it in your engine: for each edge in your figure, determine whether the edge should be highlighted on-screen. You can use whatever criteria you like for whether an edge should be highlighted; for instance, a simple one would be to highlight each edge where the faces on the two sides of the edge point in different directions with respect to the camera (that is, one pointing towards the camera and one pointing away). It would be nearly as easy to highlight each 'reflex' edge - that is, a concave edge of your figure, one where the two faces on either side are pointing towards (rather than away from) each other; etc. Your criteria don't have to be specifically graphical, either - for instance, it's easy to 'reject' any edges on your figure adjacent to the ground.

Keeping track of the edges is a little bit tricky, but not too bad - there are a few special cases (for instance, if you can have a 'figure-eight' edge where two diagonally-adjacent cubes share the edge but no two facially-adjacent cubes do), but in general building an edge list is relatively straightforward.

Once you have the (sub)list of visible edges, there are a couple of different ways to handle displaying them; probably the most straightforward is also a world-space approach, where for each edge you render another rectangular box, ; for instance, if the edge runs from (x, y, z) to (x+1, y, z) then you might render a box that goes from (x-.05, y-.05, z-.05) to (x+1.05, y+.05, z+.05). If you do this, make sure to take care in how you construct the 'end caps'; the particular version that I note there has the advantages that boxes from adjacent edges will align correctly at their endcaps, but non-uniform coordinate deltas might not.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.