首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >光线跟踪归一化屏幕空间

光线跟踪归一化屏幕空间
EN

Stack Overflow用户
提问于 2019-04-25 05:56:53
回答 1查看 52关注 0票数 0

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

代码语言:javascript
复制
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工作正常,但我的代码中肯定有bug。光栅化的球体不是球体,它更像是球体。

代码语言:javascript
复制
+---------------------------------+
|                                 |
|                                 |
|#########                        |
|#################                |
|#####################            |
|#######################          |
|#########################        |
|#########################        |
|#########################        |
|#########################        |
|#########################        |
|#######################          |
|#####################            |
|#################                |
|#########                        |
|                                 |
|                                 |
+---------------------------------+

sdf只是一个简单的球体。

代码语言:javascript
复制
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;
}

下面是我的跟踪实现。

代码语言:javascript
复制
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;
}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-04-25 06:28:59

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

您通常要做的是在x和y轴上以相同的空间采样率工作。实现这一点的典型方法是调整投射光线的区域的x或y维度,以匹配要生成的图像分辨率的纵横比。纵横比通常定义为x分辨率和y分辨率之间的比率:

代码语言:javascript
复制
float a = rterm::w * 1.0f / rterm::h;

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

代码语言:javascript
复制
float x = a * (i / (rterm::w / 2.0f) - 1.0f);
float y = j / (rterm::h / 2.0f) - 1.0f;

注意:以上宽高比计算中的* 1.0f不是多余的。它的作用是强制在float中执行计算;否则,您将以整数除法结束(假设您的分辨率是由整型值给出的)…

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/55839136

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档