cartoon outlining (cartoon rendering part1)
by F.W. Hardijzer · in Torque Game Engine · 05/31/2003 (3:22 pm) · 113 replies
Ok :)
I've been working on this for about a whole day, and still there are some bugs in it :(
But that doesn't hold me from posting it for others to use :)
so here is the code:
FOR SHAPES
in ts/tsMesh.cc
in TSMesh::render after:
FOR TERRAIN:
in terrain/terrRender.cc
in TerrainRender::renderXFCache after
FOR INTERIORS:
I'm still working on this one, and it's quite difficult (since there are lots of render codes in the interiors,
I've finally gotten some lines over it, but it is pretty glitchy, and will only look good on some interiors,
the $pref::renderOutline for interiors is $Pref::Interior::renderOutline,
and $pref::outlineWidth is $Pref::Interior::outlineWidth...
the reason i changed these vals for interiors is because i can imagine someone wanting terrain and shape, btu not this buggy interior code enabled :)
anyways, enough bullshit, code:
in interior/interiorRender.cc
in void Interior::render
after:
some prefs of this:
$Pref::renderOutline (true/false) render outlines or not
$Pref::outlineWidth (0-10) linewidth of outlines
You are free to use this code for whatever project you'd like, as long as you post every change you make on this forum so others can use it too :)
BUGS:
- enviroment mapped models have 'reflective' lines
Please if you like this stuff, contribute and help us with this!
also if you know anything about cell-shading, try to do that too...
in other words:
FRANK BIGNONE: please post your cell shading stuff from DOP here :(
and another word, noone is allowed to submit this as a resource except for me when i think the code is good enough to be posted as a resource :)
I've been working on this for about a whole day, and still there are some bugs in it :(
But that doesn't hold me from posting it for others to use :)
so here is the code:
FOR SHAPES
in ts/tsMesh.cc
in TSMesh::render after:
S32 drawType = getDrawType(draw.matIndex>>30);
glDrawElements(drawType,draw.numElements,GL_UNSIGNED_SHORT,&indices[draw.start]);
}add/*cell shading*/
bool doOutline=Con::getBoolVariable("$Pref::renderOutline",true);
if (doOutline) {
bool oldlighting=glIsEnabled(GL_LIGHTING);
glDisable(GL_LIGHTING);
F32 oldLineWidth;
int oldcullface;
glGetIntegerv(GL_CULL_FACE,&oldcullface);
glGetFloatv(GL_LINE_WIDTH,&oldLineWidth);
F32 lineWidth=Con::getFloatVariable("$Pref::OutlineWidth",2);
glLineWidth(lineWidth);
glCullFace(GL_FRONT);
glPolygonMode (GL_BACK, GL_LINE);
glDepthFunc(GL_LEQUAL);
bool old2dtex=glIsEnabled(GL_TEXTURE_2D);
glDisable(GL_TEXTURE_2D);
F32 oldcolor[4];
glGetFloatv(GL_CURRENT_COLOR,oldcolor);
glColor4f(0.0f,0.0f,0.0f,1.0f);
for (S32 i=0; i<primitives.size(); i++)
{
TSDrawPrimitive & draw = primitives[i];
AssertFatal(draw.matIndex & TSDrawPrimitive::Indexed,
"TSMesh::render: rendering of non-indexed meshes no longer supported");
S32 drawType = getDrawType(draw.matIndex>>30);
glDrawElements(drawType,draw.numElements,GL_UNSIGNED_SHORT,&indices[draw.start]);
}
glColor4fv(oldcolor);
if (old2dtex) glEnable(GL_TEXTURE_2D);
glDepthFunc(GL_LEQUAL);
glLineWidth(oldLineWidth);
glColor3f(1.0f,1.0f,1.0f);
glCullFace(GL_BACK);
glPolygonMode (GL_BACK, GL_FILL);
if (oldlighting) glEnable(GL_LIGHTING);
}
/* end cell shading*/FOR TERRAIN:
in terrain/terrRender.cc
in TerrainRender::renderXFCache after
U32 vertexCount = mXFIndexBuffer[count + 1];
glDrawElements(mode, vertexCount, GL_UNSIGNED_SHORT, mXFIndexBuffer + count + 2);add://Cell shading
/*cell shading*/
bool doOutline=Con::getBoolVariable("$Pref::renderOutline",true);
if (doOutline) {
/*extra cell shading*/
F32 oldLineWidth;
int oldcullface;
glGetIntegerv(GL_CULL_FACE,&oldcullface);
glGetFloatv(GL_LINE_WIDTH,&oldLineWidth);
F32 lineWidth=Con::getFloatVariable("$Pref::OutlineWidth",2);
glLineWidth(lineWidth);
//glBindTexture(GL_TEXTURE_2D,NULL);
glColor3f(0.0f,0.0f,0.0f);
glCullFace(GL_FRONT);
glPolygonMode (GL_BACK, GL_LINE);
//Draw here
glColor3f(0.0f,0.0f,0.0f);
glDisable(GL_TEXTURE_2D);
glDrawElements(mode, vertexCount, GL_UNSIGNED_SHORT, mXFIndexBuffer + count + 2);
glEnable(GL_TEXTURE_2D);
glLineWidth(oldLineWidth);
glCullFace(GL_BACK);
glPolygonMode (GL_BACK, GL_FILL);
/*end extra cs*/
}
/* end cell shading*/FOR INTERIORS:
I'm still working on this one, and it's quite difficult (since there are lots of render codes in the interiors,
I've finally gotten some lines over it, but it is pretty glitchy, and will only look good on some interiors,
the $pref::renderOutline for interiors is $Pref::Interior::renderOutline,
and $pref::outlineWidth is $Pref::Interior::outlineWidth...
the reason i changed these vals for interiors is because i can imagine someone wanting terrain and shape, btu not this buggy interior code enabled :)
anyways, enough bullshit, code:
in interior/interiorRender.cc
in void Interior::render
after:
if (smRenderMode != 0) {
PROFILE_START(IRO_DebugRender);
debugRender(pMaterials, instanceHandle);
PROFILE_END();
return;
}add://cartoon outline
bool doOutline=Con::getBoolVariable("$Pref::Interior::renderOutline",false);
if (doOutline) {
F32 oldLineWidth=1;
glGetFloatv(GL_LINE_WIDTH,&oldLineWidth);
F32 lineWidth=Con::getFloatVariable("$Pref::Interior::OutlineWidth",2);
glLineWidth(lineWidth);
// Base textures
glBlendFunc(GL_ONE, GL_ZERO);
glDisable(GL_TEXTURE_2D);
glColor3f(0, 0, 0);
for (U32 i = 0; i < sgActivePolyListSize; i++) {
const Surface& rSurface = mSurfaces[sgActivePolyList[i]];
glBegin(GL_LINE_LOOP);
glVertex3fv(mPoints[mWindings[rSurface.windingStart]].point);
S32 skip = rSurface.windingStart + 1;
while (skip < (rSurface.windingStart + rSurface.windingCount)) {
glVertex3fv(mPoints[mWindings[skip]].point);
skip += 2;
}
skip -= 1;
while (skip > rSurface.windingStart) {
if (skip < (rSurface.windingStart + rSurface.windingCount))
glVertex3fv(mPoints[mWindings[skip]].point);
skip -= 2;
}
glEnd();
}
glEnable(GL_TEXTURE_2D);
//return;
}
//End cartoon outlinesome prefs of this:
$Pref::renderOutline (true/false) render outlines or not
$Pref::outlineWidth (0-10) linewidth of outlines
You are free to use this code for whatever project you'd like, as long as you post every change you make on this forum so others can use it too :)
BUGS:
- enviroment mapped models have 'reflective' lines
Please if you like this stuff, contribute and help us with this!
also if you know anything about cell-shading, try to do that too...
in other words:
FRANK BIGNONE: please post your cell shading stuff from DOP here :(
and another word, noone is allowed to submit this as a resource except for me when i think the code is good enough to be posted as a resource :)
About the author
#22
[edit]
wow, me = suchanoob. I put it under tsmesh::renderVB instead of tsmesh:render x.x
compiling...
wow, now this is what i call waaaaaayyyy too cool. Gonna change it up a little bit so that Shape, Terrain, and Interior are independent of one another.
btw, i found where to put the prefs - in the starter.fps/client/prefs.cs
niceness, many thanks!
[/edit]
12/28/2004 (4:42 am)
Hrm...tried putting the prefs in the console, but all it gave me were syntax errors...[edit]
wow, me = suchanoob. I put it under tsmesh::renderVB instead of tsmesh:render x.x
compiling...
wow, now this is what i call waaaaaayyyy too cool. Gonna change it up a little bit so that Shape, Terrain, and Interior are independent of one another.
btw, i found where to put the prefs - in the starter.fps/client/prefs.cs
niceness, many thanks!
[/edit]
#23
Bunny in Egypt
Sorry doesnt show it very well, but I dont have any other shots left using this.
Using TSE instead now. Heres how its looking so far.
12/28/2004 (4:50 am)
Heres a rather old TGE shot of it.Bunny in Egypt
Sorry doesnt show it very well, but I dont have any other shots left using this.
Using TSE instead now. Heres how its looking so far.
#24
In TSE, the lines that appear over the body disappear, I guess.
I'm finding some trouble with these lines that shouldn't appear there.
If in TSE these lines really don't appear, maybe I buy it.
12/28/2004 (6:10 am)
Cool. In TSE, the lines that appear over the body disappear, I guess.
I'm finding some trouble with these lines that shouldn't appear there.
If in TSE these lines really don't appear, maybe I buy it.
#25
F.W. Hardijzer: Looking at the effects of the renders, I think what it's doing is using vertex-based geometry. Not sure if it's the right term, but i think its sorta like what flash uses: using the equations of various lines to draw a shape.
Example:
A 2x2 diamond would probably consist of a group of 4 equations: y=x, y=-x, y=x-4, y=-x+4
or something like that...because when i enable terrain rendering, sometimes i'm seeing lines in the air...and i think it's a 'continuation' of the terrain's lines that aren't supposed to show....
gonna look for a way to clean it up a lil...
12/28/2004 (8:05 am)
Dreamstorm: I think the lines don't appear over the body because those features are part of the texture, not the shape itself. To my understanding, the lines appear only on the outline of the shape, not the textures...F.W. Hardijzer: Looking at the effects of the renders, I think what it's doing is using vertex-based geometry. Not sure if it's the right term, but i think its sorta like what flash uses: using the equations of various lines to draw a shape.
Example:
A 2x2 diamond would probably consist of a group of 4 equations: y=x, y=-x, y=x-4, y=-x+4
or something like that...because when i enable terrain rendering, sometimes i'm seeing lines in the air...and i think it's a 'continuation' of the terrain's lines that aren't supposed to show....
gonna look for a way to clean it up a lil...
#26
So its not really true cell shading, but Material outlining.
12/28/2004 (8:17 am)
The way I have done it is that the outline do actually appear around textures on shapebase. However in that example the Bunny is using a single Material/texture so its outlining the whole thing. If the eyes, teeth ears etc used a different Material, then it would be outlines speperatly.So its not really true cell shading, but Material outlining.
#27
The lines I refer are these:

The rabbit in the first image seems have these lines too, but in TSE the rabbit is clean and the lines are only in the silhouette of the shape.
You understand?
12/28/2004 (12:41 pm)
I think I don't explain so exactly (my english is horrible).The lines I refer are these:

The rabbit in the first image seems have these lines too, but in TSE the rabbit is clean and the lines are only in the silhouette of the shape.
You understand?
#28
12/28/2004 (1:55 pm)
Yes, it seems to be a problem when determining whether the faces are backfacing or not.
#29
hrm, makes sense to me...
Westy, did you implement the code as is for TSE, or did you modify it a lil?
12/28/2004 (3:17 pm)
So you mean drawing he lines only on the outline silhouette, nto on the body?hrm, makes sense to me...
Westy, did you implement the code as is for TSE, or did you modify it a lil?
#30
12/28/2004 (3:21 pm)
Yes, I had to modify TSE a bit.
#31
hrm, makes sense to me...
Westy, did you implement the code as is for TSE, or did you modify it a lil?
12/28/2004 (3:25 pm)
So you mean drawing he lines only on the outline silhouette, nto on the body?hrm, makes sense to me...
Westy, did you implement the code as is for TSE, or did you modify it a lil?
#32
12/28/2004 (3:27 pm)
Yes, I had to modify TSE a bit.
#33
I'm trying to solve this problem a long time and I'm thinking to buy TSE, but I must sure it solve my problem. So, if the TSE really gone with these body lines and Westy can help me with the code modifications, maybe I buy it.
12/29/2004 (4:10 am)
Thanks twice :)I'm trying to solve this problem a long time and I'm thinking to buy TSE, but I must sure it solve my problem. So, if the TSE really gone with these body lines and Westy can help me with the code modifications, maybe I buy it.
#34
Instead of rendering the lines directly, Post processing.
Rendering to a texture at a defined resolution, offsetting the quads (helps determine line resolution too), but by modying the alpha blending of the overlying quads, it creates a black outline around the material.
This was based off the glowBuffer.
12/29/2004 (5:33 am)
Im doing it a totally different way in TSE..Instead of rendering the lines directly, Post processing.
Rendering to a texture at a defined resolution, offsetting the quads (helps determine line resolution too), but by modying the alpha blending of the overlying quads, it creates a black outline around the material.
This was based off the glowBuffer.
#35
And looking your rabbit, TSE is the engine.
12/29/2004 (5:59 am)
Oh yes, the glowBuffer. I think it's the better way.And looking your rabbit, TSE is the engine.
#36
glEnable (GL_POLYGON_OFFSET_LINE);
glPolygonOffset (2.5, 0.9); // arguments are factor and units - tweek theese
glEnable (GL_LINE_SMOOTH);
and disable at the end...
glDisable (GL_POLYGON_OFFSET_FILL);
glDisable (GL_LINE_SMOOTH);
don't know if this will help anyone, just thought i would throw it out there because of the nature of this post.
THANKS F.W., this is huge in my opinion. I'll post some screenshots later.
01/05/2005 (8:43 am)
If you offset the front-facers from the back-facers a little it will help to keep naughty lines from showing up and will give you a little control over the bias (kind of). also i think smoothing the lines helps, but im not sure. just add these lines to the top of F.W.'s code blocks...glEnable (GL_POLYGON_OFFSET_LINE);
glPolygonOffset (2.5, 0.9); // arguments are factor and units - tweek theese
glEnable (GL_LINE_SMOOTH);
and disable at the end...
glDisable (GL_POLYGON_OFFSET_FILL);
glDisable (GL_LINE_SMOOTH);
don't know if this will help anyone, just thought i would throw it out there because of the nature of this post.
THANKS F.W., this is huge in my opinion. I'll post some screenshots later.
#37
01/12/2005 (10:09 am)
The polygon-offset is not working for all lines, there are still lines which don't want to go behind the object :/
#38
02/07/2005 (6:15 pm)
@Andrew what do you mean by factor and units? *is noob* >.<
#39
02/16/2005 (9:33 am)
Honestly, this method is sort of close but no cigar. The shader engine will work for cell shading a lot better. For now, you might just want to try using the 'ol flip normal trick. In max, clone the model (reference), color it black (or whatever), add a push modifier, flip the normals. wala. Works for all your dts shapes.
#40
02/16/2005 (9:59 am)
Yes, but it's increase the poly count, right?
Torque Owner Charlie Malbaurn
Thanks,
Charlie