Not logged in, Join Here! or Log In Below:  
News Articles Search    

Submitted by Stu Yarham, posted on June 10, 2001

Image Description, by Stu Yarham

For my final year project at uni, I did some research into Non-photographic Rendering (NPR) methods, especially in an area called Sketchy Rendering. After seeing a few NPR images recently, I thought i'd send my own in. The image is of a Quake3Areana model in various states: wireframe, textured, and sketchy.

To achieve the sketchy effect, I do the following:
  • To shade, I do a multitexture render pass using addative blending. The first texture is a 1-d (grey-scale) texture that is indexed using Light Direction dotted with the Vertex Normal. This is used to darken the areas in shadow. The second texture is projected from the viewpoint of the camera, so that it "wraps" the model. The actual texture is just a bunch of "scribbled" lines (in grey-scale).
  • Manually find the silhouette edges - I have a pre-calculated list of all possible candidates.
  • Add "noise" to the silhouette edge vertices (to make them look "rough").
  • Render them several times (3x shown) in differing shades of grey. The z-buffer removes hidden lines from view.
  • The application was run on an Athlon 800 with a Geforce2 GTS (using D3D). Without any optimisation (just got it to work :), this model (526 triangles) is rendered on a 1600x1200 display (up close) at ~90 fps. A model with 10,374 triangles is rendered at ~42 fps. The models (or lights) need not be static, as the silhouettes are found dynamically every frame. Although not implemented, animated models are quite feasible.

    Please ask any questions you have.

    Cheers, Stuart Yarham.

    Image of the Day Gallery


    Message Center / Reader Comments: ( To Participate in the Discussion, Join the Community )
    Archive Notice: This thread is old and no longer active. It is here for reference purposes. This thread was created on an older version of the flipcode forums, before the site closed in 2005. Please keep that in mind as you view this thread, as many of the topics and opinions may be outdated.
    Sebastian Sylvan

    June 10, 2001, 01:04 PM

    That's pretty neat!


    June 10, 2001, 01:13 PM

    Nice pictures. I imagine that a realtime demonstration would look even better. Is it possible for you to post a demo?


    June 10, 2001, 01:16 PM

    That is very, VERY sweet... I'm most impressed.
    I'll have to try that myself.
    --> I love this forum. :)


    June 10, 2001, 01:37 PM

    very nice... i'm constantly impressed by the various methods of doing NPR. where did you get the quake3 model loading code?


    June 10, 2001, 02:20 PM

    I didn't know we could do photographic rendering! :)
    Anyway looks great, I would love to see it in real time and animated. The only disapointing thing is that there is no face but apart from that (Oh and also the way it makes clothed models look totaly naked, not complaining:) ) it looks like a real sketch. Nice shading.


    Tobias Franke

    June 10, 2001, 04:19 PM

    As already said, it looks neat!!!

    D.P.: The wireframe model also doesn't have a face nor cloth, but I guess that a modified sketch algorithm for the model-textures (so they can also be transfered to the final image) would be a cool addition!


    June 10, 2001, 04:22 PM

    I would look forward if you could do the dirty work and
    show us a demonstration of a moving model!
    I think it must look very impressive!!


    June 10, 2001, 04:53 PM

    Big tits!


    June 10, 2001, 05:13 PM

    I've done some NPR myself, and I was interested by your comment "I have a precalculated list of possible candidates" when talking about the silhouette edges -
    firstly, surely the only edges which cannot be silhouette are the edges whose adjoining faces are coplanar or meet in a convex 'dent' in the model, which is aurely not very many on an average character model, and secondly, doesn't this all fall over when the model animates (either you will have to include even more edges because previously coplanar faces are moved by the animation, or you need a huge chunk of memory containing all of the possible animation frames)

    this is not an attack BTW - what you have done is very impressive looking ;-) I am interested mostly as I also came up with this idea, but discarded it because of the above problems. Perhaps you have come up with a better solution than I did...?




    June 10, 2001, 06:06 PM

    Thanks for the replies, I wasn't expecting the pic to be up so quick!

    To load the Quake3 models, I used MentalVortex's .md3 file format. You should be able to find it with a search, although I have heard people having trouble finding it. If you have any probs, give us a shout, and I can send it to you.

    D.P. & Tobias Franke:
    One of the other parts of my project was to convert the texture map into something sketchy. However, I was unable to obtain any suitable results from filtering using convolution matrices (the main aim to identify the "edges" present in the texture). This is something I will probably investigate more.

    The "I have a precalculated list of possible candidates" line is perhaps a bit of a miss-leader, so I have to apologise :). My edge list is simply a collection of edges minus the edges which can not be silhouetted (as you describe). And obviously no duplicate edges (which took more more work than I thought!). Using the method I use, Q3 style animation would be acceptable, since IIRC the frames are all stored individually anyway, but you're dead right, animation in general would be pretty memory intensive. If you do ever stumble upon a solution to this, I would love to know. :)

    As for a demo... If you give me a couple of days to tidy up the app and just show the technique here, I can post it on me web page. I'll let you know... ;)


    Hiro Protagonist

    June 10, 2001, 06:36 PM

    Perhaps I am confused, but it would seem to me (and I've never done NPR) that you would only need to render those faces whose normal forms an angle with the camera of (90 < a > -90), and that share an edge with a face whose normal forms an angle with the camera of (-90 = 90).
    So for each face, every frame you would simply need to perform a dot-product with the camera direction vector, and that face's normal, as well as keep a pointer to each face's neighboring face.

    This doesn't see, too computationally intensive to me for a model of


    June 10, 2001, 06:40 PM

    Really good. Finally a NPR that tries to fake some pencil drawing and suceeds at it ;-)



    June 10, 2001, 06:59 PM

    That is a great pic...I nominate this for the best IOTD ever. My question is, is there a way to tweak up the amount of detail. What I mean is that, is there a way to make it draw more of the mesh and perhaps integrate the texturemap in so you can draw the face, armor etc.

    I am not an expert in that field, but I was thinking that perhaps you should average the texels in a 3x3 square, and if it erages to dark then do a pencil stroke. Then perhaps you can have some sort of algorithm that connects the neighboring squares that are penciled. Just a thought. It would definitly slow down the program if you have to read video memory, so mabye you could store the 3x3 squares as well as a normal for the squares as a seperate variable with the mesh.


    June 10, 2001, 07:33 PM

    Hiro Protagonist:
    You're right, although meshes with more than 10,000 tris obviously takes a lot of dot-products :). The main thing that saps speed from the technique is making the silhouette edges seem sketchy. To expand on the orignal description:
    I join sections together if the angle between them is not too great. I then have to add noise to the lines - for small line segments, I add an appropriately small amount of noise. This has to be done several times for the entire silhouette for the render sequence:
    + 1st time - very noisey but coloured very light grey
    + 2nd time - less noisey and coloured slightly darker
    + 3rd time - etc, etc...

    As you can see, this takes a while to do and is the area that I really need to optimise.

    Cheers! BTW, your octree source code (intersection stuff) is proving to be very useful on my current project :).

    Thanks :). One of the methods I was looking into, but never got round to implement (or figure out...), is to convert the texture into a sort of vector representation using a method similar to what you describe. This vector representation could then be modified in loads of ways, before being re-rendered into another texture.

    I also played around with a method similar to randomised detection (proposed in a paper by Markosian et. al. 1997 i think), that would allow me to search for (and render) the most important edges first, which could be a sort-of LOD mechanism. i.e. cull away real small edges and order the edge list by dihedral angle. Ordering the edges like this means that those edges which have adjacent faces with a smaller angle between them, have a higher priority in the list, since they are more likely to be silhouetted.



    June 10, 2001, 10:58 PM

    It's really a great job u've done.The pics are AMAZING!
    I'm longing for ID to change QuakeIV's monster models into NPR style :)
    But as are moving their servers,i don't know where else to get mentalvortex's .md3 file format,so can u do me a favor to mail it to my mailbox?Which is
    Thank you!


    June 10, 2001, 11:03 PM

    It's really a great job u've done.The pics are AMAZING!
    I'm longing for ID to change QuakeIV's monster models into NPR style :)
    But as are moving their servers,i don't know where else to get mentalvortex's .md3 file format,so can u do me a favor to mail it to my mailbox?Which is
    Thank you!


    June 10, 2001, 11:34 PM

    But how many tris are they? :-)



    June 11, 2001, 02:18 AM

    I wonder, if you've thought about using a cone tree hierachy. They can do wonders for quickly finding silhouettes, and the maths for cones can be collapsed down a lot to make the tests quick.


    June 11, 2001, 08:19 AM

    Ok, I'll bite - have you got any information on using cone trees for silhouette detection - I'm not quite sure what you mean, but I'd love to know if its applicable (these silhouette problems come up in more and more places these days...)




    June 11, 2001, 09:29 AM

    No, I've never heard of cone trees before. Do you have any links to tutorial or info regarding them. I'm just gonna have a look on Google now...



    June 11, 2001, 12:24 PM

    Hehe DP, gotta love you dropping all these new terms here just to tantalize people ;-)

    Briefly, basically, if you consider the whole mesh as a graph, you can eliminate some edges and make thegraph into a tree, that's a cone tree because it spreads outward like a cone, sorta, from the root.

    Anyway, I'd suggest just using some connectivity schemes, simple ones are very good IMHO... like storing neighboring faces and/or edges. That way once you find a silhuette edge on a continuous surface, you know some of its neighbors might be silhuette edges too, and you can walk that path rather than searching all edges brute force.



    June 11, 2001, 01:40 PM

    egreg: Not in this case :)

    Unfortunately I don't have any links on hand.

    Each cone (without a height btw) represents the where the items can possibly be facing in different directions relative to the camera. You build the hierachy bottom up, each time, finding a cone which bounds the directions and positions of those below.

    Arne Rosenfeldt

    June 11, 2001, 02:08 PM

    For me cone-tree sounds like
    putting the mesh in a tree
    for each node store a cone bounding all surface-normals below this node


    June 11, 2001, 11:15 PM

    From there, would it be easy to have a cartoon style look to it? What I mean is instead of a texture having many states of shade by a light, instead the texture would have, say, 3 states: normal, in the dark, and in the light. That would give it a comic book look, and would probably be pretty cool as well!

    Looks pretty wicked! I really like the NPR look as well.


    June 12, 2001, 01:56 AM

    Something like that :) Although, in this case we bound the cones as to where the the edges can be potential silhouette edges (ie, one is front facing, the other back).

    This thread contains 25 messages.
    Hosting by Solid Eight Studios, maker of PhotoTangler Collage Maker.