Example #1
0
  /**
   * Ported from paper "Reflections and Refractions in Ray Tracing" by Bram de Greve (2006)
   *
   * @param incident
   * @param normal
   * @param n1
   * @param n2
   * @return
   */
  private Refraction getRefraction(Vector incident, Vector normal, float n1, float n2) {
    float n = n1 / n2;
    float cosI = -normal.dot(incident);
    float sinT2 = n * n * (1.0f - cosI * cosI);

    if (sinT2 > 1.0) { // TIR
      return null;
    }

    float cosT = (float) Math.sqrt(1.0f - sinT2);

    Refraction res = new Refraction();
    res.direction = incident.mult(n).add(normal.mult(n * cosI - cosT));

    // Schlick approximation
    float r0 = (n1 - n2) / (n1 + n2);
    r0 *= r0;

    float cosX = cosI;
    if (n1 > n2) {
      cosX = cosT;
    }
    float x = 1.0f - cosX;

    res.reflectionAbility = r0 + (1.0f - r0) * x * x * x * x * x;
    res.transmissionAbility = 1.0f - res.reflectionAbility;

    return res;
  }
Example #2
0
  public Color trace(Scene scene) {
    // find first intersection point with scene objects
    Hit firstHit = scene.intersect(this);
    // calculate light intensity/color at hit point
    if (firstHit == null) {
      return new Color(0, 0, 0);
    }

    Material material = firstHit.getShape().getMaterial();

    Color result = new Color(0, 0, 0);

    result = result.add(material.computeAmbient(scene.getAmbientLight()));

    for (LightSource light : scene.getLightSources()) {
      Vector direction = light.getPosition().sub(firstHit.getIntersectionPoint()).normalize();
      Vector offset = direction.mult(OFFSET);

      Ray shadowRay =
          new Ray(direction, firstHit.getIntersectionPoint().add(offset), recursionDepth);

      Hit intersection = scene.intersect(shadowRay);

      if (intersection == null) {
        result = result.add(material.computeDiffuseLight(firstHit, light));
        result = result.add(material.computeSpecularLight(firstHit, light));
      }
    }

    if (recursionDepth > 0) {
      float n1 = material.getRefractionMediumOutside();
      float n2 = material.getRefractionMediumInside();

      float reflectionAbility = 1;

      if (n1 > 0 && n2 > 0) {
        Refraction refractionIn = getRefraction(direction, firstHit.getNormal(), n1, n2);

        if (refractionIn != null) {
          reflectionAbility = refractionIn.reflectionAbility;
          Vector offset = refractionIn.direction.mult(OFFSET);
          Ray refractionRay =
              new Ray(
                  refractionIn.direction,
                  firstHit.getIntersectionPoint().add(offset),
                  recursionDepth);

          Hit outHit = scene.intersect(refractionRay);

          Refraction refractionOut =
              getRefraction(refractionRay.direction, outHit.getNormal().mult(-1), n2, n1);

          if (refractionOut != null) {
            Ray outRay =
                new Ray(
                    refractionOut.direction,
                    outHit.getIntersectionPoint().add(refractionOut.direction.mult(OFFSET)),
                    recursionDepth - 1);

            result = result.add(outRay.trace(scene).modulate(refractionIn.transmissionAbility));
          }
        }
      }

      if (material.getReflectionCo() > 0) {
        Vector direction = getReflection(this.direction, firstHit.getNormal());
        Vector offset = direction.mult(OFFSET);

        Ray reflectionRay =
            new Ray(direction, firstHit.getIntersectionPoint().add(offset), recursionDepth - 1);

        result =
            result.add(
                reflectionRay
                    .trace(scene)
                    .modulate(material.getReflectionCo() * reflectionAbility));
      }
    }

    return result;
  }
Example #3
0
 public Vector getPoint(float t) {
   return origin.add(direction.mult(t));
 }
Example #4
0
 /**
  * @param direction
  * @param origin
  * @param recursionDepth
  */
 public Ray(Vector direction, Vector origin, int recursionDepth) {
   this.direction = direction.normalize();
   this.origin = origin;
   this.recursionDepth = recursionDepth;
 }
Example #5
0
  private Vector getReflection(Vector direction, Vector normal) {
    Vector rayDirection = direction.normalize().mult(-1);

    return normal.mult(normal.dot(rayDirection) * 2).sub(rayDirection);
  }