Beispiel #1
0
Color raytrace( Scene scene, Ray ray )
{
   Color color;
   color.r = 0;
   color.b = 0;
   color.g = 0;

   Intersection best;
   best.hit = false;

   float bestT = 10000;
   float t;
   for( int j = 0; j < scene.numSpheres; j++ )
   {
      t = sphereHitTest( scene.spheres[j], ray );
      if( t > 0 )
      {
         if( !best.hit || t < bestT )
         {
            best = sphereIntersection( scene.spheres[j], ray, t );
            bestT = t;
         }
      }
   }
   for( int j = 0; j < scene.numTriangles; j++ )
   {
      t = triangleHitTest( scene.triangles[j], ray );
      if( t > 0 )
      {
         if( !best.hit || t < bestT )
         {
            best = triangleIntersection( scene.triangles[j], ray, t );
            bestT = t;
         }
      }
   }
   for( int j = 0; j < scene.numPlanes; j++ )
   {
      t = planeHitTest( scene.planes[j], ray );
      if( t > 0 )
      {
         if( !best.hit || t < bestT )
         {
            best = planeIntersection( scene.planes[j], ray, t );
            bestT = t;
         }
      }
   }
   if( best.hit )
   {
      color = plus( color, directIllumination( best, scene ) );
      //printf("color: %f, %f, %f\n", color.r, color.g, color.b);
   }
   return limitColor( color );
}
Color3 PhotonIntegrator::raytracing(const Ray& ray , int dep)
{
    Color3 res = Color3(0.0 , 0.0 , 0.0);

    if (dep > 2)
        return res;

    Geometry *g = NULL;
	Intersection inter;
    Ray reflectRay , transRay;

    g = scene.intersect(ray , inter);

    if (g == NULL)
        return res;

	if (inter.matId < 0)
	{
		AbstractLight *l = scene.lights[-inter.matId - 1];
		return l->getIntensity() * 100.f;
	}
    
    res = res + directIllumination(scene , inter , rng , -ray.dir);
      
    res = res + estimate(indirectMap , nIndirectPaths , knnPhotons , scene , inter , -ray.dir , maxSqrDis);

	// final gathering is too slow!

    //res = res + finalGathering(indirectMap , scene , inter , rng , -ray.dir , 50 , knnPhotons , maxSqrDis);
    
    res = res + estimate(causticMap , nCausticPaths , knnPhotons , scene , inter , -ray.dir , maxSqrDis);

	BSDF bsdf(-ray.dir , inter , scene);

	Real pdf , cosWo;
	int sampledType;
	Ray newRay;

	Color3 bsdfFactor = bsdf.sample(scene , rng.randVector3() ,
		newRay.dir , pdf , cosWo , &sampledType);

	if (bsdfFactor.isBlack())
		return res;

	// Russian Roulette
	Real contProb = bsdf.continueProb;

	if (cmp(contProb - 1.f) < 0)
	{
		if (cmp(rng.randFloat() - contProb) > 0)
			return res;
		pdf *= contProb;
	}
    
	newRay.origin = inter.p + newRay.dir * EPS;
	newRay.tmin = 0; newRay.tmax = INF;

	Color3 contrib = raytracing(newRay , dep + 1);

	res = res + (contrib | bsdfFactor) * (cosWo / pdf);

    return res;
}
void Scene::display()
{

  std::cout << "before direct illumination" << timer.split() << std::endl;
  directIllumination();
  std::cout << "after direct illumination" << timer.split() << std::endl;
  /*
  glEnable(GL_DEPTH_TEST);
  glEnable(GL_LIGHTING);
  glBlendColor(.75, .75, .75, .75);
  glBlendFunc(GL_ONE, GL_CONSTANT_ALPHA);*/
  splatRecords();

  std::cout << "after splatRecords" << timer.split() << std::endl;

  glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
  glViewport(0, 0, windWidth, windHeight);
  float ws[2] = {windWidth, windHeight};
  glUseProgram(finalProgram);
  glActiveTexture(GL_TEXTURE0);
  glBindTexture(GL_TEXTURE_2D, splatTex);
  glUniform1i(finalSplat, 0);
  glActiveTexture(GL_TEXTURE1);
  glBindTexture(GL_TEXTURE_2D, directTex[0]);
  glUniform1i(finalDirect, 1);

  glUniform2fv(finalWindSize, 1, ws);

  glDisable(GL_BLEND);
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  
  glActiveTexture(GL_TEXTURE0);
  glMatrixMode(GL_MODELVIEW);
  glLoadIdentity();
  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();
  glMatrixMode(GL_TEXTURE);
  glLoadIdentity();
  
  glDisable(GL_CULL_FACE);
  glBegin(GL_QUADS);
  glTexCoord2f(0.0,0.0);
  glVertex2f(-1.0, -1.0);
  glTexCoord2f(1.0, 0.0);
  glVertex2f(1.0, -1.0);

  glTexCoord2f(1.0, 1.0);
  glVertex2f(1.0, 1.0);
  glTexCoord2f(0.0, 1.0);
  glVertex2f(-1.0, 1.0);

  glEnd();

  /* glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, 0);
  glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, 0);//splatBufFBOID);
  
  glBlitFramebufferEXT(0,0, windWidth, windHeight,
		       0,0, windWidth, windHeight,
		       GL_COLOR_BUFFER_BIT, GL_NEAREST);*/

  glFlush();

  std::cout << "after combination" << timer.split() << std::endl;
  glutSwapBuffers();


}
glm::vec3 Ray::trace(glm::vec3 rayOrig, glm::vec3 rayDir, float depth, int bounces) {

    // ----------------------------------------------
	// Compare ray with every object in scene
	// Find the smallest distance to an object
    // ----------------------------------------------
	float t0, t1, tNear = INF;
    Surface *s = nullptr; // Pointer to closest object
    
	for (auto &o : *scene->objects) {
		if (o->intersects(rayOrig, rayDir, t0, t1)) {
            if (t0 < tNear) {
                tNear = t0;
                s = o;
            }
		}
	}

    // ----------------------------------------------
    // We have found an object
    // ----------------------------------------------
    if (s != nullptr) {
        
        // If the closes object is a light, return light color
        if (s->isLight())
            return s->color;
    
        // p is the point of intersection
        glm::vec3 directIllumination (0.0);
        glm::vec3 indirectIllumination (0.0);
        
        glm::vec3 p = rayOrig + rayDir * tNear;
        glm::vec3 normal = s->getNormal(p);
        glm::vec3 r = rayDir - 2 * glm::dot(rayDir, normal) * normal; // reflected direction
        
        // ----------------------------------------------
        // Indirect illumination
        // If the object is reflective or refractive, calculate new ray(s)
        // ----------------------------------------------
        if (s->isRefractive()) {
            
            // If the object is refractive, create refractive ray
            // Calculate new refractive ray
            // Need to do a flip if we are inside the object
            //glm::vec3 n = normal;
            //const float index = 1/1.5;
            //Sphere *temp = static_cast <Sphere*>(s);
            //if (glm::length(temp->getCenter() - p) < temp->getRadius()) n = -n;
            
            //glm::vec3 t = glm::normalize(glm::refract(rayDir, n, index));
            
            Ray ray(scene);
            //indirectIllumination += ray.trace(p, t, depth, bounces);
         
            // Calculate reflective ray for both refracive and reflective materials
            // Trace reflective ray
            indirectIllumination += ray.trace(p, r, depth, bounces++);
            indirectIllumination /= (float)bounces;
        }
        
        // ----------------------------------------------
        // Indirect illumination
        // Material is diffuse, do Monte Carlo stuff
        // ----------------------------------------------
        else if(bounces < scene->maxBounces) {
            // Russian roulette
            float r1 = static_cast <float> (rand()) / static_cast <float> (RAND_MAX);
            float r2 = static_cast <float> (rand()) / static_cast <float> (RAND_MAX);
            float absorption = 0.5;
            
            // Ray is scattered
            if (static_cast <float> (rand()) / static_cast <float> (RAND_MAX) > absorption) {

                // New random direction over hemisphere
                float inclination = 2.0 * M_PI * r1;
                float azimuth = acos(2.0 * r2 - 1.0);
                float u = cos(azimuth);
                
                float x	= sqrt(1 - u * u) * cos(inclination);
                float y	= sqrt(1 - u * u) * sin(inclination);
                float z	= u;
                
                // New direction. If it points the wrong way, change direction
                glm::vec3 newDir(x, y, z);
                if (glm::dot(normal, newDir) < 0) newDir = -newDir;
                
                // pdf  - over hemisphere
                // cos  - relationship between normal and the direction reflected light will come from
                // BRDF - Lambertian or Oren-Nayar
                float pdf = 1.0 / 2.0 * M_PI;
                float cos = glm::dot(normal, newDir);
                float BRDF = s->isOren() ? OrenNayarBRDF(newDir, glm::normalize(-scene->cameraDir), normal) : glm::dot(normal, newDir);
                
                Ray ray(scene);
                
                indirectIllumination = ray.trace(p, newDir, depth, bounces++) * cos * BRDF / pdf;
                indirectIllumination /= ((1 - absorption));
            }
        }
        
        // ----------------------------------------------
        // Direct illumination
        // Calculate shadow rays
        // ----------------------------------------------
        int shadowRays = 4;
        
        for (int i = 0; i < scene->lights->size(); i++) {
            Sphere *l = scene->lights->at(i); // Pointer to current light
            glm::vec3 tempColor(0.0); // Total color per light
            float unobstructedRays = 0.0;
            
            for (int j = 0; j < shadowRays; j++) {
                bool shaded = false;
                glm::vec3 pDir = findRandomDirection(p, l); // Vector towards light
                float dist = glm::length(pDir);
                pDir = glm::normalize(pDir);

                // Shoot shadow ray(s) to random position on light (not random now though)
                for (auto &o : *scene->objects)
                    if (o->intersects(p, pDir, t0, t1))
                        if (t0 < dist && !o->isLight()) shaded = true;
                
                if (!shaded) {
                    unobstructedRays++;
                    float lightIntensity = 2.2 * 1.0/255.0;
                    float BRDF = s->isOren() ? OrenNayarBRDF(pDir, glm::normalize(-scene->cameraDir), normal) : glm::dot(normal, pDir);
                    // TODO: N(light) must be calculated properly
                    // radianceTransfer = dot(N(object), shadowRay) * dot(N(light), -shadowRay)
                    float radianceTransfer = glm::dot(normal, pDir) * glm::dot(-pDir, -pDir);
                    float pdfk = 2.0 * M_PI * l->getRadius() * l->getRadius(); // pdf over sphere (lights are halved spheres)
                    float pdfyk = 0.5; // Chance to pick one of the light sources
                    
                    // Direct illumination = light * BRDF * radiance transfer / pdfk * pdfyk
                    tempColor += l->color * lightIntensity * BRDF * radianceTransfer / (pdfk * pdfyk) * s->color;
                }
            }

            directIllumination += tempColor * (1.0f/(float)shadowRays);
        }

        // ----------------------------------------------
        // Add direct and indirect light and return color
        // ----------------------------------------------
        return (indirectIllumination * 2.0 + directIllumination / M_PI);
    }

    // Didn't find any object that intersects
	return glm::vec3(0.0, 0.0, 0.0);
}