Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

GLSL Shader - Outline | Stroke

1,623 views
Skip to first unread message

lumo...@gmail.com

unread,
Apr 16, 2007, 2:23:27 AM4/16/07
to
Hello NG.
I implemented a little program, that loads up my exported 3Dmodels
from any 3D-application.
Then i added to load up .frag and .vert shaders.
Everything works fine but how do i implement a shader
that outlines my model?
(where you can change the thickness of the outline by a variable in
the shader code - not passing a variable to the shader)
already got a flat shader, wood shader, and a Toon-Shader (fixed
color) & CEL-shader (takes color of my mesh) working...


here the code of my CEL-Shader
.VERT
varying vec3 normal, lightDir;
varying vec4 color;

void main()
{
lightDir = normalize(vec3(gl_LightSource[0].position));
normal = normalize(gl_NormalMatrix * gl_Normal);
color = gl_Color;

gl_Position = ftransform();
}

.FRAG
varying vec3 normal, lightDir;
varying vec4 color;

void main()
{
float intensity;
float factor;
vec3 n;

n = normalize(normal);
intensity = max(dot(lightDir,n),0.0);

if (intensity > 0.95)
factor = 1.0;
else if (intensity > 0.5)
factor = 0.5;
else if (intensity > 0.25)
factor = 0.25;
else
factor = 0.10;
gl_FragColor = color * vec4(factor, factor, factor, 1);
}

i think i have to do the same as with the light but with
view direction and normal vector, but where from do i get the camera
positon?

Thanks in Advance

Simon Wollwage

unread,
Apr 16, 2007, 3:48:36 PM4/16/07
to
lumo...@gmail.com schrieb:

Oh, I know this shader. lighthouse3d say hello ^^
i implented some sort of outlines. but, you need to add something to
your vertex shader

Vertex:

varying vec3 normal, lightDir;
varying vec2 texCoord;

void main()
{
vec4 ecPos;
ecPos = vec4(gl_ModelViewMatrix * gl_Vertex);
lightDir = normalize(vec3(gl_LightSource[0].position) - ecPos.xyz);


normal = normalize(gl_NormalMatrix * gl_Normal);

texCoord = vec2(gl_MultiTexCoord0);
gl_Position = ftransform();
}

Fragment:

varying vec3 normal, lightDir;
varying vec2 texCoord;
uniform sampler2D texture;

void main()
{
float intensity;
vec3 n;
vec4 _color;

n = normalize(normal);
intensity = dot(lightDir, n);

if (intensity > 0.98)
_color = vec4(1.0,1.0,1.0,1.0);
else if (intensity > 0.5)
_color = vec4(0.8,0.8,0.8,1.0);
else if (intensity > 0.35)
_color = vec4(0.4,0.4,0.4,1.0);
else
_color = vec4(0.0,0.0,0.0,1.0);
gl_FragColor = _color * texture2D(texture, texCoord);
}

this should work out for you.
the idea is simple. all you do is, that you also grab the viewvector.

lumo...@gmail.com

unread,
Apr 19, 2007, 7:29:06 AM4/19/07
to
did not test your shader yet (not home now)
but as far as i can see its not really an outline/stroke
it just makes the really outer faces black.
probably i did not explained my problem good enough. ill retry.

i managed to get the results i wanted to have with this method (but
its really poor as i have a lot of drawing which shouldnt be done!)

i use my mesh, enable front face culling, set rendermode to line, and
set the offset higher (so i see the lines in front of the mesh - or i
set the mesh line with to 2+ to get a thicker line)
cause the problem i have is that eg. if you render a face, you do not
see the nose really good, that way you get the nose outlined too, as
it has some things hidden (most of the time, depends on the view
angle)

any ideas how to do this without redrawing a the whole backface?
a mate gave me an idea, but i do not how to implement it
he said i should find the edges where the viewangle and the
normalvector of the face swaps from positive to negative value (as
those are the edges that i have to render)
so how do i draw only those lines??

thanks in advance

Simon Wollwage

unread,
Apr 19, 2007, 8:28:12 AM4/19/07
to
lumo...@gmail.com schrieb:

the blacking of the most outer fragments simulates the effect of outline
rendering. think about it :)

lumo...@gmail.com

unread,
Apr 19, 2007, 10:54:31 AM4/19/07
to
argh, somehow my last post got lost.
so once more.

i was thinking about your shader and i even tried it
the result were what i expected it.
you get some outlines thick, some thin and some you do not get at all.

here is a photoshopped image what should come up
http://go2lumo.com/test/celshade_outline.png
the lower image is what i expect it to look like (i know its not an a
cel shaded mesh)
the upper is your case.

thanks for your patience!

Simon Wollwage

unread,
Apr 19, 2007, 11:51:53 AM4/19/07
to
lumo...@gmail.com schrieb:

then just adjust the values in the shader and set the outline color to red.

in this part:

else if (intensity > 0.25)
factor = 0.25;
else
factor = 0.10;
gl_FragColor = color * vec4(factor, factor, factor, 1);

change it to

else if (intensity > 0.10)
factor = 0.25;
else
factor = 0.0;


gl_FragColor = color * vec4(factor, factor, factor, 1);


this should make it very thin. toy around with it and it'll be a good
base for starting off.

Simon Wollwage

unread,
Apr 19, 2007, 12:04:54 PM4/19/07
to
Simon Wollwage schrieb:

me once again ^^
if your project is planned to be bigger, i'd really play around with the
shader-version, because it's way faster than calculating all the
outlines by hand.

lumo...@gmail.com

unread,
Apr 19, 2007, 12:42:58 PM4/19/07
to
yeah, i can play with those values.
i want to keep it as fast as possible, so probably other ppl can use
my code later on to add it to a bigger program. (or myself)
quick question.
does it only look like the light source is changed or is it really
changed?
cause my other cel shader has other highlights than yours (and mine
wont work in vista - but works perfect in xp - no clue why - some
other shaders wont work in vista too - seems a driver & os problem)

Simon Wollwage

unread,
Apr 19, 2007, 6:00:58 PM4/19/07
to
lumo...@gmail.com schrieb:

This shader only takes GL_LIGHT0 into account. but you can easily
specify variable light sources by using a uniform-variable in the shader
and then pass the used lightsource from your program into the shader.

0 new messages