【问题标题】:Raytracing Normalizing Screenspace光线追踪归一化屏幕空间
【发布时间】:2019-09-14 06:53:21
【问题描述】:

我在 -1 到 +1 的范围内标准化了我的屏幕坐标。然后我从这些归一化坐标开始追踪一些光线,并使用原点和方向向量计算有符号距离场 (sdf)。

for (int i = 0; i < rterm::w; i++)
  for (int j = 0; j < rterm::h; j++) {
    float x = i / (rterm::w / 2.0f) - 1.0f;
    float y = j / (rterm::h / 2.0f) - 1.0f;

    glm::vec3 o = glm::vec3(x, y, -10.0f);
    glm::vec3 d = glm::vec3(0.0f, 0.0f, 1.0f);

    if (trace(o, d))
      rterm::ctx->buffer[i + j * rterm::w] = '#';
}

sdf 工作正常,但我的代码中一定有错误。栅格化的球体不是球体,更像那样。

+---------------------------------+
|                                 |
|                                 |
|#########                        |
|#################                |
|#####################            |
|#######################          |
|#########################        |
|#########################        |
|#########################        |
|#########################        |
|#########################        |
|#######################          |
|#####################            |
|#################                |
|#########                        |
|                                 |
|                                 |
+---------------------------------+

sdf 只是一个简单的球体。

float sphere(glm::vec3 p, float r) {
  return glm::length(p) - r;
}

float get(glm::vec3 p) {
  float ds = sphere(p, 0.8f);

  return ds;
}

这是我的跟踪实现。

bool trace(glm::vec3 o, glm::vec3 d) {
  float depth = 1.0f;

  for (int i = 0; i < MARCH_STEPS; i++) {
    float dist = sdf::get(o + d * depth);

    if (dist < EPSILON) return true;
    depth += dist;
    if (depth >= CLIP_FAR) return false;
  }

  return false;
}

【问题讨论】:

    标签: c++ mapping raytracing euclidean-distance rasterizing


    【解决方案1】:

    您必须考虑图像的纵横比,通常不会为 1。您目前正在有效地做的是将图像平面定义为宽 2 个单位和 2 个单位高度单位。然后,您将此图像平面细分为沿 x 维度的 rterm::w 像素和沿 y 维度的 rterm::h 像素的网格。请注意,您将光线投射到世界中的区域仍然是矩形,您只需沿 x 和 y 轴以不同的间隔细分它。然后,当您通过某种标准机制显示图像时,假设像素在两个维度上以相同的规则间隔进行采样,图像将出现失真。

    您通常想要做的是沿 x 轴和 y 轴使用相同的空间采样率。到达那里的典型方法是调整您投射光线的区域的 x 或 y 尺寸,以匹配您想要生成的图像分辨率的纵横比。纵横比通常定义为 x 分辨率和 y 分辨率的比值:

    float a = rterm::w * 1.0f / rterm::h;
    

    例如,如果图像的宽度大于高度,则纵横比将大于 1。如果图像的高度大于宽度,则纵横比将小于 1。对于非方形图像,要使沿 x 和 y 的像素位置之间的距离相同,我们可以将 x 坐标缩放a 或将 y 坐标缩放1.0f / a。例如

    float x = a * (i / (rterm::w / 2.0f) - 1.0f);
    float y = j / (rterm::h / 2.0f) - 1.0f;
    

    注意:上面计算纵横比时的* 1.0f 不是多余的。它可以强制在float 中进行计算;否则你最终会得到一个整数除法(假设你的分辨率是由整数类型的值给出的)......

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-02-05
      • 1970-01-01
      • 2018-11-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-03-20
      • 1970-01-01
      相关资源
      最近更新 更多