Compare commits
	
		
			5 Commits
		
	
	
		
			93330c85c2
			...
			4ccba24017
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 4ccba24017 | |||
| 3adf674871 | |||
| f1269753f9 | |||
| c41297b074 | |||
| ac6cc84bf5 | 
| @ -3,3 +3,9 @@ | ||||
| Ray tracing rendering experiments | ||||
| 
 | ||||
| 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 | ||||
| { | ||||
|     public: | ||||
|         const double ASPECT_RATIO = 16.0 / 9.0; | ||||
|         const double VIEWPORT_HEIGHT = 2.0; | ||||
|         const double VIEWPORT_WIDTH = ASPECT_RATIO * VIEWPORT_HEIGHT; | ||||
|         const double FOCAL_LENGTH = 1.0; | ||||
| 
 | ||||
|         camera() :  | ||||
|             origin_     (point3(0,0,0)), | ||||
|             horizontal_ (vec3(VIEWPORT_WIDTH,0.0,0.0)), | ||||
|             vertical_   (vec3(0.0, VIEWPORT_HEIGHT, 0.0)) | ||||
|         camera( | ||||
|             point3  lookfrom, | ||||
|             point3  lookat, | ||||
|             vec3    vup, | ||||
|             double  vfov,   // vertical field of view in degrees
 | ||||
|             double  aspect_ratio, | ||||
|             double  aperture, | ||||
|             double  focus_dist) | ||||
|         { | ||||
|             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: | ||||
| @ -28,4 +46,6 @@ class camera | ||||
|         point3  lower_left_corner_; | ||||
|         vec3    horizontal_; | ||||
|         vec3    vertical_; | ||||
|         vec3    u_, v_, w_; | ||||
|         double  lens_radius_; | ||||
| }; | ||||
|  | ||||
							
								
								
									
										114
									
								
								src/main.cpp
									
									
									
									
									
								
							
							
						
						
									
										114
									
								
								src/main.cpp
									
									
									
									
									
								
							| @ -9,17 +9,22 @@ | ||||
| #include <iostream> | ||||
| 
 | ||||
| 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 SAMPLES_PER_PIXEL = 100; | ||||
| const int MAX_DEPTH = 50; | ||||
| const int SAMPLES_PER_PIXEL = 8; | ||||
| 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) | ||||
| { | ||||
|     hit_record rec; | ||||
|     if (depth <= 0) | ||||
|     { | ||||
|         return colour(0,0,0); | ||||
|         return grey; | ||||
|     } | ||||
| 
 | ||||
|     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 colour(0,0,0); | ||||
|         return grey; | ||||
|     } | ||||
| 
 | ||||
|     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); | ||||
|     auto b = colour(1.0, 1.0, 1.0); | ||||
|     return lerp(grey, pink, t); | ||||
| } | ||||
| 
 | ||||
|     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() | ||||
| { | ||||
|     std::cout << "P3\n" << WIDTH << ' ' << HEIGHT << "\n255\n"; | ||||
| 
 | ||||
|     hittable_list world; | ||||
|     hittable_list world = random_scene(); | ||||
| 
 | ||||
|     world.add(make_shared<sphere>( | ||||
|         point3(0,0,-1), | ||||
|         0.5, | ||||
|         make_shared<lambertian>(colour(0.7,0.3,0.3)))); | ||||
|     world.add(make_shared<sphere>( | ||||
|         point3(0,-100.5,-1), | ||||
|         100, | ||||
|         make_shared<lambertian>(colour(0.8,0.8,0.0)))); | ||||
|     auto dist_to_target = 10.0; | ||||
|     auto dist_to_focus = dist_to_target + 1.0; | ||||
|     auto cam_y = 1.0; | ||||
|     point3 lookfrom(0,cam_y,-dist_to_target); | ||||
|     point3 lookat(0,0,0); | ||||
|     vec3 vup(0,1,0); | ||||
|     auto aperture = 0.5; | ||||
| 
 | ||||
|     world.add(make_shared<sphere>( | ||||
|         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; | ||||
|     camera cam(lookfrom, lookat, vup, 47, ASPECT_RATIO, aperture, dist_to_focus); | ||||
| 
 | ||||
|     for (int j = HEIGHT - 1; j >= 0; --j) | ||||
|     { | ||||
|  | ||||
| @ -13,6 +13,13 @@ class material | ||||
|             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 | ||||
| { | ||||
|     public: | ||||
| @ -37,7 +44,9 @@ class lambertian : public material | ||||
| class metal : public material | ||||
| { | ||||
|     public: | ||||
|         metal(const colour& a) : albedo_(a) {} | ||||
|         metal(const colour& a, double f) :  | ||||
|             albedo_(a), | ||||
|             fuzz_(f < 1 ? f : 1) {} | ||||
| 
 | ||||
|     virtual bool scatter( | ||||
|         const ray& r_in,  | ||||
| @ -46,11 +55,55 @@ class metal : public material | ||||
|         ray& scattered) const  | ||||
|     { | ||||
|         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_; | ||||
|         return dot(scattered.direction(), rec.normal) > 0; | ||||
|     } | ||||
| 
 | ||||
|     private: | ||||
|         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) | ||||
| { | ||||
|     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