Compare commits
	
		
			5 Commits
		
	
	
		
			93330c85c2
			...
			4ccba24017
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 4ccba24017 | |||
| 3adf674871 | |||
| f1269753f9 | |||
| c41297b074 | |||
| ac6cc84bf5 | 
| @ -3,3 +3,9 @@ | |||||||
| Ray tracing rendering experiments | Ray tracing rendering experiments | ||||||
| 
 | 
 | ||||||
| https://raytracing.github.io/ | https://raytracing.github.io/ | ||||||
|  | 
 | ||||||
|  | Produced PPM images can be converted to PNG with `imagemagick`: | ||||||
|  | 
 | ||||||
|  | ``` | ||||||
|  | convert image.ppm image.png | ||||||
|  | ``` | ||||||
|  | |||||||
							
								
								
									
										
											BIN
										
									
								
								screenshots/pinkspheres.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								screenshots/pinkspheres.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 2.1 MiB | 
							
								
								
									
										
											BIN
										
									
								
								screenshots/ring.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								screenshots/ring.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 2.4 MiB | 
							
								
								
									
										44
									
								
								src/camera.h
									
									
									
									
									
								
							
							
						
						
									
										44
									
								
								src/camera.h
									
									
									
									
									
								
							| @ -5,22 +5,40 @@ | |||||||
| class camera | class camera | ||||||
| { | { | ||||||
|     public: |     public: | ||||||
|         const double ASPECT_RATIO = 16.0 / 9.0; |         camera( | ||||||
|         const double VIEWPORT_HEIGHT = 2.0; |             point3  lookfrom, | ||||||
|         const double VIEWPORT_WIDTH = ASPECT_RATIO * VIEWPORT_HEIGHT; |             point3  lookat, | ||||||
|         const double FOCAL_LENGTH = 1.0; |             vec3    vup, | ||||||
| 
 |             double  vfov,   // vertical field of view in degrees
 | ||||||
|         camera() :  |             double  aspect_ratio, | ||||||
|             origin_     (point3(0,0,0)), |             double  aperture, | ||||||
|             horizontal_ (vec3(VIEWPORT_WIDTH,0.0,0.0)), |             double  focus_dist) | ||||||
|             vertical_   (vec3(0.0, VIEWPORT_HEIGHT, 0.0)) |  | ||||||
|         { |         { | ||||||
|             lower_left_corner_ = origin_ - horizontal_/2 - vertical_/2 - vec3(0,0,FOCAL_LENGTH); |             auto theta = degrees_to_radians(vfov); | ||||||
|  |             auto h = tan(theta/2); | ||||||
|  |             auto viewport_height = 2.0 * h; | ||||||
|  |             auto viewport_width = aspect_ratio * viewport_height; | ||||||
|  | 
 | ||||||
|  |             w_ = unit_vector(lookfrom - lookat); | ||||||
|  |             u_ = unit_vector(cross(vup, w_)); | ||||||
|  |             v_ = cross(w_, u_); | ||||||
|  | 
 | ||||||
|  |             origin_ = lookfrom; | ||||||
|  |             horizontal_ = focus_dist * viewport_width * u_; | ||||||
|  |             vertical_ = focus_dist * viewport_height * v_; | ||||||
|  |             lower_left_corner_ = origin_ - horizontal_/2 - vertical_/2 - focus_dist * w_; | ||||||
|  | 
 | ||||||
|  |             lens_radius_ = aperture / 2; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         ray get_ray(double u, double v) const  |         ray get_ray(double s, double t) const  | ||||||
|         { |         { | ||||||
|             return ray(origin_, lower_left_corner_ + u*horizontal_ + v*vertical_ - origin_); |             vec3 rd = lens_radius_ * random_in_unit_disk(); | ||||||
|  |             vec3 offset = (u_ * rd.x()) + (v_ * rd.y()); | ||||||
|  | 
 | ||||||
|  |             return ray( | ||||||
|  |                 origin_ + offset, | ||||||
|  |                 lower_left_corner_ + s*horizontal_ + t*vertical_ - origin_ - offset); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|     private: |     private: | ||||||
| @ -28,4 +46,6 @@ class camera | |||||||
|         point3  lower_left_corner_; |         point3  lower_left_corner_; | ||||||
|         vec3    horizontal_; |         vec3    horizontal_; | ||||||
|         vec3    vertical_; |         vec3    vertical_; | ||||||
|  |         vec3    u_, v_, w_; | ||||||
|  |         double  lens_radius_; | ||||||
| }; | }; | ||||||
|  | |||||||
							
								
								
									
										114
									
								
								src/main.cpp
									
									
									
									
									
								
							
							
						
						
									
										114
									
								
								src/main.cpp
									
									
									
									
									
								
							| @ -9,17 +9,22 @@ | |||||||
| #include <iostream> | #include <iostream> | ||||||
| 
 | 
 | ||||||
| const double ASPECT_RATIO = 16.0 / 9.0; | const double ASPECT_RATIO = 16.0 / 9.0; | ||||||
| const int WIDTH = 384; | const int WIDTH = 1920; | ||||||
| const int HEIGHT = static_cast<int>(WIDTH / ASPECT_RATIO); | const int HEIGHT = static_cast<int>(WIDTH / ASPECT_RATIO); | ||||||
| const int SAMPLES_PER_PIXEL = 100; | const int SAMPLES_PER_PIXEL = 8; | ||||||
| const int MAX_DEPTH = 50; | const int MAX_DEPTH = 5; | ||||||
|  | 
 | ||||||
|  | // fee2aa
 | ||||||
|  | // 
 | ||||||
|  | const colour pink(254.0/255.0, 226.0/255.0, 170.0/255.0); | ||||||
|  | const colour grey(0.133, 0.133, 0.133); | ||||||
| 
 | 
 | ||||||
| colour ray_colour(const ray& r, const hittable& world, int depth) | colour ray_colour(const ray& r, const hittable& world, int depth) | ||||||
| { | { | ||||||
|     hit_record rec; |     hit_record rec; | ||||||
|     if (depth <= 0) |     if (depth <= 0) | ||||||
|     { |     { | ||||||
|         return colour(0,0,0); |         return grey; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     if (world.hit(r, 0.001, infinity, rec)) |     if (world.hit(r, 0.001, infinity, rec)) | ||||||
| @ -32,43 +37,96 @@ colour ray_colour(const ray& r, const hittable& world, int depth) | |||||||
|             return attenuation * ray_colour(scattered, world, depth-1); |             return attenuation * ray_colour(scattered, world, depth-1); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         return colour(0,0,0); |         return grey; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     vec3 unit_direction = unit_vector(r.direction()); |     vec3 unit_direction = unit_vector(r.direction()); | ||||||
|     auto t = 0.5 * (unit_direction.y() + 1.0); |     auto t = 0.5 * (unit_direction.y() + 1.0) + 0.5; | ||||||
| 
 | 
 | ||||||
|     auto a = colour(0.5, 0.6, 0.7); |     return lerp(grey, pink, t); | ||||||
|     auto b = colour(1.0, 1.0, 1.0); | } | ||||||
| 
 | 
 | ||||||
|     return lerp(a, b, t); | hittable_list random_scene() | ||||||
|  | { | ||||||
|  |     hittable_list world; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |     //auto ground_material = make_shared<lambertian>(pink);
 | ||||||
|  |     //world.add(make_shared<sphere>(point3(0,-1000,0), 1000, ground_material));
 | ||||||
|  | 
 | ||||||
|  |     //for (int a = -11; a < 11; a++)
 | ||||||
|  |     //{
 | ||||||
|  |     //    for (int b = -11; b < 11; b++)
 | ||||||
|  |     //    {
 | ||||||
|  |     //        auto choose_mat = random_double();
 | ||||||
|  |     //        point3 centre(a + 0.9*random_double(), 0.2, b + 0.9*random_double());
 | ||||||
|  | 
 | ||||||
|  |     //        if ((centre - point3(4, 0.2, 0)).length() > 0.9)
 | ||||||
|  |     //        {
 | ||||||
|  |     //            shared_ptr<material> sphere_material;
 | ||||||
|  | 
 | ||||||
|  |     //            if (choose_mat < 0.8)
 | ||||||
|  |     //            {
 | ||||||
|  |     //                // diffuse
 | ||||||
|  |     //                //auto albedo = colour::random() * colour::random();
 | ||||||
|  |     //                sphere_material = make_shared<lambertian>(pink);
 | ||||||
|  |     //                world.add(make_shared<sphere>(centre, 0.2, sphere_material));
 | ||||||
|  |     //            }
 | ||||||
|  |     //            else if (choose_mat < 0.95)
 | ||||||
|  |     //            {
 | ||||||
|  |     //                // metal
 | ||||||
|  |     //                auto fuzz = random_double(0, 0.5);
 | ||||||
|  |     //                sphere_material = make_shared<metal>(pink, fuzz);
 | ||||||
|  |     //                world.add(make_shared<sphere>(centre, 0.2, sphere_material));
 | ||||||
|  |     //            }
 | ||||||
|  |     //            else
 | ||||||
|  |     //            {
 | ||||||
|  |     //                // glass
 | ||||||
|  |     //                sphere_material = make_shared<dielectric>(1.5);
 | ||||||
|  |     //                world.add(make_shared<sphere>(centre,0.2, sphere_material));
 | ||||||
|  |     //            }
 | ||||||
|  |     //        }
 | ||||||
|  |     //    }
 | ||||||
|  |     //}
 | ||||||
|  | 
 | ||||||
|  |     auto material1 = make_shared<dielectric>(1.5); | ||||||
|  |     world.add(make_shared<sphere>(point3(0, 0, 0), 3.0, material1)); | ||||||
|  | 
 | ||||||
|  |     //auto material2 = make_shared<lambertian>(pink);
 | ||||||
|  |     //world.add(make_shared<sphere>(point3(-4, 1, 0), 1.0, material2));
 | ||||||
|  |      | ||||||
|  |     auto material3 = make_shared<metal>(pink, 0.5); | ||||||
|  |     int sphere_count = 10; | ||||||
|  |     for (int i = 0; i < sphere_count; i++) | ||||||
|  |     { | ||||||
|  |         float a = 6.28 * (float)i/sphere_count - 100.0; | ||||||
|  |         float r = 8.0; | ||||||
|  |         float x = r*sin(a); | ||||||
|  |         float y = 2.0*cos(a); | ||||||
|  |         float z = r*cos(a); | ||||||
|  |         point3 pos(x,y,z); | ||||||
|  |         world.add(make_shared<sphere>(pos, 2.0, material3)); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |     return world; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| int main() | int main() | ||||||
| { | { | ||||||
|     std::cout << "P3\n" << WIDTH << ' ' << HEIGHT << "\n255\n"; |     std::cout << "P3\n" << WIDTH << ' ' << HEIGHT << "\n255\n"; | ||||||
| 
 | 
 | ||||||
|     hittable_list world; |     hittable_list world = random_scene(); | ||||||
| 
 | 
 | ||||||
|     world.add(make_shared<sphere>( |     auto dist_to_target = 10.0; | ||||||
|         point3(0,0,-1), |     auto dist_to_focus = dist_to_target + 1.0; | ||||||
|         0.5, |     auto cam_y = 1.0; | ||||||
|         make_shared<lambertian>(colour(0.7,0.3,0.3)))); |     point3 lookfrom(0,cam_y,-dist_to_target); | ||||||
|     world.add(make_shared<sphere>( |     point3 lookat(0,0,0); | ||||||
|         point3(0,-100.5,-1), |     vec3 vup(0,1,0); | ||||||
|         100, |     auto aperture = 0.5; | ||||||
|         make_shared<lambertian>(colour(0.8,0.8,0.0)))); |  | ||||||
| 
 | 
 | ||||||
|     world.add(make_shared<sphere>( |     camera cam(lookfrom, lookat, vup, 47, ASPECT_RATIO, aperture, dist_to_focus); | ||||||
|         point3(1,0,-1), |  | ||||||
|         0.5, |  | ||||||
|         make_shared<metal>(colour(0.8,0.6,0.2)))); |  | ||||||
|     world.add(make_shared<sphere>( |  | ||||||
|         point3(-1,0,-1), |  | ||||||
|         0.5, |  | ||||||
|         make_shared<metal>(colour(0.8,0.8,0.8)))); |  | ||||||
| 
 |  | ||||||
|     camera cam; |  | ||||||
| 
 | 
 | ||||||
|     for (int j = HEIGHT - 1; j >= 0; --j) |     for (int j = HEIGHT - 1; j >= 0; --j) | ||||||
|     { |     { | ||||||
|  | |||||||
| @ -13,6 +13,13 @@ class material | |||||||
|             ray& scattered) const = 0; |             ray& scattered) const = 0; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | double schlick(double cosine, double refraction_index) | ||||||
|  | { | ||||||
|  |     auto r0 = (1-refraction_index) / (1+refraction_index); | ||||||
|  |     r0 = r0*r0; | ||||||
|  |     return r0 + (1-r0)*pow(1-cosine, 5); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| class lambertian : public material | class lambertian : public material | ||||||
| { | { | ||||||
|     public: |     public: | ||||||
| @ -37,7 +44,9 @@ class lambertian : public material | |||||||
| class metal : public material | class metal : public material | ||||||
| { | { | ||||||
|     public: |     public: | ||||||
|         metal(const colour& a) : albedo_(a) {} |         metal(const colour& a, double f) :  | ||||||
|  |             albedo_(a), | ||||||
|  |             fuzz_(f < 1 ? f : 1) {} | ||||||
| 
 | 
 | ||||||
|     virtual bool scatter( |     virtual bool scatter( | ||||||
|         const ray& r_in,  |         const ray& r_in,  | ||||||
| @ -46,11 +55,55 @@ class metal : public material | |||||||
|         ray& scattered) const  |         ray& scattered) const  | ||||||
|     { |     { | ||||||
|         vec3 reflected = reflect(unit_vector(r_in.direction()), rec.normal); |         vec3 reflected = reflect(unit_vector(r_in.direction()), rec.normal); | ||||||
|         scattered = ray(rec.p, reflected); |         scattered = ray(rec.p, reflected + fuzz_*random_in_unit_sphere()); | ||||||
|         attenuation = albedo_; |         attenuation = albedo_; | ||||||
|         return dot(scattered.direction(), rec.normal) > 0; |         return dot(scattered.direction(), rec.normal) > 0; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     private: |     private: | ||||||
|         colour albedo_; |         colour albedo_; | ||||||
|  |         double fuzz_; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | class dielectric : public material | ||||||
|  | { | ||||||
|  |     public: | ||||||
|  |         dielectric(double ri) : refraction_index_(ri) {} | ||||||
|  | 
 | ||||||
|  |     virtual bool scatter( | ||||||
|  |         const ray& r_in,  | ||||||
|  |         const hit_record& rec,  | ||||||
|  |         colour& attenuation,  | ||||||
|  |         ray& scattered) const  | ||||||
|  |     { | ||||||
|  |         attenuation = colour(1.0,1.0,1.0); | ||||||
|  |         double etai_over_etat = rec.front_face ? (1.0 / refraction_index_) : refraction_index_; | ||||||
|  | 
 | ||||||
|  |         vec3 unit_direction = unit_vector(r_in.direction()); | ||||||
|  | 
 | ||||||
|  |         double cos_theta = fmin(dot(-unit_direction, rec.normal), 1.0); | ||||||
|  |         double sin_theta = sqrt(1.0 - cos_theta*cos_theta); | ||||||
|  |         if (etai_over_etat * sin_theta > 1.0) | ||||||
|  |         { | ||||||
|  |             vec3 reflected = reflect(unit_direction, rec.normal); | ||||||
|  |             scattered = ray(rec.p, reflected); | ||||||
|  |             return true; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         double reflect_prob = schlick(cos_theta, etai_over_etat); | ||||||
|  |         if (random_double() < reflect_prob) | ||||||
|  |         { | ||||||
|  |             vec3 reflected = reflect(unit_direction, rec.normal); | ||||||
|  |             scattered = ray(rec.p, reflected); | ||||||
|  |             return true; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         vec3 refracted = refract(unit_direction, rec.normal, etai_over_etat); | ||||||
|  |         scattered = ray(rec.p, refracted); | ||||||
|  | 
 | ||||||
|  |         return true; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     private: | ||||||
|  |         double refraction_index_; | ||||||
| }; | }; | ||||||
|  | |||||||
							
								
								
									
										19
									
								
								src/vec3.h
									
									
									
									
									
								
							
							
						
						
									
										19
									
								
								src/vec3.h
									
									
									
									
									
								
							| @ -160,7 +160,26 @@ vec3 random_in_hemisphere(const vec3& normal) | |||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | vec3 random_in_unit_disk() | ||||||
|  | { | ||||||
|  |     while(true) | ||||||
|  |     { | ||||||
|  |         auto p = vec3(random_double(-1,1), random_double(-1,1), 0); | ||||||
|  |         if (p.length_squared() >= 1) continue; | ||||||
|  |         return p; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
| vec3 reflect(const vec3& v, const vec3& n) | vec3 reflect(const vec3& v, const vec3& n) | ||||||
| { | { | ||||||
|     return v - 2*dot(v,n)*n; |     return v - 2*dot(v,n)*n; | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | vec3 refract(const vec3& uv, const vec3& n, double etai_over_etat) | ||||||
|  | { | ||||||
|  |     auto cos_theta = dot(-uv, n); | ||||||
|  |     vec3 r_out_parallel = etai_over_etat * (uv + cos_theta*n); | ||||||
|  |     vec3 r_out_perp = -sqrt(1.0 - r_out_parallel.length_squared()) * n; | ||||||
|  | 
 | ||||||
|  |     return r_out_parallel + r_out_perp; | ||||||
|  | } | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user