【图形学】Ray Tracing in a Weekend [2]
1.光线追踪
实现类:vec3,sphere(球体),ray(射线,由射线起始点+射线方向向量组成)
camera.h hitable.h hitable_list.h
ray.cpp + ray.h
sphere.h
vec3.h + vec3.cpp
图显示工具:ffplay.exe
sphere.h
#ifndef SPHEREH #define SPHEREH #include "hitable.h" class sphere: public hitable { public: sphere() {} sphere(vec3 cen, float r): center(cen), radius(r) {} virtual bool hit(const ray& r, float tmin, float tmax, hit_record& rec) const; vec3 center; float radius; }; bool sphere::hit(const ray& r, float t_min, float t_max, hit_record& rec) const { vec3 oc = r.origin() - center; float a = dot(r.direction(), r.direction()); float b = dot(oc, r.direction()); float c = dot(oc, oc) - radius * radius; float discriminant = b * b - a * c; if (discriminant > 0) { float temp = (-b - sqrt(b * b - a * c)) / a; if (temp < t_max && temp > t_min) { rec.t = temp; rec.p = r.point_at_parameter(rec.t); rec.normal = (rec.p - center) / radius; return true; } temp = (-b + sqrt(b * b - a * c)) / a; if (temp < t_max && temp > t_min) { rec.t = temp; rec.p = r.point_at_parameter(rec.t); rec.normal = (rec.p - center) / radius; return true; } } return false; } #endif
着色消除锯齿
增加光照反射
vec3 color(const ray& r, hitable* world) { hit_record rec; if (world->hit(r, 0.001, FLT_MAX, rec)) { vec3 rnd = random_in_unit_shpere(); vec3 target = rec.p + rec.normal + rnd; // printf("%f %f %f\n", rnd[0], rnd[1], rnd[2]); return 0.5 * color(ray(rec.p, target - rec.p), world); } else { vec3 unit_direction = unit_vector(r.direction()); float t = 0.5 * (unit_direction.y() + 1.0); return (1.0 - t) * vec3(1.0, 1.0, 1.0) + t * vec3(0.5, 0.7, 1.0); } }
增加纹理
#ifdef MATERIAL_H #define MATERIAL_H #include "ray.h" #include "hitable.h" vec3 reflect(const vec3& v, const vec3& n) { return v - 2 * dot(v, n) * n; } class material { public: virtual bool scatter(const ray& r_in, const hit_record& rec, vec3& attenuation, ray& scattered) const = 0; }; class lambertian: public material { public: lambertian(const vec3& a):albedo(a) {} virtual bool scatter(const ray& r_in, const hit_record& rec, vec3& attenuation, ray& scattered)const { vec3 target = rec.p + rec.normal + random_in_unit_sphere(); scattered = ray(rec.p, target - rec.p); attenuation = albedo; return true; } vec3 albedo; }; class metal: public material { public: metal(const vec3& a): albedo(a) {} virtual bool scatter(const ray& r_in, const hit_record& rec, vec3& attenuation, ray& scattered)const { vec3 reflected = reflect(unit_vector(r_in.direction()), rec.normal); scattered = ray(rec.p, reflected); attenuation = albedo; return dot(scattered.direction(), rec.normal) > 0; } vec3 albedo; // float fuzz; }; #endif
增加球体个数
int main() { int nx = 200; int ny = 100; int ns = 100; cout << "P3\n" << nx << " " << ny << "\n255\n"; // vec3 lower_left_corner(-2.0, -1.0, -1.0); // vec3 horizontal(4.0, 0.0, 0.0); // vec3 vertical(0.0, 2.0, 0.0); // vec3 origin(0.0, 0.0, 0.0); hitable* list[4]; list[0] = new sphere(vec3(0, 0, -1), 0.5, new lambertian(vec3(0.8, 0.3, 0.3))); list[1] = new sphere(vec3(0, -100.5, -1), 100, new lambertian(vec3(0.8, 0.8, 0.0))); list[2] = new sphere(vec3(1, 0, -1), 0.5, new metal(vec3(0.8, 0.6, 0.2))); list[3] = new sphere(vec3(-1, 0, -1), 0.5, new metal(vec3(0.8, 0.8, 0.8))); hitable* world = new hitable_list(list, 4); camera cam; for (int j = ny - 1; j >= 0; j--) { for (int i = 0; i < nx; i++) { vec3 col(0, 0, 0); for (int s = 0; s < ns; s++) { float u = float(i + drand48()) / float(nx); float v = float(j + drand48()) / float(ny); ray r = cam.get_ray(u, v); vec3 p = r.point_at_parameter(2.0); col += color(r, world, 0); } col /= float(ns); col = vec3(sqrt(col[0]), sqrt(col[1]), sqrt(col[2])); // cout << u << " " << v << endl; // vec3 col = color(r, world); int ir = int(255.99 * col[0]); int ig = int(255.99 * col[1]); int ib = int(255.99 * col[2]); cout << ir << " " << ig << " " << ib << endl; } } return 0; }
带金属光泽的纹理
class metal: public material { public: metal(const vec3& a, float f): albedo(a) {if (f < 1) fuzz = f; else fuzz = 1;} virtual bool scatter(const ray& r_in, const hit_record& rec, vec3& attenuation, ray& scattered)const { vec3 reflected = reflect(unit_vector(r_in.direction()), rec.normal); scattered = ray(rec.p, reflected + fuzz * random_in_unit_sphere()); attenuation = albedo; return dot(scattered.direction(), rec.normal) > 0; } vec3 albedo; float fuzz; };
9. 加入Dielectrics 折射
10. 视角切换
12. 随机场景scene的渲染
分类:
图形学
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通