func (d *Sphere) ValidSample(sg *core.ShaderContext, sample *core.BSDFSample) bool {
	t, ok := raySphereIntersect(sg.P, sample.D, d.P, d.Radius)
	if !ok {
		return false
	}
	x := m.Vec3Mad(sg.P, sample.D, t)
	D := m.Vec3Sub(x, sg.P)
	sample.Ldist = m.Vec3Length(D)
	sample.Ld = m.Vec3Normalize(D)
	sample.Liu.Lambda = sg.Lambda
	lsg := sg.NewShaderContext()
	lsg.Lambda = sg.Lambda
	N := m.Vec3Normalize(m.Vec3Sub(x, d.P))
	lsg.N = N
	lsg.Ng = N
	lsg.P = x
	lsg.U = 0.5 + m.Atan2(N[2], N[0])/(2*m.Pi)
	lsg.V = 0.5 - m.Asin(N[1])/m.Pi
	lsg.Shader = d.shader
	E := d.shader.EvalEmission(lsg, m.Vec3Neg(sample.D))
	sg.ReleaseShaderContext(lsg)
	sample.Liu.FromRGB(E)
	V := m.Vec3Sub(d.P, sg.P)
	l := m.Vec3Length(V)
	sample.PdfLight = 1 / (2 * m.Pi * (1 - m.Sqrt(1-sqr(d.Radius/l))))  
	if false {
		fmt.Printf("weight(b): %v (%v / %v) %v %v %v %v\n", sample.PdfLight, d.Radius, l, d.Radius/l, sqr(d.Radius/l), 1-sqr(d.Radius/l), m.Sqrt(1-sqr(d.Radius/l)))
	}
	return true
}
ValidSample implements core.Light.
package light
import (
	"fmt"
	"github.com/jamiec7919/vermeer/builtin/geom/sphere"
	"github.com/jamiec7919/vermeer/core"
	m "github.com/jamiec7919/vermeer/math"
	"github.com/jamiec7919/vermeer/math/ldseq"
	"github.com/jamiec7919/vermeer/nodes"
)
type Sphere struct {
	NodeDef  core.NodeDef `node:"-"`
	NodeName string       `node:"Name"`
	P        m.Vec3
	Radius   float32
	Shader   string
	Samples int `node:",opt"`
	shader core.Shader
	geom   core.Geom
}
var _ core.Node = (*Sphere)(nil)
var _ core.Light = (*Sphere)(nil)
func (d *Sphere) Name() string { return d.NodeName }
func (d *Sphere) Def() core.NodeDef { return d.NodeDef }
func (d *Sphere) PreRender() error {
	if s := core.FindNode(d.Shader); s != nil {
		shader, ok := s.(core.Shader)
		if !ok {
			return fmt.Errorf("Unable to find shader %v", d.Shader)
		}
		d.shader = shader
		geom := &sphere.Sphere{P: d.P, Radius: d.Radius, Shader: d.Shader}
		core.AddNode(geom)
		d.geom = geom
	} else {
		return fmt.Errorf("Unable to find node (shader %v)", d.Shader)
	}
	return nil
}
func (d *Sphere) PostRender() error { return nil }
func (d *Sphere) Geom() core.Geom { return d.geom }
func solveQuadratic(a, b, c float32, x0, x1 *float32) bool {
	discr := b*b - 4*a*c
	if discr < 0 {
		return false
	} else if discr == 0 {
		*x1 = -0.5 * b / a
		*x0 = *x1
	} else {
		var q float32
		if b > 0 {
			q = -0.5 * (b + m.Sqrt(discr))
		} else {
			q = -0.5 * (b - m.Sqrt(discr))
		}
		*x0 = q / a
		*x1 = c / q
	}
	if *x0 > *x1 {
		*x0, *x1 = *x1, *x0
	}
	return true
}
func raySphereIntersect(Ro, Rd, P m.Vec3, radius float32) (float32, bool) {
	L := m.Vec3Sub(Ro, P)
	a := m.Vec3Dot(Rd, Rd)
	b := 2 * m.Vec3Dot(Rd, L)
	c := m.Vec3Dot(L, L) - radius*radius
	var t0, t1 float32
	if !solveQuadratic(a, b, c, &t0, &t1) {
		return 0, false
	}
	if t0 > t1 {
		t0, t1 = t1, t0
	}
	if t0 < 0 {
		t0 = t1  
		if t0 < 0 {
			return 0, false
		}  
	}
	return t0, true
}
func sqr(x float32) float32 { return x * x }