81 lines
2.2 KiB
Go
81 lines
2.2 KiB
Go
package main
|
|
|
|
// RIGHT : x
|
|
// FORWARD : Y
|
|
// UP : Z
|
|
|
|
import (
|
|
"math"
|
|
)
|
|
|
|
func phongShading(point Vector3, normal Vector3, mat Material) Vector3 {
|
|
lightVec := (lightPos.Sub(point)).Normalized()
|
|
reflectLight := Reflect(lightVec, normal)
|
|
eyeVec := (cameraPos.Sub(point)).Normalized()
|
|
brutMat := mat.GetMaterialBrut()
|
|
ambiant := brutMat.ambiantColor.GetColor(point)
|
|
|
|
diffusePower := brutMat.diffuseFac * max(0, normal.Dot(lightVec))
|
|
diffuse := brutMat.diffuseColor.GetColor(point).Scale(diffusePower)
|
|
|
|
specularPower := brutMat.specularFac * math.Pow(max(0, reflectLight.Dot(eyeVec)), brutMat.specularExp)
|
|
specular := brutMat.specularColor.GetColor(point).Scale(specularPower)
|
|
|
|
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
|
|
}
|
|
if dist > MAX_DIST {
|
|
break
|
|
}
|
|
res = min(res, SOFT_SHADOW_COEFF*dist/dist_total)
|
|
dist_total += dist
|
|
p.Radd(direction.Scale(dist))
|
|
}
|
|
return res
|
|
}
|
|
|
|
func reflect(point Vector3, direction Vector3, normal Vector3, mat Material, reflectNumber int) Vector3 {
|
|
brutMat := mat.GetMaterialBrut()
|
|
if reflectNumber <= 0 || brutMat.reflectanceFac < EPS {
|
|
return Vector3{0, 0, 0}
|
|
}
|
|
reflected := Reflect(direction, normal).Scale(-1)
|
|
reflectRayOrigin := point.Add(reflected.Scale(5 * EPS))
|
|
hit, color := rayMarch(reflectRayOrigin, reflected, reflectNumber-1)
|
|
if !hit {
|
|
color = Vector3{0, 0, 0}
|
|
}
|
|
// fmt.Println("Reflect")
|
|
return color.Scale(brutMat.reflectanceFac)
|
|
}
|
|
|
|
func rayMarch(origin Vector3, direction Vector3, reflectNumber int) (bool, Vector3) {
|
|
p := origin
|
|
for range MAX_STEP {
|
|
dist := scene.Distance(p)
|
|
if dist < EPS {
|
|
mat := scene.GetMaterial(p)
|
|
normal := Gradient(scene, p, EPS).Normalized()
|
|
phongShade := phongShading(p, normal, mat)
|
|
shadowCoeff := max(shadow(p), 0.3)
|
|
reflectColor := reflect(p, direction, normal, mat, reflectNumber)
|
|
return true, phongShade.Add(reflectColor).Scale(shadowCoeff)
|
|
// return true, phongShading(p, normal, *mat)
|
|
}
|
|
if dist > MAX_DIST {
|
|
break
|
|
}
|
|
p.Radd(direction.Scale(dist))
|
|
}
|
|
return false, GREY
|
|
}
|