# 作业要求
完善以下函数:
| |
| Render() |
| |
| |
| |
| rayTriangleIntersect() |
| |
| |
| |
# 作业实现
# Render()
| void Renderer::Render(const Scene &scene) { |
| std::vector<Vector3f> framebuffer(scene.width * scene.height); |
| |
| float scale = std::tan(deg2rad(scene.fov * 0.5f)); |
| float imageAspectRatio = scene.width / (float)scene.height; |
| |
| |
| Vector3f eye_pos(0); |
| int m = 0; |
| for (int j = 0; j < scene.height; ++j) { |
| for (int i = 0; i < scene.width; ++i) { |
| |
| float x; |
| float y; |
| |
| |
| |
| |
| |
| x = (2 * (i + 0.5) / (float)scene.width - 1) * scale * imageAspectRatio; |
| y = (1 - 2 * (j + 0.5) / (float)scene.height) * scale; |
| |
| Vector3f dir = |
| Vector3f(x, y, -1); |
| dir = normalize(dir); |
| framebuffer[m++] = castRay(eye_pos, dir, scene, 0); |
| } |
| UpdateProgress(j / (float)scene.height); |
| } |
| |
| |
| FILE *fp = fopen("binary.ppm", "wb"); |
| (void)fprintf(fp, "P6\n%d %d\n255\n", scene.width, scene.height); |
| for (auto i = 0; i < scene.height * scene.width; ++i) { |
| static unsigned char color[3]; |
| color[0] = (char)(255 * clamp(0, 1, framebuffer[i].x)); |
| color[1] = (char)(255 * clamp(0, 1, framebuffer[i].y)); |
| color[2] = (char)(255 * clamp(0, 1, framebuffer[i].z)); |
| fwrite(color, 1, 3, fp); |
| } |
| fclose(fp); |
| } |
# rayTriangleIntersect()
使用 Moller-Trumbore 算法实现射线与三角形的相交检测。
| bool rayTriangleIntersect(const Vector3f &v0, const Vector3f &v1, |
| const Vector3f &v2, const Vector3f &orig, |
| const Vector3f &dir, float &tnear, float &u, |
| float &v) { |
| |
| |
| |
| |
| |
| |
| Vector3f e1 = v1 - v0; |
| Vector3f e2 = v2 - v0; |
| Vector3f s = orig - v0; |
| Vector3f s1 = crossProduct(dir, e2); |
| Vector3f s2 = crossProduct(s, e1); |
| float t = dotProduct(s2, e2) / dotProduct(s1, e1); |
| float b1 = dotProduct(s1, s) / dotProduct(s1, e1); |
| float b2 = dotProduct(s2, dir) / dotProduct(s1, e1); |
| if (t > 0.0 && b1 > 0.0 && b2 > 0.0 && (1 - b1 - b2) > 0.0) { |
| tnear = t; |
| u = b1; |
| v = b2; |
| return true; |
| } |
| return false; |
| } |