Ejemplo n.º 1
0
bool BoundingBox::RayIntersects(const Ray& ray, float tMin, float tMax) const
{
    Vector3f dirFrac = ray.GetDir().Reciprocal();

    Vector3f minD = (Min - ray.GetPos()) * dirFrac,
             maxD = (Max - ray.GetPos()) * dirFrac;

    float _tMin = max(max(min(minD.x, maxD.x), min(minD.y, maxD.y)), min(minD.z, maxD.z)),
          _tMax = min(min(max(minD.x, maxD.x), max(minD.y, maxD.y)), max(minD.z, maxD.z));
    return (_tMin >= tMin && _tMin <= tMax) ||
           (_tMax >= tMin && _tMax <= tMax);
}
Ejemplo n.º 2
0
bool Material_Dielectric::Scatter(const Ray& rIn, const Vertex& surface,
                                  const Shape& shpe, FastRand& prng,
                                  Vector3f& attenuation, Vector3f& emission,
                                  Ray& rOut) const
{
    float indexOfRefraction = (float)IndexOfRefraction->GetValue(rIn, prng, &shpe, &surface);

    float ratioOfIndices;
    Vector3f outwardNormal;
    float cosAngle;
    if (surface.Normal.Dot(rIn.GetDir()) > 0.0f)
    {
        ratioOfIndices = indexOfRefraction;
        outwardNormal = -surface.Normal;
        cosAngle = indexOfRefraction * rIn.GetDir().Dot(surface.Normal) / rIn.GetDir().Length();
    }
    else
    {
        ratioOfIndices = 1.0f / indexOfRefraction;
        outwardNormal = surface.Normal;
        cosAngle = -rIn.GetDir().Dot(surface.Normal) / rIn.GetDir().Length();
    }

    //Try refracting. Possibly reflect instead.
    float reflectionChance;
    Vector3f refracted;
    if (rIn.GetDir().Refract(outwardNormal, ratioOfIndices, refracted))
    {
        //Approximation of chance of refraction by Christophe Schlick:
        float r0 = (1.0f - indexOfRefraction) / (1.0f + indexOfRefraction);
        r0 *= r0;
        reflectionChance = r0 + ((1.0f - r0) * std::powf((1.0f - cosAngle), 5.0f));
    }
    else
    {
        reflectionChance = 1.01f;
    }

    if (prng.NextFloat() < reflectionChance)
        rOut = Ray(surface.Pos, rIn.GetDir().Reflect(surface.Normal));
    else
        rOut = Ray(surface.Pos, refracted);

    //Move the ray forward a tiny bit to get off the surface.
    rOut.SetPos(rOut.GetPos() + (rOut.GetDir() * PushoffDist));

    attenuation = Vector3f(1.0f, 1.0f, 1.0f);
    return true;
}
Ejemplo n.º 3
0
bool Mesh::CastRay(const Ray& ray, Vertex& outHit, FastRand& prng,
                   float tMin, float tMax) const
{
    //TODO: Try not bothering to normalize the local ray's direction.
    Ray newRay(Tr.Point_WorldToLocal(ray.GetPos()),
               Tr.Dir_WorldToLocal(ray.GetDir()).Normalize());

    if (!bounds.RayIntersects(newRay, tMin, tMax))
        return false;

    const Triangle* closest = nullptr;
    float hitDist = std::numeric_limits<float>().infinity();
    for (size_t i = 0; i < Tris.GetSize(); ++i)
    {
        float tempT;
        Vector3f tempPos;

        if (Tris[i].RayIntersect(newRay, tempPos, tempT, tMin, tMax))
        {
            if (tempT < hitDist)
            {
                hitDist = tempT;
                outHit.Pos = tempPos;
                closest = &Tris[i];
            }
        }
    }

    if (closest != nullptr)
    {
        closest->GetMoreData(outHit, Tr);
        return true;
    }

    return false;
}