So far, I create two spheres.
Sphere 1 is at (0, 0, 5), radius = 1
Sphere 2 is at (0, 10, 50), radius = 20
Camera is at (0, 0, -1)
This is the Sphere class [only the hit function is interesting]
class Sphere : Surface
{
Material material;
Vector3 center;
float radius;
this()
{
}
this(const ref Vector3 _center, float _radius)
{
center = _center;
radius = _radius;
}
bool hit(const Ray r, float p0, float p1, ref HitInfo hitInfo) const
{
Vector3 d = r.d, e = r.e, c = center;
float discriminant = dot(d, e-c) * dot(d, e-c) - dot(d, d) * (dot(e-c, e-c) - radius * radius);
if( discriminant >= 0 )
{
//float t1 = (dot(-d, e-c) + sqrt(discriminant)) / dot(d, d);
float t2 = (dot(-d, e-c) - sqrt(discriminant)) / dot(d, d);
// TODO: don't forget to change this if needed
if( t2 < p0 || t2 > p1 )
return false;
hitInfo.t = t2;
hitInfo.hitPoint = e + d * t2;
hitInfo.ray = d;
hitInfo.surfaceNormal = (hitInfo.hitPoint - c) * 2; // is this correct?
}
return discriminant >= 0; // TODO: implement
}
Box boundingBox() const
{
Vector3 min = {center.x - radius * 0.5f, center.y - radius * 0.5f, center.z - radius * 0.5f};
Vector3 max = {center.x + radius * 0.5f, center.y + radius * 0.5f, center.z + radius * 0.5f};
Box b = {min, max};
return b;
}
Vector3 shade(HitInfo hitInfo) const
{
return material.shade(hitInfo);
}
}
So, Spheres need to have a Material, that decides how they are going to be drawn.In the simplest case, my material can be:
class SimpleColor : Material
{
private Vector3 color;
this(ubyte r, ubyte g, ubyte b)
{
color.x = r / 255.0f;
color.y = g / 255.0f;
color.z = b / 255.0f;
}
Vector3 shade(HitInfo hitInfo) const
{
return color;
}
}
So, I chose red and green colours. Everything looks fine.[img=http://[url%3Dhttp://i50.tinypic.com/35b7b49.png]http://i50.tinypic.com/35b7b49.png[/url]]
The next step was to make the shade function a bit more complicated:
Vector3 shade(HitInfo hitInfo) const
{
Vector3 l = {0, 1, 0}; // let's say that the light is at this position. (It's hardcoded for now - just for the test)
Vector3 lightVector = l - hitInfo.hitPoint; // vector from the hit point to the light
// TODO: fix
if( hitInfo.surfaceNormal.dot(lightVector) <= 0 )
{
return color * 0;
}
else
{
return color * hitInfo.surfaceNormal.dot(lightVector);
}
}
So I just return the colour multipled by the dot product of the surface normal and the light direction vector. What I get is this:[img=http://[url%3Dhttp://i45.tinypic.com/29zeek1.png]http://i45.tinypic.com/29zeek1.png[/url]]
Are all those normals negative? Or am I doing something wrong? (I bet I am )