c++ - Ray Tracer,阴影射线产生黑圈?
问题描述
正如您在图像中看到的那样,我在球体顶部看到了一个黑色圆圈,并且图像看起来有颗粒感。它应该更清晰,但是有这些小的黑白点。
这是阴影射线的代码
int pos = 0;
float intersect(const ray &r, vector<unique_ptr<object>> &obj)
{
//gives closest object hit point and position;
float closest = numeric_limits<float>::max();
for(int j = 0; j < obj.size(); j++)
{
float t = obj[j]->intersect(r);
if(t > 1e-6 && t < closest)
{
closest = t;
pos = j;
}
}
return closest;
}
vec color(const ray& r, vector<unique_ptr<object>> &shape, vector<unique_ptr<Light>> &lighting, int depth)
{
vec background_color( .678, .847, .902);
vec total{0.0, 0.0, 0.0};
vec ambient{0.125, 0.125, 0.125};
float t_near = intersect(r, shape);
if(t_near == numeric_limits<float>::max())
return background_color;
else
{
total += ambient;
for(int i = 0; i < lighting.size(); i++){
total += shape[pos]->shade(lighting[i]->position(), t_near, r);//gives specular + diffuse
vec shadow_dir = unit_vector(lighting[i]->position() - r.p_at_par(t_near));
ray shadowRay(r.p_at_par(t_near), shadow_dir);
float dist = shadow_dir.lenght();
float a = intersect(shadowRay, shape);
if(a != numeric_limits<float>::max())
return vec(0.0, 0.0, 0.0);
}
return total;
}
}
解决方案
对于黑色圆圈,您必须测试阴影射线的距离是否小于点与光源之间的距离。此外,对于距离,不应标准化 shadow_dir。为了处理阴影相交的黑白色点,您必须将 N*bias 添加到偏差为例如 1e-4 的命中点。偏差不应该太小
vec shadow_dir = lighting[i]->position() - r.p_at_par(t_near);
float dist = shadow_dir.lenght();
vec N = unit_vector(shape[pos]->normal(r, t_near));
shadow_dir = unit_vector(shadow_dir);
ray shadowRay(r.p_at_par(t_near) + N*1e-4, shadow_dir);
float a = intersect(shadowRay, shape);
if(a != numeric_limits<float>::max()){
float m = shadowRay.p_at_par(a).lenght();
if(a < dist)
return vec(0.0, 0.0, 0.0);
}
}
推荐阅读
- mysql - GroupBy 来自 Laravel 5.5 中的 HasManyThrough 多对多关系的结果
- mongodb - Mongoose 查询视图
- python - Python:如何将 int 转换为 32 位 size_t 并将其写入二进制文件
- amazon-web-services - 用于在 aws 中进行弹性搜索的 Signature4 签名
- c# - 在 C# 中实现 cURL 命令(同步、发布、TLS 1,2)
- c++ - OpenCV Mat 上的 UTF8 文本
- python-3.x - Pyinstaller 不会在 Python 虚拟环境中查找文件
- c# - EntityFramework.Utilities UpdateAll 带有一个字节数组 (binary(30)) 列
- c# - 如何将 DisplayNameFor 转换为超链接
- c# - 在 else if 条件下使用 null-coalesing 运算符