【问题标题】:(Ray tracing) Trouble converting to screen coordinates, objects being stretched(光线追踪)无法转换为屏幕坐标,物体被拉伸
【发布时间】:2021-05-12 12:11:41
【问题描述】:

我跟随 Ray Tracing in One Weekend 并设法获得了最终输出,但我想了解更多关于创建相机和“绘制”屏幕的信息,因为他没有仔细研究它很多。

当我尝试使用不同的方式通过球体创建相机时,球体实际上被拉长了,使它们看起来更像椭圆。我尝试修改 screenCords 中的 x 和 y 分配,但我只设法犯了更多错误(例如对象环绕到另一侧)

相机.h:

#pragma once

#include "../Matrix.h"
#include "../Defs.h"
#include "Defs.h"

template<typename O>
using Point3 = Vec3<O>;

template<typename O>
using Color = Vec3<O>;

template <typename O>
class Camera{
  O Height;
  O Width;
  Vec3<O> Forward, Right, Up;
  Point3<O> Origin;

public:
  Camera(O fov, O aspect_ratio, Point3<O> origin, Point3<O> target, Vec3<O> upguide) {
    Height = atan(degrees_to_radians(fov));
    Width = Height * aspect_ratio;
    
    Origin = origin;

    Forward = target - origin;
    Forward.normalize();
    Right = Forward.cross(upguide);
    Right.normalize();
    Up = Right.cross(Forward);

    }

    Ray<O> get_raydir(O right, O up){
      Vec3<O> result(Forward + right * Width * Right + up * Height * Up); result.normalize();

      return Ray<O>(Origin, result);
    }

    void screenCords(O &x, O &y, O width, O height){
      x = ((2.0f * x) / width) -1.0f;
      y = ((2.0f * y) / height); 
    }
};

Main.cpp

#include <iostream>
#include <cmath>
#include "../Matrix.h"
#include "Camera.h"
#include <vector>
#include "Image.h"
#include "Shapes.h"
#include "Tracer.h"
#include "../Defs.h"

template<typename O>
using Point3 = Vec3<O>;

template<typename O>
using Color = Vec3<O>;

int main(){
  const int img_ratio = 2;
  const int img_width = 640;
  const int img_height = 480;
  const int depth = 50; float t_Max = infinity; float t_Min = 0.001;

  float inv_width = 1 / float(img_width);
  float inv_height = 1 / float(img_height);

  std::vector<Sphere<float>> shapes;

  Camera<float> cam1(20.0f, img_ratio, Point3<float>(0.0f, 0.0f, 0.0f), Point3<float>(0.0f, 0.0f, -1.0f), Vec3<float>(0.0f, 1.0f, 0.0f));

  Sphere<float> cir1(0.2f, Point3<float>(0.2f, 0.0f, -1.0f));
  Sphere<float> cir2(7.0f, Point3<float>(0.0f, -7.0f, -1.0f));
  Sphere<float> cir3(0.5f, Point3<float>(1.0f, 0.0f, -1.0f));
  shapes.push_back(cir1);
  //shapes.push_back(cir2);
  //shapes.push_back(cir3);

  Tracer<float> tracer(shapes);

  std::cout << "P3\n" << img_width << ' ' << img_height << "\n255" << std::endl;

  Ray<float> ray(Point3<float>(0.0f), Vec3<float>(0.0f));

  for (int j = 0; j < img_height; j++)
  {
    std::cerr << "\rScanlines remaining: " << j << ' ' << std::flush;
    for (int i = 0; i < img_width; i++){

        float x = i;
        float y = j;

        cam1.screenCords(x, y, img_width, img_height);

        ray = cam1.get_raydir(x, y);
        //ray = Ray<float>(Vec3<float>(x1, y1, 1), Point3<float>(0.0f, 0.0f, 0.0f));
        tracer.iterator(ray, depth, t_Max, t_Min);
    }
  }
  std::cerr << "\n done " << std::endl;
}

我怀疑错误出在其中一个文件中,因为球体实际上是使用基于法线的颜色绘制的(毫无疑问,顶部和底部的法线颜色被窃听)

以下是一些输出示例:

【问题讨论】:

  • 将此问题添加书签以用作正确使用图像的示例。不幸的是,我对你没有帮助。

标签: c++ graphics camera aspect-ratio raytracing


【解决方案1】:

你应该定义

const float img_ratio = (float)img_width/img_height;

对于 640x480 图像,应该是 1.333 而不是您的代码中的 2

同样在screenCords 中,你从x 中减去1.0f,但不是从y 中。它会产生倾斜移位效果。

【讨论】:

  • 感谢您指出 img_ratio!我完全忘记了我之前对它进行了硬编码。那个愚蠢的忽视固定了拉伸。不幸的是,如果底部球体“包裹”并出现在顶部,我无法将 1.0f 减去 y(我之前就是这样做的)。我将其作为临时修复程序删除,但我知道它是错误的。我不确定它为什么会环绕。
  • @Tippitytopkek:它显示在顶部一定是因为你没有检查交叉点是在相机后面还是前面。那个球体离相机太近了,从画面上部射出的光线在你的背后与它相交。
  • 我明白了,所以我必须以某种方式将交点转换回相机坐标并检查 i 是否落后于 (0, 0, -1)?
  • @Tippitytopkek:通常射线-球体的交点代码已经具有沿射线的交点的距离t。您只需调整该代码以忽略与t&lt;0 的交集。
  • 我实际上已经在这样做了。我的 t_Min 为 0.01,如果交点小于该值,则不会记录命中。我还尝试使球体扩散(用于简单阴影),但它们与以前完全相同,如果这有任何帮助的话。
猜你喜欢
  • 2018-11-13
  • 1970-01-01
  • 2015-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-09-14
  • 2012-01-17
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多