如何实现Lambertian着色

时间:2016-10-06 23:11:47

标签: graphics raytracing shading

我正在使用C ++和OpenGL(glDrawPixels)处理光线跟踪器,到目前为止进展顺利。但是,我的阴影似乎有点偏。我希望我的球体在没有强度之间明显的线条的情况下看起来更平滑。目前,我只是尝试实现Lambertian着色,即Intensity = Id * pd *(N dot L)。我知道我需要通过归一化法向矢量和光矢量来计算(N点L),但Id和pd(强度漫射和比例因子)怎么样?我只是使用2.5的常量值来实现以下目的:

Here is a picture of what my shading looks like

显然,2.5是完全随意的,我只使用它,因为我的其他尝试甚至不像正确的阴影。上面的等式似乎表明我应该将颜色乘以强度。这是我的方法:

Color simpleIlluminate(Vector3D normal, Vector3D light, Color color) {
    float intensity = dotProduct(normal, light)*2.5f;
    color = Color((unsigned int)intensity*color.r, (unsigned int)intensity*color.g, (unsigned int)intensity*color.b);
    return color;
}

假设法向量和光矢量是正确的。颜色只是我制作的颜色结构,每个RGB值都有一个unsigned int。参数Color color是我想要阴影的球体的颜色,例如红色=颜色(255,0,0)。要修改颜色的强度,我只需将每个值乘以我计算的强度,但在运行时它看起来并不正确。

有人可以解释我缺少的东西,并告诉我在给定矢量和球体颜色的情况下,正确的函数应该是什么样的?我到处寻找,但我无法找到一个好的解决方案。我可能也会将我的浮点转换为unsigned int转换错误,但我不确定。任何帮助表示赞赏。

2 个答案:

答案 0 :(得分:2)

我会删除那个2.5因子,因为它可能会搞砸结果,这很可能产生条带,因为你将因子扩大到0和1之外的范围。

朗伯反射率也称为余弦反射率,实际上只是为了理解。考虑一个平面,如果光垂直于平面,那么所有光都会落在表面上(100%,或因子1.0)。如果一个光线平行于那个平面,那么0光将落在表面上(所有光线都是平行的,因此永远不会与平面相交,因此是一个因子或0)。

朗伯反射率只是光方向和表面法线之间角度的余弦,范围从0(没有光线照射到平面)到1.0(所有光线照射到平面)。注意余弦(90)= 1.余弦(0)= 0,因此称为余弦定律(朗伯反射率)。

答案 1 :(得分:0)

  

我可能也正在将我的浮点转换为unsigned int conversion错误

点亮。 (unsigned int)intensity*color.r相当于((unsigned int)intensity)*color.r。因此,您的强度会在乘以颜色之前呈现离散水平,从而产生这些线条。请改为(unsigned int)(intensity*color.r)