Tagged: 

Viewing 1 reply thread
  • Author
    Posts
    • #7659 Score: 0
      Knewhow
      Participant
      1 pt

      我的光线和三角形求交的代码如下:

      
      inline Intersection Triangle::getIntersection(Ray ray)
      {
          Intersection inter;
      
          if (dotProduct(ray.direction, normal) > 0)
              return inter;
          double u, v, t_tmp = 0;
          Vector3f pvec = crossProduct(ray.direction, e2);
          double det = dotProduct(e1, pvec);
          if (fabs(det) < EPSILON)
              return inter;
      
          double det_inv = 1. / det;
          Vector3f tvec = ray.origin - v0;
          u = dotProduct(tvec, pvec) * det_inv;
          if (u < 0 || u > 1)
              return inter;
          Vector3f qvec = crossProduct(tvec, e1);
          v = dotProduct(ray.direction, qvec) * det_inv;
          if (v < 0 || u + v > 1)
              return inter;
          t_tmp = dotProduct(e2, qvec) * det_inv;
          
          inter.happened = true;
          inter.distance = t_tmp;
          inter.obj = this;
          inter.coords = Vector3f(ray.origin + t_tmp * ray.direction);
          inter.normal = this->normal;
          inter.m = this->m;
          return inter;
      }
      

      光线和包围盒求交的IntersectP 代码如下:

      
      inline bool Bounds3::IntersectP(const Ray& ray, const Vector3f& invDir,
                                      const std::array<int, 3>& dirIsNeg) const
      {
         float t_min_x = (pMin.x - ray.origin.x) * invDir.x;
          float t_min_y = (pMin.y - ray.origin.y) * invDir.y;
          float t_min_z = (pMin.z - ray.origin.z) * invDir.z;
      
          float t_max_x = (pMax.x - ray.origin.x) * invDir.x;
          float t_max_y = (pMax.y - ray.origin.y) * invDir.y;
          float t_max_z = (pMax.z - ray.origin.z) * invDir.z;
      
          if(!dirIsNeg[0]) {
              std::swap(t_min_x, t_max_x);
          }
      
          if(!dirIsNeg[1]) {
              std::swap(t_min_y, t_max_y);
          }
      
          if(!dirIsNeg[2]) {
              std::swap(t_min_z, t_max_z);
          }
      
          float t_enter = std::max(t_min_x, std::max(t_min_y, t_min_z));
          float t_exit = std::min(t_max_x, std::min(t_max_y, t_max_z));
      
          return t_exit > t_enter && t_exit > 0;
      }
      

      BVH 扫描算法如下:

      
      Intersection BVHAccel::getIntersection(BVHBuildNode* node, const Ray& ray) const
      {
          std::array<int, 3> dirIsNeg = std::array<int, 3>{(int)(ray.direction.x > 0), (int)(ray.direction.y > 0), (int)(ray.direction.z > 0)};
          if(node->bounds.IntersectP(ray, ray.direction_inv, dirIsNeg)) {
              if(node->left == nullptr && node->right == nullptr) {
                  return node->object->getIntersection(ray);
              } else {
                  Intersection left = getIntersection(node->left, ray);
                  Intersection right = getIntersection(node->right, ray);
                  return left.distance < right.distance ? left : right;
              }
          } else {
              return Intersection();
          }
      }
      

      最后Path tracing 算法如下:

      
      // Implementation of Path Tracing
      Vector3f Scene::castRay(const Ray &ray, int depth) const
      {
          Intersection p = intersect(ray);
          if(p.happened) {
              Vector3f L_dir = Vector3f(0.0f,0.0f,0.0f);
              Vector3f L_indir = Vector3f(0.0f,0.0f,0.0f);
              Material* m = p.m;
              float pdf_light;
              Intersection light;
              sampleLight(light, pdf_light);
              Vector3f wo = normalize(ray.direction);
              Vector3f ws = normalize(light.coords - p.coords);
              Vector3f p_normal = normalize(p.normal);
              Vector3f light_normal = normalize(light.normal);
              Ray test_p_to_light_ray(p.coords, ws);
              auto p_to_light_test_result = this->intersect(test_p_to_light_ray);
              float d = (light.coords - p_to_light_test_result.coords).norm();
              if(d < 0.1) { // no block
                  float distance = (p.coords - light.coords).norm();
                  L_dir = light.emit * m->eval(wo, ws, p_normal) * dotProduct(ws, p_normal) * dotProduct(ws, light_normal)  / (distance * distance * pdf_light); 
              }
               else {
                  return Vector3f(255.0f, 255.0f, 255.0f);
              }
              
      
              float ksi = (float)(std::rand() % 100) / 100.0f;
              if(ksi < this->RussianRoulette) {
                  Vector3f wi = p.m->sample(wo, p_normal).normalized();
                  Ray indir_ray(p.coords, wi);
                  auto indir_result = this->intersect(indir_ray);
                  if(indir_result.happened && !indir_result.obj->hasEmit()) { // collision a object but not light
                      L_indir = castRay(indir_ray, depth + 1) * p.m->eval(wo, wi, p_normal) * dotProduct(wi, p_normal) / p.m->pdf(wo, wi, p_normal) / this->RussianRoulette;
                  }
              }
              return L_dir + L_indir;
          } else {
              return Vector3f();
          }
      

      可是最后的结果只有黑白:

      • This topic was modified 3 years, 2 months ago by Knewhow. Reason: 代码重新格式一下
      Attachments:
      You must be logged in to view attached files.
    • #7660 Score: 0
      Knewhow
      Participant
      1 pt

      希望哪位大神有空帮我看一下,谢谢!

      • This reply was modified 3 years, 2 months ago by Knewhow. Reason: 取消多余的代码
      Attachments:
      You must be logged in to view attached files.
Viewing 1 reply thread
  • You must be logged in to reply to this topic.