-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathMaterial.php
121 lines (95 loc) · 3.56 KB
/
Material.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
<?php
abstract class Material {
abstract protected function scatter(
Ray $r_in, Hit_record $rec
) ;
abstract protected function get_color_attenuation();
abstract protected function get_scattered();
};
class Lambertian extends Material {
public $albedo;
public $color_attenuation;
public $scattered;
function __construct($color){
$this->albedo = $color;
}
function scatter(Ray $r_in, Hit_record $rec){
$scatter_direction = Vec3::op('+', $rec->normal, random_unit_vector());
// Catch degenerate scatter direction
if (Vec3::near_zero($scatter_direction))
$scatter_direction = $rec->normal;
$this->scattered = new Ray($rec->p, $scatter_direction);
$this->color_attenuation = $this->albedo;
return true;
}
function get_color_attenuation(){
return $this->color_attenuation;
}
function get_scattered(){
return $this->scattered;
}
};
class Metal extends Material {
public $albedo;
public $color_attenuation;
public $scattered;
public $fuzz;
function __construct($color, $fuzz){
$this->albedo = $color;
$this->fuzz = $fuzz;
}
function scatter(Ray $r_in, Hit_record $rec){
$reflected = Vec3::reflect(Vec3::unit_vector($r_in->direction()), $rec->normal);
//scattered = ray(rec.p, reflected + fuzz*random_in_unit_sphere());
$fuzz_r = Vec3::escalar_op('*',random_in_unit_sphere(), $this->fuzz);
$this->scattered = new Ray($rec->p, Vec3::op('+',$reflected,$fuzz_r));
$this->color_attenuation = $this->albedo;
return (Vec3::dot($this->scattered->direction(), $rec->normal) > 0);
}
function get_color_attenuation(){
return $this->color_attenuation;
}
function get_scattered(){
return $this->scattered;
}
};
class Dielectric extends Material {
public $index_of_refraction;
public $color_attenuation;
public $scattered;
function __construct(float $index_of_refraction){
$this->index_of_refraction = $index_of_refraction;
}
function scatter(Ray $r_in, Hit_record $rec){
$this->color_attenuation = [1.0, 1.0, 1.0];
$refraction_ratio = $rec->front_face ? (1.0/$this->index_of_refraction) : $this->index_of_refraction;
$unit_direction = Vec3::unit_vector($r_in->direction());
/*
$refracted = Vec3::refract($unit_direction, $rec->normal, $refraction_ratio);
$this->scattered = new Ray($rec->p, $refracted);
return true;
*/
$cos_theta = min(Vec3::dot(Vec3::negative($unit_direction), $rec->normal), 1.0);
$sin_theta = sqrt(1.0 - $cos_theta*$cos_theta);
$cannot_refract = $refraction_ratio * $sin_theta > 1.0;
//if ($cannot_refract)
if ($cannot_refract || $this->reflectance($cos_theta, $refraction_ratio) > random_double())
$direction = Vec3::reflect($unit_direction, $rec->normal);
else
$direction = Vec3::refract($unit_direction, $rec->normal, $refraction_ratio);
$this->scattered = new Ray($rec->p, $direction);
return true;
}
private function reflectance($cosine, $ref_idx) {
// Use Schlick's approximation for reflectance.
$r0 = (1-$ref_idx) / (1+$ref_idx);
$r0 = $r0*$r0;
return $r0 + (1-$r0)*pow((1 - $cosine),5);
}
function get_color_attenuation(){
return $this->color_attenuation;
}
function get_scattered(){
return $this->scattered;
}
};