我已开始编写光线跟踪器,但今天在处理反射时遇到了问题。
首先,这是问题的图像:
我只计算了物体的反射颜色(因此没有对反射物体施加光效) 问题是失真,我真的不明白。 我查看了我的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]
我有一个新图像,我删除了飞机只是为了保留球体:
正如您所看到的,球体的边界上有蓝色和黄色。 感谢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;
贝娄是视觉效果:
询问我是否需要任何信息。 提前致谢
答案 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)
您提供的示例有很多小事。这可能 - 或者可能不 - 回答你的问题,但是我认为你正在为学习目的(在学校或你的空闲时间)做一个光线追踪器,我会给你一些提示。
您有两个课程Vector
和Position
。看起来这似乎是一个好主意,但为什么不把这个位置视为来自原点的翻译向量?这样可以避免我认为的一些代码重复(除非你做过像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(...)
有什么问题,请发布其代码:)