光线跟踪反射失真

时间:2016-02-08 20:15:55

标签: c++ c++11 raytracing

我已开始编写光线跟踪器,但今天在处理反射时遇到了问题。

首先,这是问题的图像:

enter image description here

我只计算了物体的反射颜色(因此没有对反射物体施加光效) 问题是失真,我真的不明白。 我查看了我的rayVector和normalVector之间的角度,看起来没问题,反射的矢量看起来也很好。

Vector Math::calcReflectedVector(const Vector &ray,
                                 const Vector &normal) const {
  double cosAngle;
  Vector copyNormal = normal;
  Vector copyView = ray;

  copyNormal.makeUnit();
  copyView.makeUnit();
  cosAngle = copyView.scale(copyNormal);
  return (-2.0 * cosAngle * normal + ray);
}

因此,例如当我的光线射到我的球体底部时,我有以下值:

cos:1

ViewVector:[185.869,-2.44308,-26.3504]

NormalVector:[185.869,-2.44308,-26.3504]

ReflectedVector:[ - 185.869,2.44308,26.3504]

Bellow如果处理反射的代码:

Color Rt::getReflectedColor(std::shared_ptr<SceneObj> obj, Camera camera,
                            Vector rayVec, double k, unsigned int pass) {
  if (pass > 10)
    return obj->getColor();
  if (obj->getReflectionIndex() == 0) {
    // apply effects
    return obj->getColor();
  }

  Color cuColor(obj->getColor());
  Color newColor(0);
  Math math;
  Vector view;
  Vector normal;
  Vector reflected;
  Position impact;
  std::pair<std::shared_ptr<SceneObj>, double> reflectedObj;

  normal = math.calcNormalVector(camera.pos, obj, rayVec, k, impact);
  view = Vector(impact.x, impact.y, impact.z) -
         Vector(camera.pos.x, camera.pos.y, camera.pos.z);
  reflected = math.calcReflectedVector(view, normal);
  reflectedObj = this->getClosestObj(reflected, Camera(impact));
  if (reflectedObj.second <= 0) {
    cuColor.mix(0x000000, obj->getReflectionIndex());
    return cuColor;
  }
  newColor = this->getReflectedColor(reflectedObj.first, Camera(impact),
                                     reflected, reflectedObj.second, pass + 1);
  // apply effects
  cuColor.mix(newColor, obj->getReflectionIndex());
  return newColor;
}

计算法线和反射矢量:

Vector Math::calcReflectedVector(const Vector &ray,
                                 const Vector &normal) const {
  double cosAngle;
  Vector copyRay = ray;

  copyRay.makeUnit();
  cosAngle = copyRay.scale(normal);
  return (-2.0 * cosAngle * normal + copyRay);
}

Vector Math::calcNormalVector(Position pos, std::shared_ptr<SceneObj> obj,
                              Vector rayVec, double k, Position& impact) const {
  const Position &objPos = obj->getPosition();
  Vector normal;

  impact.x = pos.x + k * rayVec.x;
  impact.y = pos.y + k * rayVec.y;
  impact.z = pos.z + k * rayVec.z;
  obj->calcNormal(normal, impact);
  return normal;
}

[EDIT1]

我有一个新图像,我删除了飞机只是为了保留球体:

enter image description here

正如您所看到的,球体的边界上有蓝色和黄色。 感谢neam,我使用以下公式为球体着色:

  newColor.r = reflected.x * 127.0 + 127.0;
  newColor.g = reflected.y * 127.0 + 127.0;
  newColor.b = reflected.z * 127.0 + 127.0;

贝娄是视觉效果:

enter image description here

询问我是否需要任何信息。 提前致谢

2 个答案:

答案 0 :(得分:3)

这有用吗?

我假设你的光线和法线向量已经标准化了。

package Foo;
use Carp::Assert;
sub method {
    my $self = shift;
    assert($self->isa(__PACKAGE__));
    my @args = @_;
    ...
}

此外,我无法理解您提供的代码:

Vector Math::reflect(const Vector &ray, const Vector &normal) const
{
    return ray - 2.0 * Math::dot(normal, ray) * normal;
}

那应该是那样的吗?

this->getClosestObj(reflected, Camera(obj->getPosition()));

答案 1 :(得分:3)

您提供的示例有很多小事。这可能 - 或者可能不 - 回答你的问题,但是我认为你正在为学习目的(在学校或你的空闲时间)做一个光线追踪器,我会给你一些提示。

  • 您有两个课程VectorPosition。看起来这似乎是一个好主意,但为什么不把这个位置视为来自原点的翻译向量?这样可以避免我认为的一些代码重复(除非你做过像using Position = Vector;这样的事情)。您可能还想查看一些为您执行所有数学操作的库(如glm可以执行的操作)。 (这样,您就可以避免一些错误,比如命名dot函数scale()

  • 你从这个位置创建一个摄像头(这是真的奇怪的东西)。反射不涉及任何相机。在典型的光线跟踪器中,您有一个相机{position + direction + fov + ...},对于图像的每个像素/反射/折射/ ...,您可以投射rays {origin + direction}(因此名称为光线跟踪器,这不是 cameratracer )。 Camera类通常与物理相机的概念有关,例如焦点,景深,光圈,色差......而光线只是......光线。 (可以是从输出图像映射到第一个对象的平面的光线,或者是从反射,衍射,散射......创建的光线。)

  • 并且最后一点,我认为您的错误可能来自Math::calcNormalVector(...)函数。对于位置P和交叉点I的球体,法线N为:N = normalize(I - P);

编辑:似乎您的问题来自Rt::getClosestObj。其他一切都很好看

网上有关于创建简单光线跟踪器的网站/博客/教育内容,所以前两点我让他们教你。看看glm。 如果不弄清楚calcNormalVector(...)有什么问题,请发布其代码:)