【问题标题】:raytracing plane intersection only draws partial plane C++光线追踪平面相交只绘制部分平面 C++
【发布时间】:2018-02-20 16:36:44
【问题描述】:

这是一个简单的 C++ 光线追踪程序,它获取来自相机的光线与没有偏移的简单平面和法线 (1, 0, 0) 碰撞的点,并根据点的交点绘制棋盘图案给人一种空间感。然而,平面并没有像预期的那样绘制,因为它有时会被切断和/或扭曲。是什么导致了这些行为?为什么这个光线追踪代码是错误的?还是需要更多信息来回答这个问题?

如果 viewPort.x = -150, viewPort.y = 0, viewPort.z = 0, viewPort.px = 0, viewPort.py = 1, viewPort.width = 480 和 viewPort.height = 360,它会显示: Image of render

//viewPort is the camera, bMap is a bitmap and green is the color green
//Get sin and cos of camera angles
float sx, sy, cx, cy;
sx = sin(viewPort.px);
sy = sin(viewPort.py);
cx = cos(viewPort.px);
cy = cos(viewPort.py);

//Get angle of camera view in radians for height and width with 3:4 ratio
float fh, fw;
fh = 60 / 180 * 3.14159;
fw = fh * (1 + 1 / 3);

//Get all rays and their angles
for (int h = 0;h < viewPort.width;++h)
{
  //Get Positon of starting ray
  Point3D tmp;
  tmp.x = viewPort.x + h * cy;
  tmp.y = viewPort.y + h * sx * sy;
  tmp.z = viewPort.z + h * (0 - sy * cx);

  //Get y angle of ray
  float sh, ch, dh;
  dh = viewPort.py - ((float)(h - viewPort.width / 2) / viewPort.width / 2) * fw;
  sh = sin(dh);
  ch = cos(dh);

  for (int v = 0;v < viewPort.height;++v)
  {
    //Get x angle of ray
    float sv, cv, dv;
    dv = viewPort.px - ((float)(v - viewPort.height / 2) / viewPort.height / 2) * fh;
    sv = sin(dv);
    cv = cos(dv);

    //Get slope of ray
    float dx, dy, dz;
    dx = sv;
    dy = 0 - sh * cv;
    dz = ch * cv;

    if (dx != 0)
    {
      //Get point of intersection from normal, ray start, and ray angle
      Point3D nor = {1, 0, 0};
      Point3D lin = {dx, dy, dz};

      float denom = DotProduct(nor, lin);
      if (std::abs(denom) > 1e-6)
      {
        float mag = sqrt(tmp.x * tmp.x + tmp.y * tmp.y + tmp.z * tmp.z);

        //Point (0, 0, 0) is on plane. p0 - tmp
        Point3D p0l0 = {-tmp.x / mag, -tmp.y / mag, -tmp.z / mag};

        float t = DotProduct(p0l0, nor) / denom;

        //Check if ray is coliding (not line)
        if (t >= 0)
        {
          //Determine square of checkerboard pattern
          if ((int)((t * dy + tmp.y) / 16) % 2 == 0)
          {
            if ((int)std::abs((t * dz + tmp.z) / 16) % 2 == 0)
            {
              bMap.SetPixel(h, v, green);
            }
          }
          else
          {
            if ((int)std::abs((t * dz + tmp.z) / 16) % 2 == 1)
            {
              bMap.SetPixel(h, v, blue);
            }
          }
        }
      }
    }
    //Offset ray position by one
    tmp.y += cx;
    tmp.z += sx;
  }
}

【问题讨论】:

  • 它画了什么?建议包括截图

标签: c++ raytracing


【解决方案1】:

问题是由程序如何确定光线的位置和方向引起的。由于对光线追踪的工作原理存在误解,我给每条光线一个独特的位置。相反,所有光线应该共享相同的位置,并根据由屏幕位置缩放并以每个像素为中心的光线角度映射到屏幕空间。这应该占屏幕空间中的每个象限。因此:

angle_x = (2 * ((screen_x + 0.5) / screen_width) - 1) * tan(pi / 2 * fov / 180) * ascpect_ratio

angle_y = (1 - 2 * ((screen_y + 0.5) / screen_height)) * tan(pi / 2 * fov / 180)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-04-13
    • 1970-01-01
    • 2019-03-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-12-01
    相关资源
    最近更新 更多