3

我使用头发粒子系统使用 Blender 2.66 创建了一个发型。这看起来像这样:

在此处输入图像描述

如您所见,亮度已应用于线条片段。转换后,我已将发型网格导出为 OBJ 文件格式。我在我的程序中解析了它,渲染看起来像这样:

在此处输入图像描述

粒子已绘制为 GL_LINES(在我的 OBJ 文件中,每个面有 2 个顶点)。

在另一个测试程序中,我想用一个简单的线段来测试亮度。这是我的顶点缓冲区:

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
};

结果(线在原点垂直于X轴旋转->我调用glLineWidth(5.0f)以获得更好的可见结果):

在此处输入图像描述

通过实时动画,我可以看到亮度是正确的,但只是在线条的特定“一侧”。这是正常的,因为一条线段应该有无限的法线,而我只有两条法线(每个顶点一个)。我想确切地说这两个法线是方程平面的法线 Y = 0 -> n(0.0, 1.0, 0.0)。所以我想知道是否可以为每个顶点添加多个法线?我相信 OpengL 做不到。但也许另一种方式是可能的。这是一张图,解释了我想做什么来计算线段每个部分的正确亮度:

在此处输入图像描述

就像您在第一张图片上看到的那样,Blender 可以在线段上实时计算亮度。此外,这张图片上存在 OpenGL 渲染。所以我确信这是可能的。我尝试重复相同的线段坐标两次,但对于第二行,我应用了相反的法线 n2(0.0, -1.0, 0.0) 但它不起作用。“另一面”是“黑暗的”。两个多边形也是一样的。目前,我使用 GLSL 着色器。我认为使用几何着色器或镶嵌着色器等特殊着色器是可能的。也许需要 CUDA 语言。但我不确定。

有人可以帮助我吗?

4

2 回答 2

2

这是一个复杂的话题。您应该首先阅读Marschner 2003 年关于头发照明的论文。一旦您感到困惑,请查看nvidia对此模型的解释(第 23.3 节,头发着色),其中包括漂亮的图表和着色器代码。

希望这可以帮助!

于 2013-04-10T21:19:19.393 回答
1

ananthonline 已经为您提供了一些参考资料,但对于简单的线束照明模型而言,这些参考资料完全是多余的。

如果您的要求不那么先进,您可以将 Phong 照明模型应用于股线。您可能会问“等等,股线没有法线,但您需要 Phong 的法线?” 嗯,是的,也不是。一条线段有无数条法线,也称为平面。或者换句话说,线股本身是平面的法线。

phong 模型从朗伯散射模型的假设开始,即入射角越“垂直”,它变得越亮。描述这个的数学是

I(phi) = I_max * cos( phi )

或者,通过用向量替换 phi 并且cos( angle(↑a,↑b) ) = ↑a · ↑b在哪里||↑a|| = ||↑b|| = 1

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

现在让↑c · ↑b = 0,在哪里||↑c|| = 1,然后↑a · ↑b = 1 - ↑a · ↑c。但是↑c · ↑b = 0是正常的定义。↑b这意味着对于光源方向和方向的线段,↑c您可以将强度写为

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

这就是线条的 Phong 照明模型。碰巧这也正是 Blender 所做的。

更新:镜面反射

您只需要眼睛位置来计算镜面反射。您也可以这样做,假设线束的法线是垂直于线束的光方向矢量。再次让↑b线段↑c的方向和朝向光的方向。↑n然后应用 Gram-Schmidt 正交归一化方法,您可以通过以下方式得出原位法线

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

使用它,您可以构建通常的一组

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

在一个线链顶点着色器中并将其传递给一个常规的 Phong 片段着色器并像往常一样进行数学运算。

于 2013-04-10T22:42:11.090 回答