/** * * * @param RayTracer_Color $c1 * @param RayTracer_Color $c2 * @param float $w * @return unknown */ public static function blend(RayTracer_Color $c1, RayTracer_Color $c2, $w) { $result = RayTracer_Color::add(RayTracer_Color::multiplyScalar($c1, 1 - $w), RayTracer_Color::multiplyScalar($c2, $w)); return $result; }
public function rayTrace(RayTracer_IntersectionInfo $info, RayTracer_Ray $ray, RayTracer_Scene $scene, $depth) { // Calc ambient $color = RayTracer_Color::multiplyScalar($info->color, $scene->background->ambience); $shininess = pow(10, $info->shape->material->gloss + 1); foreach ($scene->lights as $light) { // Calc diffuse lighting $v = RayTracer_Vector::subtract($light->position, $info->position)->normalize(); if ($this->options['renderDiffuse']) { $L = $v->dot($info->normal); if ($L > 0.0) { $color = RayTracer_Color::add($color, RayTracer_Color::multiply($info->color, RayTracer_Color::multiplyScalar($light->color, $L))); } } // The greater the depth the more accurate the colours, but // this is exponentially (!) expensive if ($depth <= $this->options['rayDepth']) { // calculate reflection ray if ($this->options['renderReflections'] && $info->shape->material->reflection > 0) { $reflectionRay = $this->getReflectionRay($info->position, $info->normal, $ray->direction); $refl = $this->testIntersection($reflectionRay, $scene, $info->shape); if ($refl->isHit && $refl->distance > 0) { $refl->color = $this->rayTrace($refl, $reflectionRay, $scene, $depth + 1); } else { $refl->color = $scene->background->color; } $color = RayTracer_Color::blend($color, $refl->color, $info->shape->material->reflection); } // Refraction /* TODO */ } /* Render shadows and highlights */ $shadowInfo = new RayTracer_IntersectionInfo(); if ($this->options['renderShadows']) { $shadowRay = new RayTracer_Ray($info->position, $v); $shadowInfo = $this->testIntersection($shadowRay, $scene, $info->shape); if ($shadowInfo->isHit && $shadowInfo->shape != $info->shape) { $vA = RayTracer_Color::multiplyScalar($color, 0.5); $dB = 0.5 * pow($shadowInfo->shape->material->transparency, 0.5); $color = RayTracer_Color::addScalar($vA, $dB); } } // Phong specular highlights if ($this->options['renderHighlights'] && !$shadowInfo->isHit && $info->shape->material->gloss > 0) { $Lv = RayTracer_Vector::subtract($info->shape->position, $light->position)->normalize(); $E = RayTracer_Vector::subtract($scene->camera->position, $info->shape->position)->normalize(); $H = RayTracer_Vector::subtract($E, $Lv)->normalize(); $glossWeight = pow(max($info->normal->dot($H), 0), $shininess); $color = RayTracer_Color::add(RayTracer_Color::multiplyScalar($light->color, $glossWeight), $color); } } $color->limit(); return $color; }