2016-06-13 109 views
1

我写了一个光线追踪程序(目前)有两个表面照明选项:环境和反射。环境照明复制自然表面如何散射光线。反射明显地重现了镜子如何反射光线。一切工作正常,但我无法弄清楚如何混合颜色与光泽反射。Java:光线追踪:光泽反射着色

反射算法返回一个颜色并递归地工作。光线是以参数化线的形式“投射”的。当他们击中反射表面时,他们完美地反弹(以及我的工作方法)。然后将这些反射光线用作再次调用反射算法的参数。这一直持续下去,直到当前光线遇到环境(非反射)表面或者当前光线根本没有碰到表面。

我现在计算颜色的方式是我平均反射表面的颜色和从后到前新打的表面。因此,光线早期点击的表面上的颜色比以后的表面颜色更多。

如果颜色A是它遇到的第一个(反射)表面的颜色,则颜色B是它碰到的第二个表面的颜色,C是第三个表面的颜色,依此类推。所以在最终的颜色返回将是50%A,25%B,12.5%C ...

我用于此的方法实际上支持加权平均值,以便镜像表面对最终颜色影响较小。它是:

public void addColor(Color b, double dimFac) { 
    double red = c.getRed() * (1 - dimFac) + b.getRed() * dimFac; 
    double green = c.getGreen() * (1 - dimFac) + b.getGreen() * dimFac; 
    double blue = c.getBlue() * (1 - dimFac) + b.getBlue() * dimFac; 
    c = new Color((int) red, 
        (int) green, 
        (int) blue); 
} 

下面是该程序的截图。有三种环境球体悬停在一个光滑的反射面,随着a的0.5“dimFac”:

enter image description here

这里是相同的模拟用的1,使得反射镜对最终颜色没有影响一个dimFac:

enter image description here

这里dimFac是0.8

enter image description here

这里,它是0.1

enter image description here

也许这只是我,但没有这些反射看起来惊人的逼真的。我用作指南的是康奈尔的一个简报,其中除了别的以外,还提到了有关添加颜色的任何内容。镜子确实有一定的颜色,我不知道混合颜色的正确方法。我在做什么错了?

所以我从光线中获取颜色的方式如下。射线追踪器的每次迭代都以形状的初始化开始。该程序支持三种形状:平面,球体和直角棱镜(最终只有6个平面)。我有一个每个形状的类,和一个类(称为形状),可以存储每种类型的形状(但每个对象只有一个)。

形状形成后,一个类(称为投影仪)通过称为MasterLight的另一个类(实际上包含用于基本光线追踪,阴影,反射和(现在)折射的方法)投射光线。

为了得到一个交点的颜色,我调用getColor()方法,该方法使用交点的向量(我如何存储3d点)。我用它来确定表面的无阴影颜色。如果曲面是无纹理的并且只是一个空白颜色(如上面的形状),那么将返回一个无阴影的颜色(它只存储在每个形状类“Color c = Color.RED”中)。一个例子是Color.RED

我采取了这种颜色,递归地插回到MasterLight作为基础颜色来获得阴影,就好像表面是正常的和环境的。这个过程返回形状通常会有的阴影。现在RGB值可能是(128,0,0);

public Color getColor(Vector v) { 
    if (texturing) { 
     return texturingAlgorithm; 
    } 
    else { 
     return c; 
    } 
} 

DimFac它被使用的方式有可能是0到1之间的任何值;现在在我的程序中,它是0.8(这是普遍的阴影常数,在环境阴影中,我把我调暗的值乘以0.8并加上0.2(1 - 0.8),这样最暗的a颜色可以是其原始亮度的0.2)。

addColor在另一个类中(我现在有17个,其中一个是一个枚举)称为Intersection。这存储了有关光线交点与形状(颜色,位置,击中表面的法向矢量以及与物体材质有关的其他常数)的所有重要信息。颜色c是计算中当前的颜色。

反射的每次迭代调用addColor与最新的表面颜色。详细说明一下,如果(在上图中)一条光线刚刚从平面反射回来,撞到一个球体并跳入空白区域,我首先在球反射点处发现球体表面的颜色,这就是'c ' 被设定为。然后我在交叉点(第一次)使用平面颜色调用addColor。

只要我回溯了所有的反射,我就留下了一种颜色,这是我用来对该特定光线的像素着色的颜色。

告诉我是否错过了任何东西或者不清楚。

+0

您能否提供您正在使用的获取光线颜色的方法的副本?另外,你可以提供一些你的'addColor()'方法的上下文:dimFac是一个per-object属性,就像在一个材质中一样?还是全球价值?你能解释你如何使用'Color''c'吗? –

回答

3

您应该使用由Phong-Bui Tong于1975年创建的Phong Shading方法。Phong方程将照明简化为三个部分:环境,漫反射和镜面反射。

环境光是在完全黑暗中物体的光照。环境照明不受光源的影响。

漫射光是基于交叉点的表面法线与交叉点的光矢量之间的角度的光亮度。

镜面光是我相信你正在寻找。它基于从交叉角度到相机位置的矢量与表面周围光矢量的反射矢量之间的角度。

以下是我通常使用Phong光照:

  • 有关场景的任何对象,定义了三个常量:嘉(环境照明),KD(漫射照明)和堪萨斯(高光)。我们还将定义一个恒定的“n”来表示物体的光泽。我会将此值保持在3以上。
  • 找到法向量和光向量的点积,现在我们称这个量为“dF”。
  • 现在让我们来计算反射向量:它是法向量,乘以法向量和光向量的点积乘以2。减去光矢量,如果正常和光矢量做的话,它应该有1的幅度。
  • 从交叉点中查找反射向量和向量的点积,我们称之为“sF”。
  • 最后,我们将调用对象“clr”的颜色,最终的颜色将被称为“fClr”。
  • 要获得的最终颜色,使用以下公式: FCLR = KA(CLR)+ KD(因子)(CLR)+堪萨斯(specularFactor^N)(CLR)
  • 最后,我检查是否有任何你的R ,G或B值超出范围。如果是这种情况,则使R,G或B值等于最接近的界限。

**如果您使用RGB,请对每个RGB值执行公式。

**我想指出,所有的RGB值应该是标量为0.0 - 1.0。如果您使用的是8位RGB(0-255),请在将值分成255之前将其除以255,然后将输出值乘以255.

**任何时候我指的是矢量是一个单位矢量,也就是说,它的幅度应该是1.

我希望这有助于!祝你好运!