diff --git a/src/ray_marching.go b/src/ray_marching.go index 8e7806b..08e268c 100644 --- a/src/ray_marching.go +++ b/src/ray_marching.go @@ -17,8 +17,10 @@ const WIDTH = 500 const HEIGHT = 500 const PI = math.Pi +const SOFT_SHADOW_COEFF = 4 + var lightPos Vector3 -var scene SmoothUnionSDF +var scene SDF // radius, theta, phi var screenSpherical Vector3 @@ -28,16 +30,17 @@ var cameraPos Vector3 func init() { lightPos = Vector3{0, -200, 800} - cameraPos = Vector3{0, -10, 30} + cameraPos = Vector3{0, -10, 25} screenSpherical = Vector3{10, PI/2 + 0.2, PI / 2} screenPhysicalSize = 5 sphereMat := RED_MAT sphereMat.specularFac = 0.5 - sphere := TranslatedSDF{Sphere{10, sphereMat}, Vector3{0, 100, 5}} + sphere := TranslatedSDF{Sphere{10, sphereMat}, Vector3{0, 100, 15}} + // sphere := RepeatSDF{Sphere{20, sphereMat}, Vector3{50, 50, 50}} plane := Plane{Vector3{0, 0, 1}, WHITE_GREY_GRID_MAT} - scene = SmoothUnionSDF{sphere, plane, 2} + scene = UnionSDF{sphere, plane} } @@ -56,13 +59,33 @@ func phongShading(point Vector3, normal Vector3, mat Material) Vector3 { return ambiant.Add(diffuse).Add(specular) } +func shadow(point Vector3) float64 { + direction := (lightPos.Sub(point)).Normalized() + p := point.Add(direction.Scale(5 * EPS)) + res := 1.0 + dist_total := 0.0 + for range MAX_STEP { + dist, _ := scene.Distance(p) + if dist < EPS { + return 0.1 + } + if dist > MAX_DIST { + break + } + res = min(res, SOFT_SHADOW_COEFF*dist/dist_total) + dist_total += dist + p = p.Add(direction.Scale(dist)) + } + return res +} + func rayMarch(origin Vector3, direction Vector3) (bool, Vector3) { p := origin for range MAX_STEP { dist, mat := scene.Distance(p) if dist < EPS { normal := Gradient(scene, p, EPS).Normalized() - return true, phongShading(p, normal, mat) + return true, phongShading(p, normal, mat).Scale(shadow(p)) } if dist > MAX_DIST { break