使用计算着色器从GLSL中的一个周末进行Raytracing的非递归ray_color函数

问题描述 投票:0回答:1

我正在尝试使用opengl 4.3中的计算着色器编写实时光线跟踪器。我知道这是一个相当受欢迎的问题。我已经检查了thisthis,但是那里提供的体系结构与我的用例并不完全对应。

[我只是试图将P. Shirley的书ray_color中提供的here函数转换为非递归函数。

提到的ray_color功能:

color ray_color(const ray& r, const hittable& world, int depth) {
    hit_record rec;

    // If we've exceeded the ray bounce limit, no more light is gathered.
    if (depth <= 0)
        return color(0,0,0);

    if (world.hit(r, 0.001, infinity, rec)) {
        point3 target = rec.p + rec.normal + random_unit_vector();
        return 0.5 * ray_color(ray(rec.p, target - rec.p), world, depth-1);
    }

    vec3 unit_direction = unit_vector(r.direction());
    auto t = 0.5*(unit_direction.y() + 1.0);
    return (1.0-t)*color(1.0, 1.0, 1.0) + t*color(0.5, 0.7, 1.0);
}

这是我的尝试:


vec3 no_hit_color(in Ray r) {
  vec3 dir = normalize(r.direction);
  float temp = 0.5 * (dir.y + 1.0);
  vec3 cval = vec3(1.0 - temp) + temp * vec3(0.5, 0.7, 1.0);
  return cval;
}

vec3 ray_color(in Ray r, in Scene scene, int depth) {
  //
  Ray r_in;
  r_in.origin = r.origin;
  r_in.direction = r.direction;
  vec3 bcolor = vec3(1);

  while (true) {
    Ray r_out;
    if (depth <= 0) {
      //
      return vec3(0);
    }
    HitRecord rec;
    if (hit_scene(scene, r_in, 0.001, INFINITY, rec)) {
      vec3 target = rec.point + random_in_hemisphere(rec.normal);
      r_in = makeRay(rec.point, target - rec.point);
      depth--;
      bcolor *= 0.5;
    } else {
      bcolor *= no_hit_color(r_in);
      return bcolor;
    }
  }
}

如果我使用静态值作为深度值,例如#define MAX_DEPTH,我想我可以通过制作自己的堆栈来实现该算法,但是我想将深度值保持为动态变量,以便让用户根据发挥他们的计算能力。所以我想在可能的情况下使用while来实现它。我的版本在球体底部附近产生一个黑色切片,该黑色切片与参考图片不对应。

更新1:

我稍微相信上述实现是正确的,但是我从中产生光线的相机位置是有问题的。

glsl raytracing opengl-4 compute-shader non-recursive
1个回答
0
投票

我已经确认实施确实正确。这是glsl版本和c ++版本,以供将来参考。它应该为以后实现更复杂内容的方向提供指导。

// glsl version
vec3 ray_color(in Ray r, in Scene scene, int depth) {
  //
  Ray r_in;
  r_in.origin = r.origin;
  r_in.direction = r.direction;
  vec3 bcolor = vec3(1);

  while (true) {
    if (depth <= 0) {
      //
      return vec3(0);
      // return bcolor;
    }
    HitRecord rec;
    if (hit_scene(scene, r_in, 0.001, INFINITY, rec)) {
      vec3 target = rec.point + random_in_hemisphere(rec.normal);
      r_in = makeRay(rec.point, target - rec.point);
      depth--;
      bcolor *= 0.5;
    } else {
      vec3 dir = normalize(r_in.direction);
      float temp = 0.5 * (dir.y + 1.0);
      bcolor *= vec3(1.0 - temp) + temp * vec3(0.5, 0.7, 1.0);
      return bcolor;
    }
  }
}
// cpp version
color ray_color2(const Ray &r, const HittableList &scene, int depth) {
  Ray r_in = Ray(r.origin, r.direction);
  color rcolor = color(1);
  while (true) {
    HitRecord record;
    if (depth <= 0) {
      // final case
      return color(0);
    }
    if (scene.hit(r_in, 0.001, INF, record)) {
      // recursive case
      point3 target = record.point + random_in_hemisphere(record.normal);
      r_in = Ray(record.point, target - record.point);
      depth--;
      rcolor *= 0.5;
    } else {
      vec3 direction = to_unit(r_in.direction);
      double temp = 0.5 * (direction.y + 1.0);
      rcolor *= (1.0 - temp) * color(1.0) + temp * color(0.5, 0.7, 1.0);
      return rcolor;
    }
  }
}

基本上,只要可以使用线性算子对光线的贡献进行建模,就应该可以使用while循环来实现该功能。请注意,该函数不使用调用堆栈,因此可以在光线的最大跳动率或最大深度是动态的情况下使用。

© www.soinside.com 2019 - 2024. All rights reserved.