我现在正在golang写一个路径追踪器,我有漫反射和镜面反射的材料。然而,我的透明材料看起来很怪异和环绕。
这是相关代码:
积分仪:
func render(scene *Scene, cam *Camera, img *image.RGBA) {
random := rand.New(rand.NewSource(1))
for y := Height - 1; y >= 0; y-- {
for x := 0; x < Width; x++ {
col := RGB{0.0, 0.0, 0.0}
for i := 0; i < SPP; i++ {
u := (float64(x) + random.Float64()) / float64(Width)
v := (float64(y) + random.Float64()) / float64(Height)
r := cam.RayAt(u, v, random)
c := getColor(r, scene, 0, random)
col.R += c.R
col.G += c.G
col.B += c.B
}
col.R *= 255.0 / SPP
col.G *= 255.0 / SPP
col.B *= 255.0 / SPP
img.Set(x, y, color.RGBA{uint8(col.R), uint8(col.G), uint8(col.B), uint8(255)})
}
}
}
func getColor(r Ray, scene *Scene, depth int, rnd *rand.Rand) RGB {
if depth > MaxDepth {
return background(r)
}
b, hit := scene.Hit(r, tMin, tMax)
if b {
bounced, bouncedRay := hit.Bounce(r, rnd.Float64(), rnd.Float64(), hit, rnd)
if bounced {
bounceColor := getColor(bouncedRay, scene, depth+1, rnd)
return hit.Material.Color().Multiply(bounceColor)
}
return hit.Material.Color()
}
return background(r)
}
材料:
type Material struct {
Col RGB
Index float64 // refractive index
Reflectivity float64
Transparency float64 // the amount of light to let through
Gloss float64 // reflection cone angle in radians
}
func (m *Material) Color() RGB {
return m.Col
}
func (m *Material) Bounce(r Ray, fu, fv float64, hit Hit, rnd *rand.Rand) (bool, Ray) {
var direction Vector
if m.Reflectivity > 0 && rnd.Float64() < m.Reflectivity {
// we should reflect
reflectDirection := r.Direction.Reflect(hit.Normal)
direction = Cone(reflectDirection, m.Gloss, fu, fv, rnd)
} else if m.Transparency > 0 && rnd.Float64() < m.Transparency {
// we should refract
_, direction = r.Direction.Refract(hit.Normal, m.Index)
} else {
direction = hit.Normal.Add(VectorInUnitSphere(rnd))
}
return true, Ray{hit.Point, direction}
}
载体:
func (v Vector) Refract(ov Vector, n float64) (bool, Vector) {
uv := v.Normalize()
uo := ov.Normalize()
dt := uv.Dot(uo)
discriminant := 1.0 - (n * n * (1 - dt*dt))
if discriminant > 0 {
a := uv.Subtract(ov.MultiplyScalar(dt)).MultiplyScalar(n)
b := ov.MultiplyScalar(math.Sqrt(discriminant))
return true, a.Subtract(b)
}
return false, Vector{}
}