我写了一个光线追踪程序(目前)有两个表面照明选项:环境和反射。环境照明复制自然表面如何散射光线。反射明显地重现了镜子如何反射光线。一切工作正常,但我无法弄清楚如何混合颜色与光泽反射。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”:
这里是相同的模拟用的1,使得反射镜对最终颜色没有影响一个dimFac:
这里dimFac是0.8
这里,它是0.1
也许这只是我,但没有这些反射看起来惊人的逼真的。我用作指南的是康奈尔的一个简报,其中除了别的以外,还提到了有关添加颜色的任何内容。镜子确实有一定的颜色,我不知道混合颜色的正确方法。我在做什么错了?
所以我从光线中获取颜色的方式如下。射线追踪器的每次迭代都以形状的初始化开始。该程序支持三种形状:平面,球体和直角棱镜(最终只有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。
只要我回溯了所有的反射,我就留下了一种颜色,这是我用来对该特定光线的像素着色的颜色。
告诉我是否错过了任何东西或者不清楚。
您能否提供您正在使用的获取光线颜色的方法的副本?另外,你可以提供一些你的'addColor()'方法的上下文:dimFac是一个per-object属性,就像在一个材质中一样?还是全球价值?你能解释你如何使用'Color''c'吗? –