implement Material as tagged union
This commit is contained in:
		
							parent
							
								
									bc3fb54991
								
							
						
					
					
						commit
						c842fcf713
					
				
					 2 changed files with 53 additions and 44 deletions
				
			
		|  | @ -14,8 +14,6 @@ const World = @import("world.zig").World; | ||||||
| const Camera = @import("camera.zig").Camera; | const Camera = @import("camera.zig").Camera; | ||||||
| const material = @import("material.zig"); | const material = @import("material.zig"); | ||||||
| const Material = material.Material; | const Material = material.Material; | ||||||
| const MaterialType = material.MaterialType; |  | ||||||
| const scatter = @import("material.zig").scatter; |  | ||||||
| 
 | 
 | ||||||
| // From: https://github.com/Nelarius/weekend-raytracer-zig/blob/master/src/main.zig | // From: https://github.com/Nelarius/weekend-raytracer-zig/blob/master/src/main.zig | ||||||
| // See https://github.com/zig-lang/zig/issues/565 | // See https://github.com/zig-lang/zig/issues/565 | ||||||
|  | @ -46,7 +44,7 @@ fn rayColor(ray: Ray, world: World, rng: *Random, depth: i32) Color { | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     if (world.hit(ray, 0.001, 99999)) |hit| { |     if (world.hit(ray, 0.001, 99999)) |hit| { | ||||||
|         if (scatter(ray, hit, rng)) |sRay| { |         if (material.scatter(ray, hit, rng)) |sRay| { | ||||||
|             return sRay.color.mul(rayColor(sRay.ray, world, rng, depth - 1)); |             return sRay.color.mul(rayColor(sRay.ray, world, rng, depth - 1)); | ||||||
|         } |         } | ||||||
|         return Color{ .x = 0, .y = 0, .z = 0 }; |         return Color{ .x = 0, .y = 0, .z = 0 }; | ||||||
|  | @ -94,20 +92,24 @@ pub fn main() anyerror!void { | ||||||
| 
 | 
 | ||||||
|     // World |     // World | ||||||
|     const materialGround = Material{ |     const materialGround = Material{ | ||||||
|         .materialType = .Lambertian, |         .lambertian = material.Lambertian{ | ||||||
|         .color = Color{ .x = 0.8, .y = 0.8, .z = 0.0 }, |             .color = Color{ .x = 0.8, .y = 0.8, .z = 0.0 } | ||||||
|  |         } | ||||||
|     }; |     }; | ||||||
|     const materialCenter = Material{ |     const materialCenter = Material{ | ||||||
|         .materialType = .Lambertian, |         .lambertian = material.Lambertian{ | ||||||
|         .color = Color{ .x = 0.7, .y = 0.3, .z = 0.3 }, |             .color = Color{ .x = 0.7, .y = 0.3, .z = 0.3 } | ||||||
|  |         } | ||||||
|     }; |     }; | ||||||
|     const materialLeft = Material{ |     const materialLeft = Material{ | ||||||
|         .materialType = .Metal, |         .metal = material.Metal{ | ||||||
|         .color = Color{ .x = 0.8, .y = 0.8, .z = 0.8 }, |             .color = Color{ .x = 0.8, .y = 0.8, .z = 0.8 } | ||||||
|  |         } | ||||||
|     }; |     }; | ||||||
|     const materialRight = Material{ |     const materialRight = Material{ | ||||||
|         .materialType = .Metal, |         .metal = material.Metal{ | ||||||
|         .color = Color{ .x = 0.8, .y = 0.6, .z = 0.2 }, |             .color = Color{ .x = 0.8, .y = 0.6, .z = 0.2 } | ||||||
|  |         } | ||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
|     const spheres = [_]Sphere{ |     const spheres = [_]Sphere{ | ||||||
|  |  | ||||||
|  | @ -7,13 +7,41 @@ const Ray = @import("ray.zig").Ray; | ||||||
| const HitRecord = @import("hittable.zig").HitRecord; | const HitRecord = @import("hittable.zig").HitRecord; | ||||||
| 
 | 
 | ||||||
| pub const MaterialType = enum { | pub const MaterialType = enum { | ||||||
|     Lambertian, |     lambertian, | ||||||
|     Metal, |     metal, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| pub const Material = struct { | pub const Lambertian = struct { | ||||||
|     materialType: MaterialType, |  | ||||||
|     color: Color, |     color: Color, | ||||||
|  | 
 | ||||||
|  |     pub fn scatter(self: Lambertian, ray: Ray, hit: HitRecord, rng: *Random) ?ScatteredRay { | ||||||
|  |         var scatterDirection = hit.normal.add(vec3.random_unit_vector(rng)); | ||||||
|  |         // Catch degenerate scatter direction | ||||||
|  |         if (scatterDirection.nearZero()) { | ||||||
|  |             scatterDirection = hit.normal; | ||||||
|  |         } | ||||||
|  |         return ScatteredRay{ | ||||||
|  |             .ray = Ray{ .origin = hit.p, .direction = scatterDirection}, | ||||||
|  |             .color = self.color, | ||||||
|  |         }; | ||||||
|  |     } | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | pub const Metal = struct { | ||||||
|  |     color: Color, | ||||||
|  |     // fuzzy: f32, | ||||||
|  | 
 | ||||||
|  |     pub fn scatter(self: Metal, ray: Ray, hit: HitRecord, rng: *Random) ?ScatteredRay { | ||||||
|  |         const reflected = ray.direction.unit().reflect(hit.normal); | ||||||
|  |         const scattered = Ray{ .origin = hit.p, .direction = reflected }; | ||||||
|  |         if (scattered.direction.dot(hit.normal) <= 0) { | ||||||
|  |             return null; | ||||||
|  |         } | ||||||
|  |         return ScatteredRay{ | ||||||
|  |             .ray = scattered, | ||||||
|  |             .color = self.color, | ||||||
|  |         }; | ||||||
|  |     } | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| pub const ScatteredRay = struct { | pub const ScatteredRay = struct { | ||||||
|  | @ -21,35 +49,14 @@ pub const ScatteredRay = struct { | ||||||
|     color: Color, |     color: Color, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | pub const Material = union(MaterialType) { | ||||||
|  |     lambertian: Lambertian, | ||||||
|  |     metal: Metal, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| pub fn scatter(ray: Ray, hit: HitRecord, rng: *Random) ?ScatteredRay { | pub fn scatter(ray: Ray, hit: HitRecord, rng: *Random) ?ScatteredRay { | ||||||
|     const scatteredDirection = switch (hit.material.materialType) { |     return switch (hit.material) { | ||||||
| 
 |         .lambertian => |m| m.scatter(ray, hit, rng), | ||||||
|         .Lambertian => blk: { |         .metal => |m| m.scatter(ray, hit, rng), | ||||||
|             var scatterDirection = hit.normal.add(vec3.random_unit_vector(rng)); |  | ||||||
|             // Catch degenerate scatter direction |  | ||||||
|             if (scatterDirection.nearZero()) { |  | ||||||
|                 scatterDirection = hit.normal; |  | ||||||
|             } |  | ||||||
|             break :blk scatterDirection; |  | ||||||
|         }, |  | ||||||
| 
 |  | ||||||
|         .Metal => blk: { |  | ||||||
|             const reflected = ray.direction.unit().reflect(hit.normal); |  | ||||||
|             const scattered = Ray{ .origin = hit.p, .direction = reflected }; |  | ||||||
|             if (scattered.direction.dot(hit.normal) <= 0) { |  | ||||||
|                 break :blk null; |  | ||||||
|             } |  | ||||||
|             break :blk scattered.direction; |  | ||||||
|         }, |  | ||||||
| 
 |  | ||||||
|     }; |     }; | ||||||
| 
 |  | ||||||
|     if (scatteredDirection) |dir| { |  | ||||||
|         return ScatteredRay{ |  | ||||||
|             .ray = Ray{ .origin = hit.p, .direction = dir}, |  | ||||||
|             .color = hit.material.color, |  | ||||||
|         }; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     return null; |  | ||||||
| } | } | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue