使用计算着色器从GLSL中的一个周末进行光线跟踪的非递归ray_color函数 [英] Non recursive ray_color function from Raytracing in One Weekend in GLSL using compute shaders

查看:71
本文介绍了使用计算着色器从GLSL中的一个周末进行光线跟踪的非递归ray_color函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

我只是想转换P. Shirley的书ray_color 函数 ="nofollow noreferrer">此处.

提到的 ray_color 函数:

  color ray_color(const ray&r,const hittable& world,int depth){hit_record rec;//如果我们超过了射线反射限制,则不会再收集更多的光.如果(深度< = 0)返回颜色(0,0,0);如果(world.hit(r,0.001,infinity,rec)){point3目标= rec.p + rec.normal + random_unit_vector();返回0.5 * ray_color(ray(rec.p,target-rec.p),world,depth-1);}vec3 unit_direction = unit_vector(r.direction());自动t = 0.5 *(unit_direction.y()+ 1.0);返回(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);浮点温度= 0.5 *(dir.y + 1.0);vec3 cval = vec3(1.0-temp)+ temp * vec3(0.5,0.7,1.0);返回cval;}vec3 ray_color(在Ray r中,在Scene场景中,int深度){//雷·林r_in.origin = r.origin;r_in.direction = r.direction;vec3 bcolor = vec3(1);而(true){雷r_out;如果(深度< = 0){//返回vec3(0);}HitRecord rec;如果(hit_scene(scene,r_in,0.001,INFINITY,rec)){vec3目标=记录点+ random_in_hemisphere(rec.normal);r_in = makeRay(rec.point,target-rec.point);深度 - ;bcolor * = 0.5;} 别的 {bcolor * = no_hit_color(r_in);返回bcolor;}}} 

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

更新1:

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

解决方案

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

 <代码>//glsl版本vec3 ray_color(在Ray r中,在Scene场景中,int深度){//雷·林r_in.origin = r.origin;r_in.direction = r.direction;vec3 bcolor = vec3(1);而(true){如果(深度< = 0){//返回vec3(0);//返回bcolor;}HitRecord rec;如果(hit_scene(scene,r_in,0.001,INFINITY,rec)){vec3目标=记录点+ random_in_hemisphere(rec.normal);r_in = makeRay(rec.point,target-rec.point);深度 - ;bcolor * = 0.5;} 别的 {vec3 dir = normalize(r_in.direction);浮点温度= 0.5 *(dir.y + 1.0);bcolor * = vec3(1.0-temp)+ temp * vec3(0.5,0.7,1.0);返回bcolor;}}} 

 <代码>//cpp版本color ray_color2(const Ray& r,const HittableList& scene,int depth){Ray r_in = Ray(r.origin,r.direction);color rcolor = color(1);而(true){HitRecord记录;如果(深度< = 0){//最后的情况返回颜色(0);}如果(scene.hit(r_in,0.001,INF,记录)){//递归的情况point3目标= record.point + random_in_hemisphere(record.normal);r_in = Ray(记录点,目标-记录点);深度 - ;rcolor * = 0.5;} 别的 {vec3 direction = to_unit(r_in.direction);双温度= 0.5 *(direction.y + 1.0);rcolor * =(1.0-temp)* color(1.0)+ temp * color(0.5,0.7,1.0);返回rcolor;}}} 

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

I am trying to write a real time ray tracer using compute shaders in opengl 4.3. I know that this is a rather popular question. I have checked this, and this, but the architecture provided over there does not really correspond to my use case.

I am simply trying to transform the ray_color function provided in the P. Shirley's book here into a non recursive function.

The mentioned ray_color function:

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);
}

Here is my attempt:


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;
    }
  }
}

If I use a static value for depth, with something like #define MAX_DEPTH, I think i can implement the algorithm, by making my own stack, but I would like to keep the depth as dynamic variable where I can let users tweak according to their computing power. So I would like to implement it using while if possible. My version produces a black slice near the bottom of the sphere, which does not correspond to the reference picture.

Update 1:

I am slightly convinced that the above implementation is correct but my camera position from which I am generating rays is problematic.

解决方案

I have confirmed that the implementation is indeed correct. Here is a glsl version and c++ version for future reference. It should give you a direction for implementing more complex stuff later on.

// 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;
    }
  }
}

Basically as long as the contribution of rays can be modeled with a linear operator, it should be possible to use while loop to implement the function. Notice that the function does not use a call stack, thus it can be used where the maximum bounce rate, or maximum depth whichever you prefer, for rays is dynamic.

这篇关于使用计算着色器从GLSL中的一个周末进行光线跟踪的非递归ray_color函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆