Esempio n. 1
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;
  }