Jump to content
  • Advertisement
Sign in to follow this  
Getov

How to shade hair (line segments) in OpenGL

This topic is 1564 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi everyone, I hope you could give me any suggestions for my problem!

I render my hair geometry in line segments. The problem I have is with the correct shading of the hair.

From what I've read I understood that I need the direction of the line segment and the direction to the light source. Then the dot product of these direction vectors defines how the current vertex is shaded.

My vertex data is in one array buffer and I've decided to pass to GLSL 2 pointers - one for the current vertex and one for the next vertex, so I can calculate the direction of the line segment.

glEnableVertexAttribArray(gpuProgram->attrib("vert"));
glVertexAttribPointer(gpuProgram->attrib("vert"), 3, GL_FLOAT, GL_FALSE, 0, NULL);
glEnableVertexAttribArray(gpuProgram->attrib("vertNext"));
glVertexAttribPointer(gpuProgram->attrib("vertNext"), 3, GL_FLOAT, GL_FALSE, 0, (void*)sizeof(Vertex));

Where Vertex is a struct with 3 floats.

 

My vertex shader:

#version 150

uniform mat4 projection;
uniform mat4 view;
uniform mat4 model;
in vec3 vert;
in vec3 vertNext;
in vec3 color;
out vec3 fragVert;
out vec3 fragColor;
out vec3 fragVertNext;

void main(void)
{
    fragColor = color;
    fragVert = vert;
    fragVertNext = vertNext;
    gl_Position = projection * view * model * vec4(vert, 1);
}

My fragment shader:

#version 150

uniform mat4 model;
uniform vec3 lightPosition;
uniform vec4 surfaceColor;
in vec3 fragVertNext;
in vec3 fragVert;
in vec3 fragColor;
out vec4 finalColor;

void main(void)
{
    vec3 lightColor = vec3(1.0, 1.0, 1.0);

    vec3 vertPos1 = vec3(model * vec4(fragVert, 1));
    vec3 vertPos2 = vec3(model * vec4(fragVertNext, 1));

    vec3 segmentDir = normalize(vertPos1-vertPos2);
    vec3 dirToLight = normalize(lightPosition-vertPos1);

    float diffCoef = 1.0 - dot(segmentDir, dirToLight);

    vec3 diffuse = ambient + lightColor * diffCoef * fragColor;

    vec3 result = min(diffuse, vec3(1.0));
    finalColor = vec4(result, 1);
}

This is just the diffuse shading without specular reflection. And the result is wrong. I have to mention that 1 hair strand is composed of a couple line segments, and also there seems to be bug in the shading of the very last line segment - it appears black.

Share this post


Link to post
Share on other sites
Advertisement


there seems to be bug in the shading of the very last line segment - it appears black.

What are you passing as the vertNext attribute for the last vertex? Seems likely you need one more value in that array.

Share this post


Link to post
Share on other sites

I use the same vertex buffer for "vert" and "vertNext", just with different offsets. I guess that when "vert" points to the last element of the buffer, "vertNext" is some undefined garbage and weird things happen.

 

Any suggestion how can I get the line segment direction ? Do I need to calculate it outside of the shader and later pass it ?

Share this post


Link to post
Share on other sites


I use the same vertex buffer for "vert" and "vertNext", just with different offsets. I guess that when "vert" points to the last element of the buffer, "vertNext" is some undefined garbage and weird things happen.

Then you need to pass in an extra vertex, so that the last segment has that one more it needs to read...

 

Or you can calculate the directions on the CPU, and pass them in directly, but that seems like a waste.

Share this post


Link to post
Share on other sites

The thing is I am not sure how to pass that additional vertex. How can the shader know when its time to use it ?

If I just add a vertex to my buffer, the result will be the same I think?

 

EDIT: I managed to get better results with precalculating the segment directions, fill them in an array and pass them to opengl. But the shading is not smooth and you can see the different line segments, not sure how to interpolate it.

Edited by Getov

Share this post


Link to post
Share on other sites


If I just add a vertex to my buffer, the result will be the same I think?

Yes, that's what I meant. Add an extra vertex to your buffer, but don't increase the number of primitives in your glDraw*() call.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!