Chapter 12 done

This commit is contained in:
Luxdragon 2024-03-06 13:08:24 +01:00
parent 6de86045ba
commit 1f8d6adae3
2 changed files with 89451 additions and 89430 deletions

178814
image.ppm

File diff suppressed because it is too large Load diff

67
main.go
View file

@ -120,7 +120,7 @@ func q_rsqrt(v Vec3) float32 {
func Unit_vector(v Vec3) Vec3 {
//new_v := v.Mult(q_rsqrt(v))
new_v := v.Mult(1.0/float32(math.Sqrt(float64(v.Length_squared()))))
new_v := v.Mult(1.0/v.Length())
return new_v
}
@ -151,17 +151,17 @@ func Reflect(v Vec3, n Vec3) Vec3 {
return v.Sub(n.Mult(2*Dot(v,n)))
}
func Refract(uv Vec3, n Vec3, etai_over_etat float32) Vec3 {
cos_theta := float32(math.Min(float64(Dot(uv.Neg(), n)), 1.0))
var r_out_perp Vec3 = (uv.Add(n.Mult(cos_theta))).Mult(etai_over_etat)
var r_out_parallel Vec3 = n.Mult(float32(-math.Sqrt(math.Abs(float64(1.0 - r_out_perp.Length_squared())))))
return r_out_perp.Add(r_out_parallel)
func Refract(uv, n Vec3, etai_over_etat float32) Vec3 {
cos_theta := float32(math.Min(float64(Dot(uv.Neg(), n)), 1.0))
r_out_perp := uv.Add(n.Mult(cos_theta)).Mult(etai_over_etat)
r_out_parallel := n.Mult(-float32(math.Sqrt(math.Abs(1.0 - float64(r_out_perp.Length_squared())))))
return r_out_perp.Add(r_out_parallel)
}
const pi float32 = 3.1415926535897932385
func Degrees_to_radians(degrees float32) float32 {
return (degrees * pi) / 180.0
func Degrees_to_radians(degrees float32) float64 {
return float64((degrees * pi) / 180.0)
}
func Linear_to_gamma(linear_component float32) float32 {
@ -400,7 +400,7 @@ func Reflectance(cosine float32, ref_idx float32) float32 {
// Use Schlick's approximation for reflectance
r0 := (1.0-ref_idx) / (1.0+ref_idx)
r0 = r0*r0
return r0 + (1.0-r0)*float32(math.Pow(float64(1 - cosine), 5))
return r0 + (1.0-r0)*float32(math.Pow(1.0 - float64(cosine), 5))
}
func (mat Material) Scatter(r_in *Ray, rec *Hit_record, attenuation *Vec3, scattered *Ray) bool {
@ -424,7 +424,7 @@ func (mat Material) Scatter(r_in *Ray, rec *Hit_record, attenuation *Vec3, scatt
*attenuation = NewColor(1.0, 1.0, 1.0)
var refraction_ration float32
if rec.front_face {
refraction_ration = 1/mat.ir
refraction_ration = 1.0/mat.ir
} else {
refraction_ration = mat.ir
}
@ -462,6 +462,13 @@ type Camera struct {
pixel_delta_v Vec3
samples_per_pixel int
max_depth int
vfov float32
lookfrom Vec3
lookat Vec3
vup Vec3
u Vec3
v Vec3
w Vec3
}
func NewCamera() *Camera {
@ -493,22 +500,31 @@ func (cam *Camera) Initialize() {
if cam.image_height < 1 {
cam.image_height = 1
}
cam.center = cam.lookfrom
// Viewport
var focal_length float32 = 1.0
var viewport_height float32 = 2.0
var focal_length float32 = (cam.lookfrom.Sub(cam.lookat)).Length()
theta := Degrees_to_radians(cam.vfov)
h := float32(math.Tan(theta/2.0))
var viewport_height float32 = 2.0 * h * focal_length
var viewport_width float32 = viewport_height * float32(cam.image_width)/float32(cam.image_height)
cam.center = NewVec3(0,0,0)
// Calculate the u,v,w unit basis vectors for the camera coordinate frame
cam.w = Unit_vector(cam.lookfrom.Sub(cam.lookat))
cam.u = Unit_vector(Cross(cam.vup, cam.w))
cam.v = Cross(cam.w, cam.u)
// Calculate the vectors across the horizontal and down the vertical viewport edges
viewport_u := NewVec3(viewport_width, 0, 0)
viewport_v := NewVec3(0, -viewport_height, 0)
viewport_u := cam.u.Mult(viewport_width)
viewport_v := cam.v.Mult(-viewport_height)
//Calculate the horizontal and vertical delta vectors from pixel to pixel
cam.pixel_delta_u = viewport_u.Div(float32(cam.image_width))
cam.pixel_delta_v = viewport_v.Div(float32(cam.image_height))
// Calculate the location of the upper left pixel
viewport_upper_left := cam.center.Sub(cam.center).Sub(NewVec3(0, 0, focal_length)).Sub(viewport_u.Div(2)).Sub(viewport_v.Div(2))
viewport_upper_left := cam.center.Sub(cam.w.Mult(focal_length)).Sub(viewport_u.Div(2)).Sub(viewport_v.Div(2))
cam.pixel00_loc = viewport_upper_left.Add((cam.pixel_delta_u.Add(cam.pixel_delta_v)).Div(2))
}
@ -551,32 +567,33 @@ func (cam *Camera) Pixel_sample_square() Vec3 {
// =============== MAIN =====================
func main() {
// Materials
material_ground := NewMaterial(0, NewColor(0.8, 0.8, 0.0), 0.0, 0.0)
material_center := NewMaterial(0, NewColor(0.1, 0.2, 0.5), 0.0, 1.5)
material_left := NewMaterial(2, NewColor(0.8, 0.8, 0.8), 0.3, 1.5)
material_center := NewMaterial(0, NewColor(0.1, 0.2, 0.5), 0.0, 0.0)
material_left := NewMaterial(2, NewColor(1.0, 1.0, 1.0), 0.0, 1.5)
material_right := NewMaterial(1, NewColor(0.8, 0.6, 0.2), 0.0, 0.0)
// World
world := NewHittable()
world.Add(Sphere{
center: NewVec3(0, -100.5, -1),
radius: 100,
center: NewVec3(0.0, -100.5, -1.0),
radius: 100.0,
mat: material_ground,
})
world.Add(Sphere{
center: NewVec3(0, 0, -1.0),
center: NewVec3(0, 0, -1),
radius: 0.5,
mat: material_center,
})
world.Add(Sphere{
center: NewVec3(-1.0, 0, -1.0),
center: NewVec3(-1, 0, -1),
radius: 0.5,
mat: material_left,
})
world.Add(Sphere{
center: NewVec3(-1.0, 0, -1.0),
center: NewVec3(-1, 0, -1),
radius: -0.4,
mat: material_left,
})
@ -592,6 +609,10 @@ func main() {
cam.image_width = 400
cam.samples_per_pixel = 100
cam.max_depth = 50
cam.vfov = 20
cam.lookfrom = NewVec3(-2,2,1)
cam.lookat = NewVec3(0,0,-1)
cam.vup = NewVec3(0,1,0)
cam.Render(world)
// INFO: The pixels are written out in rows.
// Image file can be created with