3

I have created a hairstyle with Blender 2.66 using hair particle system. This looks like this :

enter image description here

As you can see, the luminosity has been applied on line fragments. After conversion, I have exported my hairstyle mesh to OBJ file format. I parsed it in my program and the render looks like this :

enter image description here

The particules have been drawn as GL_LINES (in my OBJ file I have 2 vertices per face).

In another test program I wanted to test luminosity with a simple line fragment. Here's my vertices buffers :

static GLfloat vertices[6] =
{
    0.000000f, 0.000000f, -2.000000f,
    0.000000f, 0.000000f, 2.000000f
};

static GLfloat normals[6] =
{
    0.000000f, 1.000000f, 0.000000f,
    0.000000f, 1.000000f, 0.000000f
};

static GLfloat colors[6] =
{
    0.000000f, 0.000000f, 1.000000f,
    0.000000f, 0.000000f, 1.000000f
};

And the result (the line is rotating at the origin orthogonally to the X axe -> I have called glLineWidth(5.0f) to have a better visible result) :

enter image description here

With the real-time animation, I could see that the luminosity is correct but just on a specific'side' of the line. It's normal because a line segment is supposed to have an infinity of normals and I have just two normals (one per vertex). I want to precise that these two normals are the normal of the plane of equation Y = 0 -> n(0.0, 1.0, 0.0). So I wonder if it's possible to add several normals per vertex ? I believe OpengL can't do that. But maybe an other way is possible. Here's a drawing that explains what I want to do to compute a correct luminosity on each part of the line segment :

enter image description here

Like you can see it above on the first picture, Blender can compute luminosity in real-time on line segment. Furthermore, it's an OpenGL render that is present on this picture. So I'm sure it's possible to do that. I tried repeat the same line segment coordinates two time but for the second line I apply the opposite normal n2(0.0, -1.0, 0.0) but it does not work. The 'other side' is 'dark'. It's the same thing with two polygons. Currently, I use GLSL shader. I think the thing is possible using special shaders like Geometry shader or tesselation shader. Maybe CUDA language is required. But I'm not sure.

Does anyone can help me?

talonmies
  • 70,661
  • 34
  • 192
  • 269
user1364743
  • 5,283
  • 6
  • 51
  • 90

2 Answers2

2

This is a complex topic. You should begin by reading Marschner's 2003 paper on hair lighting. Once you have been confused enough, look at nvidia's explanation of this model (sec 23.3, Hair Shading), which includes nice diagrams and shader code.

Hope this helps!

Ani
  • 10,826
  • 3
  • 27
  • 46
1

ananthonline has already given you some references, but those are total overkill for a simple line strand illumination model.

If your demands are not as advanced you can apply the Phong illumination model onto strands. You may ask "wait what, strands don't have normals, but you need those for Phong?" Well, yes and no. A line segment has an infinite number of normals, also known as a plane. Or in other words the line strand itself is a normal to a plane.

The phong model starts off the assumption of a Lambertian scattering model, i.e. the "more" perpendicular the angle of incidence, the brighter it gets. The math describing this is

I(phi) = I_max * cos( phi )

or, by substituting phi with a vector and cos( angle(↑a,↑b) ) = ↑a · ↑b where ||↑a|| = ||↑b|| = 1

I(↑a, ↑b) = I_max * ↑a · ↑b

Now let ↑c · ↑b = 0, where ||↑c|| = 1, then ↑a · ↑b = 1 - ↑a · ↑c. But ↑c · ↑b = 0 is the definition of a normal. Which means for a line segment of direction ↑b and direction to light source ↑c you can write the intensity as

I(↑b, ↑c) = I_max * (1 - ↑b · ↑c)

And that is a Phong illumination model for lines. And as it happens it's also exactly what Blender does.

Update: Specular reflection

You need the eye position only for the calculation of the specular reflex. You can do this as well, by assuming that the normal of the line strand is the light direction vector perpendicularized to the line strand. Let ↑b again be the direction of the line segment and ↑c the direction toward the light. Then applying the Gram-Schmidt orthonormalization method you can derive a in-situ normal ↑n by

↑n = normalize(↑c - ↑b·↑c)

Using that you can build the usual set of

- vertex position
- vertex "normal"
- light direction
- light half direction

in a line strand vertex shader and pass it to a regular Phong fragment shader and do the math as usual.

Community
  • 1
  • 1
datenwolf
  • 159,371
  • 13
  • 185
  • 298
  • Thanks for this complete answer. But I don't understand why there is no eye position in the equation ? To compute final color I need eye position and light position, right ? Are they vector b and vector c in your exemple ? And I_max is the max color value ? Do you have a drawing that can show that ? I did not understand exactly what these vectors refers. Thanks again. – user1364743 Apr 10 '13 at 23:27
  • Sorry I misread. Ok for vector b and c. But when I change the position of the eye, this one does not interfere in the equation ? – user1364743 Apr 10 '13 at 23:55
  • Ok thank you very much for all. I have a better understanding now. Bye. – user1364743 Apr 11 '13 at 09:43
  • This is a bad answer to a bad question. Something as complex as hair rendering can not be answered by an intro to shading?! This looks like SO spam or SEO to me. – starmole Apr 11 '13 at 10:11
  • 2
    @starmole: We're not talking about hair rendering here. This is a approximation to illuminate line strangs, which works very well by the method I described. BTW, I'm (still) the top user StackOverflow opengl tag (i.e. people regard my answers among the best about OpenGL). Also nowhere in my answer there is shader code. It's only mathematics. *Did you actually __read__ my answer?* – datenwolf Apr 11 '13 at 10:18
  • 1
    @starmole What the...? Is this a joke? The question wasn't asking about the most complex or best way to render hair. It was asking about a particular problem encountered when trying to illuminate lines and this answer presents an easy, simple and general solution (even if maybe not the most specialized, beautiful or complex one). And in no way are any shaders or something mentioned, just a general mathematical solution to the particular problem of insufficient normal information the OP was facing. Your comment looks like SO spam or like you at least haven't read the question and answer. – Christian Rau Apr 11 '13 at 11:35
  • @starmole Yeah, no matter what rather simple problem the OP is facing, as long as he speaks about hair, the most helpful and best solution is probably to just refer him to some complex papers about high-end hair rendering and leave him to himself, definitely (not to discredit *ananthonline*'s answer, it's *also* helpful)! And what is *"SEO"* by the way (wait, maybe I rather don't want to know)? – Christian Rau Apr 11 '13 at 11:39
  • Yes I did. It is a sound answer. I try to answer gl questions myself. And I appreciate that you are being helpful. Often the answer is just "learn basic linear algebra". I just really can not understand how the question matched you answer. If I might make an analogy: "How do I build a car?" - "This is how Newtonian physics work". Yes, you need to know that to build a car. But it is not helpful. – starmole Apr 11 '13 at 11:51
  • @starmole *"...With the real-time animation, I could see that the luminosity is correct but just on a specific 'side' of the line. It's normal because a line segment is supposed to have an infinity of normals and I have just two normals (one per vertex)...So I wonder if it's possible to add several normals per vertex?...But maybe an other way is possible..."* - How do *datenwolf*'s explanations not fit *exactly* to this problem? – Christian Rau Apr 11 '13 at 17:16
  • @starmole - I have no idea what in the world your problem was with this answer, but that first comment was an entirely inappropriate response. This is a well-explained answer by someone who has earned a lot of respect here. Please be more constructive with your comments in the future. – Brad Larson Apr 11 '13 at 20:08