Home › Forums › GAMES在线课程(现代计算机图形学入门)讨论区 › 作业八全是黑白的
Tagged: 作业八
- This topic has 1 reply, 1 voice, and was last updated 3 years, 10 months ago by Knewhow.
Viewing 1 reply thread
-
AuthorPosts
-
-
我的光线和三角形求交的代码如下:
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, 10 months ago by Knewhow. Reason: 代码重新格式一下
Attachments:
You must be logged in to view attached files.
-
-
AuthorPosts
Viewing 1 reply thread
- You must be logged in to reply to this topic.