RayMarchingGo/sdf.go
2025-09-24 05:07:48 +02:00

67 lines
1.4 KiB
Go

package main
const EPS = 0.001
type SDF interface {
Distance(Vector3) float64
}
func Gradient(sdf SDF, p Vector3, eps float64) Vector3 {
dx := (sdf.Distance(p.Add(Vector3{X: eps})) - sdf.Distance(p.Add(Vector3{X: -eps}))) / (2 * eps)
dy := (sdf.Distance(p.Add(Vector3{Y: eps})) - sdf.Distance(p.Add(Vector3{Y: -eps}))) / (2 * eps)
dz := (sdf.Distance(p.Add(Vector3{Z: eps})) - sdf.Distance(p.Add(Vector3{Z: -eps}))) / (2 * eps)
return Vector3{X: dx, Y: dy, Z: dz}
}
// Some transformations see https://iquilezles.org/articles/distfunctions/
type translatedSDF struct {
primitive SDF
translate Vector3
}
func (s translatedSDF) Distance(p Vector3) float64 {
return s.primitive.Distance(p.Sub(s.translate))
}
type rotatedSDF struct {
primitive SDF
rotVector Vector3
angle float64
}
func (s rotatedSDF) Distance(p Vector3) float64 {
rotated_p := rotate(p, s.rotVector, s.angle)
return s.primitive.Distance(rotated_p)
}
type scaledSDF struct {
primitive SDF
scale float64
}
func (s scaledSDF) Distance(p Vector3) float64 {
return s.primitive.Distance(p.Scale(1/s.scale)) * s.scale
}
type infiniteRep struct {
primitive SDF
cellSize Vector3
}
// TODO
// func (s infiniteRep) Distance(p Vector3) float64 {
// x, y, z := p.Unpack()
// sx, sy, sz := s.cellSize.Unpack()
// }
// Sphere
type Sphere struct {
center Vector3
radius float64
}
func (s Sphere) Distance(p Vector3) float64 {
return p.Sub(s.center).Length()
}