zoukankan      html  css  js  c++  java
  • 【图像处理】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
    ", 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
    " << nx << " " << ny << "
    255
    ";
        // 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的渲染

     

     

     

  • 相关阅读:
    指令周期与机器周期
    MFC使用Access数据库
    函数指针的用途
    大端模式和小端模式
    Matlab信号展开
    EL表达式的11个内置对象
    JSP 4个域对象、7个动作指令、9个内置对象
    阿里巴巴java代码规范
    HDDATA基本注意事项
    SVN相关
  • 原文地址:https://www.cnblogs.com/wangzming/p/11967122.html
Copyright © 2011-2022 走看看