how to light GL_LINE_STRIP

i have a situation much like this guy on stackoverflow: http://stackoverflow.com/questions/4075674/opengl-lighting-question

i am drawing a object with GL_LINE_STRIP and the whole thing looks pretty “flat” without lighting (see my attached picture). first i tried to add a light to the scene but it became obvious that the standard lighting just doesn’t work with GL_LINE_STRIP … it did some weird thing but it didn’t at all look like a lighted object.

on stackoverflow they said you can somehow calculate the normals for an object drawn with GL_LINE_STRIP but i don’t get how to do this for my case. at the moment my code looks like this:

  
  
if(_useDepthShader)   
{  
     shader.begin();  
     shader.setUniform1f("camRadius", cRadius);    
}  
                          
wormbody.draw();  
                          
if(_useDepthShader) shader.end();  
  

and i wrote some shader code which is totally quick and dirty and produces an effect which resembles real lighting but it’s still not quite what i want. i guess it’s some kind of distance attenuation.
my vertex shader:

  
  
uniform float camRadius;  
  
void main(void)  
{  
      
     
    float cl;  
    vec4 eyeCoord = gl_ModelViewMatrix * gl_Vertex;  
      
    gl_Position = gl_ProjectionMatrix * eyeCoord;    
    float dist = sqrt(eyeCoord.x*eyeCoord.x + eyeCoord.y*eyeCoord.y + eyeCoord.z*eyeCoord.z);    
     
    float att = (camRadius*0.59) / dist;  
      
    if (att > 0.7)  
        cl = 1.0;  
      
    else if( att > 0.65)  
        cl = 0.8;  
      
    else if( att > 0.6)  
        cl = 0.6;  
      
    else if( att > 0.55)  
        cl = 0.5;  
      
    else if( att > 0.50)  
        cl = 0.45;  
      
    else  
        cl = 0.4;  
      
    gl_FrontColor = gl_Color * cl;  
      
}  
  

the whole vertex data of the object is stored in multiple VBOs (one for every bone) so i don’t know how to calculate and pass the normal data for a specific vertex to my shader in the main loop.

has anybody an idea how i could get the desired effect?

I think you want something that has a better falloff and you can still define lights as a pair of ofVec3s, light color and light position. There’s a shader on this site that I’ve used and hacked around a bit before that might be helpful to you: http://ciardhubh.de/node/18 It does per fragment lighting so that’ll help you around the usual problem of normals being averaged for the surface over multiple vertices.

thank you joshua!

but i have some questions regarding your link:
how do i have to modificate this per-fragment-shader for my purposes? looking at the shader code it makes use of normal maps and textures, my gl_line_strip object has none of those. also i see gl_Normal being used and when i understood the whole gl_line thing then the vertices drawn with gl_line_strip have no normals.
maybe these are dumb questions but im pretty new to the whole thing and looking at your link i’m a bit confused how i should proceed to adapt this thing for my application

You’re right, re-reading your problem that link wasn’t super helpful, my bad. One option is to do some kind of delaunay triangulation to extrude your lines a little bit. I think what you’re doing is probably the best approach if you’re going to continue just using the lines though. I’d make the falloff more like:

  
  
  
vec3 illumination(vec3 point, vec3 normal, vec3 lightCentre, float lightRadius, vec3 lightColour, float cutoff)  
{  
    float r = lightRadius;  
    vec3 light = lightCentre - point;  
    float distance = length(L);  
    float d = max(distance - r, 0);  
    light /= distance;  
  
    // attenuation  
    float denominator = d/r + 1;  
    float attenuation = 1 / (denominator*denominator);  
  
    //   attenuation == 0 at extent of max influence  
    //   attenuation == 1 when d == 0  
    attenuation = (attenuation - cutoff) / (1 - cutoff);  
    attenuation = max(attenuation, 0);  
  
    float dot = max(dot(light, normal), 0);  
    return lightColour * dot * attenuation;  
}  

ok, i think i get your illumination function. one question though: it takes a normal as a parameter, what would be the way to get my vertex normal in case of GL_LINE_STRIP. do i just use gl_Normal or do i have to do some calculations (if so, with what algorithm) to get the normal.

i still don’t really understand the GL_LINE_STRIP <-> Normal thing. do the vertices from GL_LINE_STRIP automatically have Normals, but Normals which don’t produce a very good lighting effect if used.
or do the vertices just have no normal at all?

The vertices don’t have normals by default, but you could try calculating them using the technique here:

http://tonfilm.blogspot.com/2007/01/calculate-normals-in-shader.html

which would kind of look like this (taken from the VVVV forums here, not guaranteeing that this will work. Haven’t tested it)

  
float3 lemniscape(float u, float v)  
{  
    // \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\  
    // [http://local.wasp.uwa.edu.au/~pbourke/surfaces-curves/lemniscape/](http://local.wasp.uwa.edu.au/~pbourke/surfaces-curves/lemniscape/)  
    /*  
    x = cos(v) sqrt(|sin(2 u)|) cos(u)  
    y = cos(v) sqrt(|sin(2 u)|) sin(u)  
    z = x2 - y2 + 2 x y tan2(v)  
      
    0 <= u <= pi, 0 <= v <= pi  
    */  
      
    float x = cos(v)*sqrt(abs(sin(2*u)))*cos(u);  
    float y = cos(v)*sqrt(abs(sin(2*u)))*sin(u);  
    float z = x*x - y*y + 2*x*y*pow(tan(v),2);  
  
    return vec3(x, y, z);  
}  
  
void process(vec3 pos, vec4 tex)  
{  
    //inititalize all fields of output struct with 0  
    vs2ps Out = (vs2ps)0;  
      
    float x, y, z, u, v, pi;  
    float u2, v2;  
    float3 tang, bitang;  
    pi = 3.14159265;  
      
    //map u and v  
    gridScaleX *= pi;  
    gridScaleY *= pi;  
      
    u = (pox.x + gridOffsetX) * gridScaleX;  
    v = (pox.y + gridOffsetY) * gridScaleY;  
      
    //to get neighbour in u direction  
    u2 = (pos.x + gridSpaceX + gridOffsetX) * gridScaleX;  
      
    //to get neighbour in v direction  
    v2 = (pos.y + gridSpaceY + gridOffsetY) * gridScaleY;  
  
    //get position  
    pos.xyz = lemniscape(u, v);  
      
    //get position of neighbours  
    tang   = lemniscape(u2, v);  
    bitang = lemniscape(u, v2);  
  
    //get tangent and bitangent  
    tang   -= pos.xyz;  
    bitang -= pos.xyz;  
  
    //get normal  
    vec4 norm = cross(tang, bitang);  
    vec3 lightDirV = normalize(-mul(lDir, tV));  
      
    //normal in view space  
    vec3 normV = normalize(mul(NormO, tWV));  
  
    vec3 viewDirV = -normalize(mul(PosO, tWV));  
}