Пример #1
0
  /*! Anisotropic power cosine distribution constructor. */
inline void AnisotropicBlinn__Constructor(AnisotropicBlinn* This, const Vec3fa& Kr, const Vec3fa& Kt, 
                                          const Vec3fa& dx, float nx, const Vec3fa& dy, float ny, const Vec3fa& dz) 
{
  This->Kr = Kr;
  This->Kt = Kt;
  This->dx = dx;
  This->nx = nx;
  This->dy = dy;
  This->ny = ny;
  This->dz = dz;
  This->norm1 = sqrtf((nx+1)*(ny+1)) * float(one_over_two_pi);
  This->norm2 = sqrtf((nx+2)*(ny+2)) * float(one_over_two_pi);
  This->side = reduce_max(Kr)/(reduce_max(Kr)+reduce_max(Kt));
}
Пример #2
0
  // We create packets and directly fill each zBuffer tile. Note that we
  // really store t values
  void TaskRayTraceHiZ::run(size_t taskID)
  {
    const uint32 taskX = taskID % this->taskXNum;
    const uint32 taskY = taskID / this->taskXNum;
    const uint32 startX = taskX * this->width;
    const uint32 startY = taskY * this->height;
    const uint32 endX = startX + this->width;
    const uint32 endY = startY + this->height;
    uint32 tileY = startY / HiZ::Tile::height;

    for (uint32 y = startY; y < endY; y += RayPacket::height, ++tileY) {
      uint32 tileX = startX / HiZ::Tile::width;
      for (uint32 x = startX; x < endX; x += RayPacket::width, ++tileX) {
        RayPacket pckt;
        PacketHit hit;
        gen.generate(pckt, x, y);
        intersector->traverse(pckt, hit);
        ssef zmin(inf), zmax(neg_inf);
        const uint32 tileID = tileX + tileY * zBuffer->tileXNum;
        PF_ASSERT(tileID < zBuffer->tileNum);
        HiZ::Tile &tile = zBuffer->tiles[tileID];
        for (uint32 chunkID = 0; chunkID < HiZ::Tile::chunkNum; ++chunkID) {
          //const ssef t = hit.t[chunkID];
          const ssef t = hit.t[chunkID] *dot(sse3f(view.x,view.y,view.z), pckt.dir[chunkID]);
          tile.z[chunkID] = t;
          zmin = min(zmin, t);
          zmax = max(zmax, t);
        }
        tile.zmin = reduce_min(zmin)[0];
        tile.zmax = reduce_max(zmax)[0];
      }
    }
  }
Пример #3
0
void ProbeWidget::render()
{
  const float size = 0.25f * reduce_max(boundingBox.upper - boundingBox.lower);

  glPushAttrib(GL_ENABLE_BIT);
  glDisable(GL_LIGHTING);
  glEnable(GL_DEPTH_TEST);

  glPushMatrix();
  glTranslatef(coordinate.x, coordinate.y, coordinate.z);
  glScalef(size, size, size);

  glBegin(GL_LINES);

  glColor3f(1.f, 0.f, 0.f);
  glVertex3f(-0.5f, 0.f, 0.f);
  glVertex3f( 0.5f, 0.f, 0.f);

  glColor3f(0.f, 1.f, 0.f);
  glVertex3f(0.f, -0.5f, 0.f);
  glVertex3f(0.f,  0.5f, 0.f);

  glColor3f(0.f, 0.f, 1.f);
  glVertex3f(0.f, 0.f, -0.5f);
  glVertex3f(0.f, 0.f,  0.5f);

  glEnd();

  glPopMatrix();
  glPopAttrib();
}
Пример #4
0
      //! \brief commit the material's parameters
      virtual void commit()  override
      {
        if (getIE() == nullptr)
          ispcEquivalent = ispc::PathTracer_OBJ_create();

        Texture2D *map_d  = (Texture2D*)getParamObject("map_d");
        affine2f xform_d  = getTextureTransform("map_d");
        Texture2D *map_Kd = (Texture2D*)getParamObject("map_Kd", getParamObject("map_kd",  getParamObject("colorMap")));
        affine2f xform_Kd = getTextureTransform("map_Kd") * getTextureTransform("map_kd") * getTextureTransform("colorMap"); 
        Texture2D *map_Ks = (Texture2D*)getParamObject("map_Ks", getParamObject("map_ks"));
        affine2f xform_Ks = getTextureTransform("map_Ks") * getTextureTransform("map_ks"); 
        Texture2D *map_Ns = (Texture2D*)getParamObject("map_Ns", getParamObject("map_ns"));
        affine2f xform_Ns = getTextureTransform("map_Ns") * getTextureTransform("map_ns"); 
        Texture2D *map_Bump = (Texture2D*)getParamObject("map_Bump", getParamObject("map_bump", getParamObject("normalMap", getParamObject("bumpMap"))));
        affine2f xform_Bump = getTextureTransform("map_Bump") * getTextureTransform("map_bump") * getTextureTransform("normalMap") * getTextureTransform("BumpMap"); 
        linear2f rot_Bump   = xform_Bump.l.orthogonal().transposed();

        const float d = getParam1f("d", getParam1f("alpha", 1.f));
        vec3f Kd = getParam3f("Kd", getParam3f("kd", getParam3f("color", vec3f(0.8f))));
        vec3f Ks = getParam3f("Ks", getParam3f("ks", vec3f(0.f)));
        const float Ns = getParam1f("Ns", getParam1f("ns", 10.f));
        vec3f Tf = getParam3f("Tf", getParam3f("tf", vec3f(0.0f)));

        const float color_total = reduce_max(Kd + Ks + Tf);
        if (color_total > 1.0) {
          postStatusMsg() << "#osp:PT: warning: OBJ material produces energy "
                          << "(Kd + Ks + Tf = " << color_total
                          << ", should be <= 1). Scaling down to 1.";
          Kd /= color_total;
          Ks /= color_total;
          Tf /= color_total;
        }

        ispc::PathTracer_OBJ_set(ispcEquivalent,
           map_d ? map_d->getIE() : nullptr, (const ispc::AffineSpace2f&)xform_d,
           d,
           map_Kd ? map_Kd->getIE() : nullptr, (const ispc::AffineSpace2f&)xform_Kd,
           (const ispc::vec3f&)Kd,
           map_Ks ? map_Ks->getIE() : nullptr, (const ispc::AffineSpace2f&)xform_Ks,
           (const ispc::vec3f&)Ks,
           map_Ns ? map_Ns->getIE() : nullptr, (const ispc::AffineSpace2f&)xform_Ns,
           Ns,
           (const ispc::vec3f&)Tf,
           map_Bump ? map_Bump->getIE() : nullptr, (const ispc::AffineSpace2f&)xform_Bump,
           (const ispc::LinearSpace2f&)rot_Bump);
      }
Пример #5
0
 void TriangleMeshWithNormals::postIntersect(const StreamRay& ray, const StreamRayExtra& rayExtra, const StreamHit& hit, DifferentialGeometry& dg) const
 {
   const Triangle& tri = triangles[hit.id1];
   const Vertex& v0 = vertices[tri.v0];
   const Vertex& v1 = vertices[tri.v1];
   const Vertex& v2 = vertices[tri.v2];
   float u = hit.u, v = hit.v, w = 1.0f-u-v, t = ray.tfar;
   Vector3f dPdu = v1.p - v0.p, dPdv = v2.p - v0.p;
   dg.P = rayExtra.org()+t*rayExtra.dir();
   dg.Ng = normalize(_mm_load_ps(hit.Ng));
   dg.st = Vec2f(u,v);
   Vector3f Ns = w*v0.n + u*v1.n + v*v2.n;
   float len2 = dot(Ns,Ns);
   Ns = len2 > 0 ? Ns*rsqrt(len2) : Vector3f(dg.Ng);
   if (dot(Ns,dg.Ng) < 0) Ns = -Ns;
   dg.Ns = Ns;
   dg.Tx = dPdu;
   dg.Ty = dPdv;
   dg.error = max(abs(ray.tfar),reduce_max(abs(dg.P)));
 }
Пример #6
0
/* task that renders a single screen tile */
Vec3fa renderPixelPathTrace(float x, float y, const Vec3fa& vx, const Vec3fa& vy, const Vec3fa& vz, const Vec3fa& p)
{
  RandomSampler sampler;
  RandomSampler_init(sampler, x, y, g_accu_count);
  x += RandomSampler_get1D(sampler);
  y += RandomSampler_get1D(sampler);
  float time = RandomSampler_get1D(sampler);

  /* initialize ray */
  RTCRay2 ray;
  ray.org = p;
  ray.dir = normalize(x*vx + y*vy + vz);
  ray.tnear = 0.0f;
  ray.tfar = inf;
  ray.geomID = RTC_INVALID_GEOMETRY_ID;
  ray.primID = RTC_INVALID_GEOMETRY_ID;
  ray.mask = -1;
  ray.time = time;
  ray.filter = nullptr; 
  
  Vec3fa color = Vec3fa(0.0f);
  Vec3fa weight = Vec3fa(1.0f);
  size_t depth = 0;

  while (true)
  {
    /* terminate ray path */
    if (reduce_max(weight) < 0.01 || depth > 20) 
      return color;

    /* intersect ray with scene and gather all hits */
    rtcIntersect(g_scene,*((RTCRay*)&ray));
    
    /* exit if we hit environment */
    if (ray.geomID == RTC_INVALID_GEOMETRY_ID) 
      return color + weight*Vec3fa(g_ambient_intensity);

    /* calculate transmissivity of hair */
    AnisotropicBlinn brdf;
    float tnear_eps = 0.0001f;

    ISPCGeometry* geometry = g_ispc_scene->geometries[ray.geomID];
    if (geometry->type == HAIR_SET) 
    {
      /* calculate tangent space */
      const Vec3fa dx = normalize(ray.Ng);
      const Vec3fa dy = normalize(cross(ray.dir,dx));
      const Vec3fa dz = normalize(cross(dy,dx));

      /* generate anisotropic BRDF */
      AnisotropicBlinn__Constructor(&brdf,hair_Kr,hair_Kt,dx,20.0f,dy,2.0f,dz);
      brdf.Kr = hair_Kr;
      Vec3fa p = evalBezier(ray.geomID,ray.primID,ray.u);
      tnear_eps = 1.1f*p.w;
    }
    else if (geometry->type == TRIANGLE_MESH)
    {
      ISPCTriangleMesh* mesh = (ISPCTriangleMesh*) geometry;
      ISPCTriangle* triangle = &mesh->triangles[ray.primID];
      OBJMaterial* material = (OBJMaterial*) &g_ispc_scene->materials[triangle->materialID];

      if (dot(ray.dir,ray.Ng) > 0) ray.Ng = neg(ray.Ng);
      
      /* calculate tangent space */
      const Vec3fa dz = normalize(ray.Ng);
      const Vec3fa dx = normalize(cross(dz,ray.dir));
      const Vec3fa dy = normalize(cross(dz,dx));
      
      /* generate isotropic BRDF */
      AnisotropicBlinn__Constructor(&brdf,Vec3fa(1.0f),Vec3fa(0.0f),dx,1.0f,dy,1.0f,dz);
    }
    
    /* sample directional light */
    RTCRay2 shadow;
    shadow.org = ray.org + ray.tfar*ray.dir;
    shadow.dir = neg(Vec3fa(g_dirlight_direction));
    shadow.tnear = tnear_eps;
    shadow.tfar = inf;
    shadow.time = time;
    Vec3fa T = occluded(g_scene,shadow);
    Vec3fa c = AnisotropicBlinn__eval(&brdf,neg(ray.dir),neg(Vec3fa(g_dirlight_direction)));
    color = color + weight*c*T*Vec3fa(g_dirlight_intensity);

#if 1
    /* sample BRDF */
    Vec3fa wi;
    float ru = RandomSampler_get1D(sampler);
    float rv = RandomSampler_get1D(sampler);
    float rw = RandomSampler_get1D(sampler);
    c = AnisotropicBlinn__sample(&brdf,neg(ray.dir),wi,ru,rv,rw);
    if (wi.w <= 0.0f) return color;

    /* calculate secondary ray and offset it out of the hair */
    float sign = dot(Vec3fa(wi),brdf.dz) < 0.0f ? -1.0f : 1.0f;
    ray.org = ray.org + ray.tfar*ray.dir + sign*tnear_eps*brdf.dz;
    ray.dir = Vec3fa(wi);
    ray.tnear = 0.001f;
    ray.tfar = inf;
    ray.geomID = RTC_INVALID_GEOMETRY_ID;
    ray.primID = RTC_INVALID_GEOMETRY_ID;
    ray.mask = -1;
    ray.time = time;
    ray.filter = nullptr;
    weight = weight * c/wi.w;

#else    

    /* continue with transparency ray */
    ray.geomID = RTC_INVALID_GEOMETRY_ID;
    ray.tnear = 1.001f*ray.tfar;
    ray.tfar = inf;
    weight *= brdf.Kt;
    
#endif

    depth++;
  }
  return color;
}
Пример #7
0
  Col3f PathTraceIntegrator::Li(const LightPath& lightPathOrig, const Ref<BackendScene>& scene, Sampler* sampler, size_t& numRays)
  {
	  bool done = false;
	  Col3f coeff = Col3f(1,1,1);
	  Col3f Lsum = zero;
	  Col3f L = zero;
	  LightPath lightPath = lightPathOrig;
    bool doneDiffuse = false;

    /*! while cycle instead of the recusrion call 
    * throughput is accumulated and the resulting light addition is 
    * multipliled by this throughput (coef) at each itteration */
	  while (!done)
	  {

    BRDFType directLightingBRDFTypes = (BRDFType)(DIFFUSE);
    BRDFType giBRDFTypes = (BRDFType)(ALL);

    /*! Terminate path if too long or contribution too low. */
    L = zero;

    /*! Terminate the path if maxDepth is reached */
    if (lightPath.depth >= maxDepth) // || reduce_max(coeff) < minContribution)
      return Lsum;

    /*! Traverse ray. */
    DifferentialGeometry dg;
    scene->accel->intersect(lightPath.lastRay,dg);
    scene->postIntersect(lightPath.lastRay,dg);
    const Vec3f wo = -lightPath.lastRay.dir;
    numRays++;

    /*! Environment shading when nothing hit. */
    if (!dg)
    {
      if (backplate && lightPath.unbend) {
        Vec2f raster = sampler->getPrimary();
        int width = sampler->getImageSize().x;
        int height = sampler->getImageSize().y;
        int x = (int)((raster.x / width) * backplate->width);
        x = clamp(x, 0, int(backplate->width)-1);
        int y = (int)((raster.y / height) * backplate->height);
        y = clamp(y, 0, int(backplate->height)-1);
        L = backplate->get(x, y);
      }
      else {
        if (!lightPath.ignoreVisibleLights)
          for (size_t i=0; i<scene->envLights.size(); i++)
            L += scene->envLights[i]->Le(wo);
      }
      return Lsum + L*coeff;
    }

    /*! Shade surface. */
    CompositedBRDF brdfs;
    if (dg.material) dg.material->shade(lightPath.lastRay, lightPath.lastMedium, dg, brdfs);

    /*! face forward normals */
    bool backfacing = false;
#if defined(__EMBREE_CONSISTENT_NORMALS__) && __EMBREE_CONSISTENT_NORMALS__ > 1
    return Col3f(abs(dg.Ns.x),abs(dg.Ns.y),abs(dg.Ns.z));
#else
    if (dot(dg.Ng, lightPath.lastRay.dir) > 0) {
      backfacing = true; dg.Ng = -dg.Ng; dg.Ns = -dg.Ns;
    }
#endif

    /*! Sample BRDF - get the sample direction for
    * both the indirect illumination as well as for the MIS BRDF sampling */
    Col3f c; Sample3f wi;BRDFType type;
    Vec2f s  = sampler->getVec2f(firstScatterSampleID     + lightPath.depth);
    float ss = sampler->getFloat(firstScatterTypeSampleID + lightPath.depth);
    c = brdfs.sample(wo, dg, wi, type, s, ss, giBRDFTypes);

    /*! Add light emitted by hit area light source. */
    if (!lightPath.ignoreVisibleLights && dg.light && !backfacing)
      L += dg.light->Le(dg,wo);

    /*! Check if any BRDF component uses direct lighting. */
    bool useDirectLighting = false;
    for (size_t i=0; i<brdfs.size(); i++)
      useDirectLighting |= (brdfs[i]->type & directLightingBRDFTypes) != NONE;

    /*! Direct lighting. */
    if (useDirectLighting)
    {
		  std::vector<float> illumFactor;  // illumination factor for each ls
      float sum = 0;
      LightSample ls;

		  if ( wi.pdf > 0.0f )
	    {
		    Ray r( dg.P, wi.value, dg.error*epsilon, inf );
		    DifferentialGeometry diff;
		    scene->accel->intersect( r, diff );
		    scene->postIntersect( r, diff );

// 		    Col3f red = Col3f( 1.0f, 0.0f, 0.0f);
		    Col3f radiance =  Col3f( 0.0f,0.0f,0.0f );
		    if ( diff.light  ) // if BRDF sampling hits the light
		    {
		      radiance = diff.light->Le(diff, -wi.value );
		    }
        
        if ( dot( diff.Ng, -r.dir ) > 0 && type != GLOSSY_REFLECTION)	
	        L += radiance * c / wi.pdf;
      }

		/*! Run through all the lightsources and sample or compute the distribution function for rnd gen */
		for (size_t i=0; i<scene->allLights.size(); i++)
      {
        /*! Either use precomputed samples for the light or sample light now. */
        if (scene->allLights[i]->precompute()) ls = sampler->getLightSample(precomputedLightSampleID[i]);
        else ls.L = scene->allLights[i]->sample(dg, ls.wi, ls.tMax, sampler->getVec2f(lightSampleID));

		    /*! Start using only one random lightsource after first Lambertian reflection
        * in case of the direct illumination MIS this heuristics is ommited */ 
		    if (true)//donedif
		    {
			    /*! run through all the lighsources and compute radiance accumulatively */
          float boo = reduce_max(ls.L)/ls.tMax;  // incomming illuminance heuristic
          sum += boo;
			    illumFactor.push_back(boo);  // illumination factor
		    }
		    else  // if all the lights are sampled - take each sample and compute the addition
		    {
			    /*! Ignore zero radiance or illumination from the back. */
			    if (ls.L == Col3f(zero) || ls.wi.pdf == 0.0f || dot(dg.Ns,Vec3f(ls.wi)) <= 0.0f) continue;

			    /*! Test for shadows. */
			    bool inShadow = scene->accel->occluded(Ray(dg.P, ls.wi, dg.error*epsilon, ls.tMax-dg.error*epsilon));
			    numRays++;
			    if (inShadow) continue;

			    /*! Evaluate BRDF. */
			    L += ls.L * brdfs.eval(wo, dg, ls.wi, directLightingBRDFTypes) * rcp(ls.wi.pdf);
		    }
      }

	  /*! After fisrt Lambertian reflection pick one random lightsource and compute contribution
    * in case of MIS active this heuristic is ommited */
	  if (true && scene->allLights.size() != 0)//donedif
	  {
		  /*! Generate the random value */
		  unsigned int RndVal;  // random value
//       if (rand_s(&RndVal)) std::cout << "\nRND gen error!\n";
		  rand_r(&RndVal);
      float rnd((float)RndVal/(float)UINT_MAX);  // compute the 0-1 rnd value
		  
		  /*! Pick the particular lightsource according the intensity-given distribution */
		  size_t i = 0; 
      float accum = illumFactor[i]/sum;  // accumulative sum
		  while (i < scene->allLights.size() && rnd > accum)  // get the lightsource index accirding the Pr
      {
			  ++i;
        accum +=illumFactor[i]/sum;
      }

		  /*! Sample the selected lightsource and compute contribution */
		  if ( i >= scene->allLights.size() ) i = scene->allLights.size() -1;
      // if (usedLight != NULL)
      // std::cout << "direct light " << scene->allLights[i].ptr << "\n";
        float ql = illumFactor[i]/sum;  // Pr of given lightsource
		    // LightSample ls;
		    if (scene->allLights[i]->precompute()) ls = sampler->getLightSample(precomputedLightSampleID[i]);
		    else ls.L = scene->allLights[i]->sample(dg, ls.wi, ls.tMax, sampler->getVec2f(lightSampleID));

		    /*! Ignore zero radiance or illumination from the back. */
		    if (ls.L != Col3f(zero) && ls.wi.pdf != 0.0f && dot(dg.Ns,Vec3f(ls.wi)) > 0.0f) 
		    {
			    /*! Test for shadows. */
			    bool inShadow = scene->accel->occluded(Ray(dg.P, ls.wi, dg.error*epsilon, ls.tMax-dg.error*epsilon));
			    numRays++;
			    if (!inShadow) 
			    {
				    /*! Evaluate BRDF. */
				    L += ls.L * brdfs.eval(wo, dg, ls.wi, directLightingBRDFTypes) * rcp(ls.wi.pdf*ql) * weight;
			    }
        }
	  }
    }
	
	/* Add the resulting light */
	Lsum += coeff * L;

    /*! Global illumination. Pick one BRDF component and sample it. */
    if (lightPath.depth < maxDepth) //always true
    {
      /*! Continue only if we hit something valid. */
      if (c != Col3f(zero) && wi.pdf > 0.0f)
      {
        /*! detect the first diffuse */
        if (wi.pdf < 0.33) doneDiffuse = true;

        /*! Compute  simple volumetric effect. */
        const Col3f& transmission = lightPath.lastMedium.transmission;
        if (transmission != Col3f(one)) c *= pow(transmission,dg.t);

        /*! Tracking medium if we hit a medium interface. */
        Medium nextMedium = lightPath.lastMedium;
        if (type & TRANSMISSION) nextMedium = dg.material->nextMedium(lightPath.lastMedium);

        /*! Continue the path. */
		    float q = 1;
        if (doneDiffuse) { //std::cout << "\ndifusni\n";
          q = min(abs(reduce_max(c) * rcp(wi.pdf)), (float)1);
          // std::cout << q << "\n";
          unsigned int RndVal;
//           if (rand_s(&RndVal)) std::cout << "\nRND gen error!\n";
          rand_r(&RndVal);
          if ((float)RndVal/(float)UINT_MAX > q) { // std::cout << "konec";
            return Lsum;// + L*coeff;
          }
        }
        /*! Continue the path */
		    lightPath = lightPath.extended(Ray(dg.P, wi, dg.error*epsilon, inf), nextMedium, c, (type & directLightingBRDFTypes) != NONE);
		    coeff = coeff * c * rcp(q * wi.pdf);
      }else done = true;   // end the path
    }
  }
  return Lsum;
  }
Пример #8
0
/* task that renders a single screen tile */
Vec3fa renderPixelPathTrace(float x, float y, const Vec3fa& vx, const Vec3fa& vy, const Vec3fa& vz, const Vec3fa& p)
{
  int seed = 21344*x+121233*y+234532*g_accu_count;
  float time = frand(seed);

  /* initialize ray */
  RTCRay2 ray;
  ray.org = p;
  ray.dir = normalize(x*vx + y*vy + vz);
  ray.tnear = 0.0f;
  ray.tfar = inf;
  ray.geomID = RTC_INVALID_GEOMETRY_ID;
  ray.primID = RTC_INVALID_GEOMETRY_ID;
  ray.mask = -1;
  ray.time = time;
  ray.filter = NULL; 
  
  Vec3fa color = Vec3fa(0.0f);
  Vec3fa weight = Vec3fa(1.0f);
  size_t depth = 0;

  while (true)
  {
    /* terminate ray path */
    if (reduce_max(weight) < 0.01 || depth > 20) 
      return color;

    /* intersect ray with scene and gather all hits */
    rtcIntersect(g_scene,*((RTCRay*)&ray)); // FIXME: use (RTCRay&) cast
    
    /* exit if we hit environment */
    if (ray.geomID == RTC_INVALID_GEOMETRY_ID) 
      return color + weight*Vec3fa(g_ambient_intensity);

    /* calculate transmissivity of hair */
    AnisotropicBlinn brdf;
    float tnear_eps = 0.0001f;

    if (ray.geomID < g_ispc_scene->numHairSets) 
    {
      /* calculate tangent space */
      const Vec3fa dx = normalize(ray.Ng);
      const Vec3fa dy = normalize(cross(ray.dir,dx));
      const Vec3fa dz = normalize(cross(dy,dx));

      /* generate anisotropic BRDF */
      AnisotropicBlinn__Constructor(&brdf,hair_Kr,hair_Kt,dx,20.0f,dy,2.0f,dz);
      brdf.Kr = hair_Kr;
      Vec3fa p = evalBezier(ray.geomID,ray.primID,ray.u);
      tnear_eps = 1.1f*p.w;
    }
    else 
    {
      int meshID = ray.geomID-g_ispc_scene->numHairSets;
      ISPCMesh* mesh = g_ispc_scene->meshes[meshID];
      ISPCTriangle* triangle = &mesh->triangles[ray.primID];
      ISPCMaterial* material = &g_ispc_scene->materials[triangle->materialID];
      if (material->illum == 1)
      {
        /* calculate tangent space */
        const Vec3fa dx = normalize(Vec3fa(mesh->normals[triangle->v0]));
        const Vec3fa dy = normalize(cross(ray.dir,dx));
        const Vec3fa dz = normalize(cross(dy,dx));
        
        /* generate anisotropic BRDF */
        AnisotropicBlinn__Constructor(&brdf,hair_Kr,hair_Kt,dx,20.0f,dy,2.0f,dz);
        brdf.Kr = hair_Kr;
        tnear_eps = 1.1f*mesh->texcoords[triangle->v0].x;
      }
      else
      {
        if (dot(ray.dir,ray.Ng) > 0) ray.Ng = neg(ray.Ng);
        
        /* calculate tangent space */
        const Vec3fa dz = normalize(ray.Ng);
        const Vec3fa dx = normalize(cross(dz,ray.dir));
        const Vec3fa dy = normalize(cross(dz,dx));
        
        /* generate isotropic BRDF */
        AnisotropicBlinn__Constructor(&brdf,Vec3fa(1.0f),Vec3fa(0.0f),dx,1.0f,dy,1.0f,dz);
      }
    }
    
    /* sample directional light */
    RTCRay2 shadow;
    shadow.org = ray.org + ray.tfar*ray.dir;
    shadow.dir = neg(Vec3fa(g_dirlight_direction));
    shadow.tnear = tnear_eps;
    shadow.tfar = inf;
    shadow.time = time;
    Vec3fa T = occluded(g_scene,shadow);
    Vec3fa c = AnisotropicBlinn__eval(&brdf,neg(ray.dir),neg(Vec3fa(g_dirlight_direction)));
    color = color + weight*c*T*Vec3fa(g_dirlight_intensity); // FIXME: use += operator

#if 1
    /* sample BRDF */
    Vec3fa wi;
    c = AnisotropicBlinn__sample(&brdf,neg(ray.dir),wi,frand(seed),frand(seed),frand(seed));
    if (wi.w <= 0.0f) return color;

    /* calculate secondary ray and offset it out of the hair */
    float sign = dot(Vec3fa(wi),brdf.dz) < 0.0f ? -1.0f : 1.0f;
    ray.org = ray.org + ray.tfar*ray.dir + sign*tnear_eps*brdf.dz;
    ray.dir = Vec3fa(wi);
    ray.tnear = 0.001f;
    ray.tfar = inf;
    ray.geomID = RTC_INVALID_GEOMETRY_ID;
    ray.primID = RTC_INVALID_GEOMETRY_ID;
    ray.mask = -1;
    ray.time = time;
    ray.filter = NULL;
    weight = weight * c/wi.w; // FIXME: use *= operator

#else    

    /* continue with transparency ray */
    ray.geomID = RTC_INVALID_GEOMETRY_ID;
    ray.tnear = 1.001f*ray.tfar;
    ray.tfar = inf;
    weight *= brdf.Kt;
    
#endif

    depth++;
  }
  return color;
}
  Color PathTraceIntegrator::Li(LightPath& lightPath, const Ref<BackendScene>& scene, IntegratorState& state)
  {
    /*! Terminate path if too long or contribution too low. */
    if (lightPath.depth >= maxDepth || reduce_max(lightPath.throughput) < minContribution)
      return zero;

    /*! Traverse ray. */
    DifferentialGeometry dg;
    //scene->intersector->intersect(lightPath.lastRay);
    rtcIntersect(scene->scene,(RTCRay&)lightPath.lastRay);
    scene->postIntersect(lightPath.lastRay,dg);
    state.numRays++;
    //return Color(dg.st.x,dg.st.y,0.0f);

    Color L = zero;
    const Vector3f wo = -lightPath.lastRay.dir;
    BRDFType directLightingBRDFTypes = (BRDFType)(DIFFUSE); 
    BRDFType giBRDFTypes = (BRDFType)(ALL);
    if (sampleLightForGlossy) {
      directLightingBRDFTypes = (BRDFType)(DIFFUSE|GLOSSY); 
      giBRDFTypes = (BRDFType)(SPECULAR);
    }

    /*! Environment shading when nothing hit. */
    if (!lightPath.lastRay)
    {
      if (backplate && lightPath.unbend) {
        const int x = clamp(int(state.pixel.x * backplate->width ), 0, int(backplate->width )-1);
        const int y = clamp(int(state.pixel.y * backplate->height), 0, int(backplate->height)-1);
        L = backplate->get(x, y);
      }
      else {
        if (!lightPath.ignoreVisibleLights)
          for (size_t i=0; i<scene->envLights.size(); i++)
            L += scene->envLights[i]->Le(wo);
      }
      return L;
    }

    /*! face forward normals */
    bool backfacing = false;
    if (dot(dg.Ng, lightPath.lastRay.dir) > 0) {
      backfacing = true; dg.Ng = -dg.Ng; dg.Ns = -dg.Ns;
    }

    /*! Shade surface. */
    CompositedBRDF brdfs;
    if (dg.material) dg.material->shade(lightPath.lastRay, lightPath.lastMedium, dg, brdfs);

    /*! Add light emitted by hit area light source. */
    if (!lightPath.ignoreVisibleLights && dg.light && !backfacing)
      L += dg.light->Le(dg,wo);

    /*! Global illumination. Pick one BRDF component and sample it. */
    if (lightPath.depth < maxDepth)
    {
      /*! sample brdf */
      Sample3f wi; BRDFType type;
      Vec2f s  = state.sample->getVec2f(firstScatterSampleID     + lightPath.depth);
      float ss = state.sample->getFloat(firstScatterTypeSampleID + lightPath.depth);
      Color c = brdfs.sample(wo, dg, wi, type, s, ss, giBRDFTypes);

      /*! Continue only if we hit something valid. */
      if (c != Color(zero) && wi.pdf > 0.0f)
      {
        /*! Compute  simple volumetric effect. */
        const Color& transmission = lightPath.lastMedium.transmission;
        if (transmission != Color(one)) c *= pow(transmission,lightPath.lastRay.tfar);

        /*! Tracking medium if we hit a medium interface. */
        Medium nextMedium = lightPath.lastMedium;
        if (type & TRANSMISSION) nextMedium = dg.material->nextMedium(lightPath.lastMedium);

        /*! Continue the path. */
        LightPath scatteredPath = lightPath.extended(Ray(dg.P, wi, dg.error*epsilon, inf, lightPath.lastRay.time), 
                                                     nextMedium, c, (type & directLightingBRDFTypes) != NONE);
        L += c * Li(scatteredPath, scene, state) * rcp(wi.pdf);
      }
    }

    /*! Check if any BRDF component uses direct lighting. */
    bool useDirectLighting = false;
    for (size_t i=0; i<brdfs.size(); i++)
      useDirectLighting |= (brdfs[i]->type & directLightingBRDFTypes) != NONE;

    /*! Direct lighting. Shoot shadow rays to all light sources. */
    if (useDirectLighting)
    {
      for (size_t i=0; i<scene->allLights.size(); i++)
      {
        if ((scene->allLights[i]->illumMask & dg.illumMask) == 0)
          continue;

        /*! Either use precomputed samples for the light or sample light now. */
        LightSample ls;
        if (scene->allLights[i]->precompute()) ls = state.sample->getLightSample(precomputedLightSampleID[i]);
        else ls.L = scene->allLights[i]->sample(dg, ls.wi, ls.tMax, state.sample->getVec2f(lightSampleID));

        /*! Ignore zero radiance or illumination from the back. */
        //if (ls.L == Color(zero) || ls.wi.pdf == 0.0f || dot(dg.Ns,Vector3f(ls.wi)) <= 0.0f) continue; 
        if (ls.L == Color(zero) || ls.wi.pdf == 0.0f) continue;

        /*! Evaluate BRDF */
        Color brdf = brdfs.eval(wo, dg, ls.wi, directLightingBRDFTypes);
        if (brdf == Color(zero)) continue;

        /*! Test for shadows. */
        Ray shadowRay(dg.P, ls.wi, dg.error*epsilon, ls.tMax-dg.error*epsilon, lightPath.lastRay.time,dg.shadowMask);
        rtcOccluded(scene->scene,(RTCRay&)shadowRay);
        state.numRays++;
        if (shadowRay) continue;

        /*! Evaluate BRDF. */
        L += ls.L * brdf * rcp(ls.wi.pdf);
      }
    }
    
    return L;
  }
Пример #10
0
  void TriangleMeshFull::postIntersect(const StreamRay& ray, const StreamRayExtra& rayExtra, const StreamHit& hit, DifferentialGeometry& dg) const
  {
    const Triangle& tri = triangles[hit.id1];
    
  const float u = hit.u, v = hit.v, w = 1.0f - u - v, t = ray.tfar;
  dg.P = rayExtra.org() + t*rayExtra.dir();
  dg.Ng = normalize(_mm_load_ps(hit.Ng));

    /* interpolate shading normal */
    if (normal.size())
    {
      const Vector3f n0 = normal[tri.v0], n1 = normal[tri.v1], n2 = normal[tri.v2];
      Vector3f Ns = w*n0 + u*n1 + v*n2;
    Vector3f nNs = normalize(Ns);
    if (dot(Ns, dg.Ng) < 0) nNs = -nNs;
    dg.Ns = nNs;
    }
    else
      dg.Ns = dg.Ng;

  dg.error = max(abs(ray.tfar), reduce_max(abs(dg.P)));

  if (!dg.material || !dg.material->computeTextureCoordinates)
    return;

  /* interpolate texture coordinates */
  float dsdu, dtdu;
  float dsdv, dtdv;
  if (texcoord.size()) {
    const Vec2f st0 = texcoord[tri.v0];
    const Vec2f st1 = texcoord[tri.v1];
    const Vec2f st2 = texcoord[tri.v2];
    dg.st = st0*w + st1*u + st2*v;
    dsdu = st1.x - st0.x; dtdu = st1.y - st0.y;
    dsdv = st2.x - st0.x; dtdv = st2.y - st0.y;
  }
  else {
    dg.st = Vec2f(u, v);
    dsdu = 1; dtdu = 0;
    dsdv = 0; dtdv = 1;
  }

  if (!dg.material || !dg.material->computeTangentBasis)
    return;

  Vector3f p0 = position[tri.v0], p1 = position[tri.v1], p2 = position[tri.v2];
  const Vector3f dPdu = p1 - p0, dPdv = p2 - p0;

  if (unlikely(motion.size())) {
    p0 += rayExtra.time * motion[tri.v0];
    p1 += rayExtra.time * motion[tri.v1];
    p2 += rayExtra.time * motion[tri.v2];
  }

    /* interpolate x tangent direction */
    if (tangent_x.size()) { 
      const Vector3f t0 = tangent_x[tri.v0], t1 = tangent_x[tri.v1], t2 = tangent_x[tri.v2];
      dg.Tx = w*t0 + u*t1 + v*t2;
    }
    else {
      const Vector3f dPds = dPdu*dtdv - dPdv*dtdu;
      dg.Tx = dPds-dot(dPds,dg.Ns)*dg.Ns;
    }

    /* interpolate y tangent direction */
    if (tangent_y.size()) {
      const Vector3f t0 = tangent_y[tri.v0], t1 = tangent_y[tri.v1], t2 = tangent_y[tri.v2];
      dg.Ty = w*t0 + u*t1 + v*t2;
    } else {
      const Vector3f dPdt = dPdv*dsdu - dPdu*dsdv;
      dg.Ty = dPdt-dot(dPdt,dg.Ns)*dg.Ns;
    }

  dg.Tx = normalize(dg.Tx);
  dg.Ty = normalize(dg.Ty);
  }
Пример #11
0
  size_t BVH4MB::rotate(Base* nodeID, size_t depth)
  {
    /*! nothing to rotate if we reached a leaf node. */
    if (nodeID->isLeaf()) return 0;
    Node* parent = nodeID->node();

    /*! rotate all children first */
    ssei cdepth;
    for (size_t c=0; c<4; c++)
      cdepth[c] = (int)rotate(parent->child[c],depth+1);

    /* compute current area of all children */
    ssef sizeX = parent->upper_x-parent->lower_x;
    ssef sizeY = parent->upper_y-parent->lower_y;
    ssef sizeZ = parent->upper_z-parent->lower_z;
    ssef childArea = sizeX*(sizeY + sizeZ) + sizeY*sizeZ;

    /*! transpose node bounds */
    ssef plower0,plower1,plower2,plower3; transpose(parent->lower_x,parent->lower_y,parent->lower_z,ssef(zero),plower0,plower1,plower2,plower3);
    ssef pupper0,pupper1,pupper2,pupper3; transpose(parent->upper_x,parent->upper_y,parent->upper_z,ssef(zero),pupper0,pupper1,pupper2,pupper3);
    BBox<ssef> other0(plower0,pupper0), other1(plower1,pupper1), other2(plower2,pupper2), other3(plower3,pupper3);

    /*! Find best rotation. We pick a target child of a first child,
      and swap this with an other child. We perform the best such
      swap. */
    float bestCost = pos_inf;
    int bestChild = -1, bestTarget = -1, bestOther = -1;
    for (size_t c=0; c<4; c++)
    {
      /*! ignore leaf nodes as we cannot descent into */
      if (parent->child[c]->isLeaf()) continue;
      Node* child = parent->child[c]->node();

      /*! transpose child bounds */
      ssef clower0,clower1,clower2,clower3; transpose(child->lower_x,child->lower_y,child->lower_z,ssef(zero),clower0,clower1,clower2,clower3);
      ssef cupper0,cupper1,cupper2,cupper3; transpose(child->upper_x,child->upper_y,child->upper_z,ssef(zero),cupper0,cupper1,cupper2,cupper3);
      BBox<ssef> target0(clower0,cupper0), target1(clower1,cupper1), target2(clower2,cupper2), target3(clower3,cupper3);

      /*! put other0 at each target position */
      float cost00 = halfArea3f(merge(other0 ,target1,target2,target3));
      float cost01 = halfArea3f(merge(target0,other0 ,target2,target3));
      float cost02 = halfArea3f(merge(target0,target1,other0 ,target3));
      float cost03 = halfArea3f(merge(target0,target1,target2,other0 ));
      ssef cost0 = ssef(cost00,cost01,cost02,cost03);
      ssef min0 = vreduce_min(cost0);
      int pos0 = (int)__bsf(movemask(min0 == cost0));

      /*! put other1 at each target position */
      float cost10 = halfArea3f(merge(other1 ,target1,target2,target3));
      float cost11 = halfArea3f(merge(target0,other1 ,target2,target3));
      float cost12 = halfArea3f(merge(target0,target1,other1 ,target3));
      float cost13 = halfArea3f(merge(target0,target1,target2,other1 ));
      ssef cost1 = ssef(cost10,cost11,cost12,cost13);
      ssef min1 = vreduce_min(cost1);
      int pos1 = (int)__bsf(movemask(min1 == cost1));

      /*! put other2 at each target position */
      float cost20 = halfArea3f(merge(other2 ,target1,target2,target3));
      float cost21 = halfArea3f(merge(target0,other2 ,target2,target3));
      float cost22 = halfArea3f(merge(target0,target1,other2 ,target3));
      float cost23 = halfArea3f(merge(target0,target1,target2,other2 ));
      ssef cost2 = ssef(cost20,cost21,cost22,cost23);
      ssef min2 = vreduce_min(cost2);
      int pos2 = (int)__bsf(movemask(min2 == cost2));

      /*! put other3 at each target position */
      float cost30 = halfArea3f(merge(other3 ,target1,target2,target3));
      float cost31 = halfArea3f(merge(target0,other3 ,target2,target3));
      float cost32 = halfArea3f(merge(target0,target1,other3 ,target3));
      float cost33 = halfArea3f(merge(target0,target1,target2,other3 ));
      ssef cost3 = ssef(cost30,cost31,cost32,cost33);
      ssef min3 = vreduce_min(cost3);
      int pos3 = (int)__bsf(movemask(min3 == cost3));

      /*! find best other child */
      ssef otherCost = ssef(extract<0>(min0),extract<0>(min1),extract<0>(min2),extract<0>(min3));
      int pos[4] = { pos0,pos1,pos2,pos3 };
      sseb valid = ssei(int(depth+1))+cdepth <= ssei(maxDepth); // only select swaps that fulfill depth constraints
      if (none(valid)) continue;
      
      size_t n = select_min(valid,otherCost);
      float cost = otherCost[n]-childArea[c]; //< increasing the original child bound is bad, decreasing good

      /*! accept a swap when it reduces cost and is not swapping a node with itself */
      if (cost < bestCost && n != c) {
        bestCost = cost;
        bestChild = (int)c;
        bestOther = (int)n;
        bestTarget = pos[n];
      }
    }

    /*! if we did not find a swap that improves the SAH then do nothing */
    if (bestCost >= 0) return 1+reduce_max(cdepth);

    /*! perform the best found tree rotation */
    Node* child = parent->child[bestChild]->node();
    swap(parent,bestOther,child,bestTarget);
    parent->lower_x[bestChild] = reduce_min(child->lower_x);
    parent->lower_y[bestChild] = reduce_min(child->lower_y);
    parent->lower_z[bestChild] = reduce_min(child->lower_z);
    parent->upper_x[bestChild] = reduce_max(child->upper_x);
    parent->upper_y[bestChild] = reduce_max(child->upper_y);
    parent->upper_z[bestChild] = reduce_max(child->upper_z);
    parent->lower_dx[bestChild] = reduce_min(child->lower_dx);
    parent->lower_dy[bestChild] = reduce_min(child->lower_dy);
    parent->lower_dz[bestChild] = reduce_min(child->lower_dz);
    parent->upper_dx[bestChild] = reduce_max(child->upper_dx);
    parent->upper_dy[bestChild] = reduce_max(child->upper_dy);
    parent->upper_dz[bestChild] = reduce_max(child->upper_dz);

    /*! This returned depth is conservative as the child that was
     *  pulled up in the tree could have been on the critical path. */
    cdepth[bestOther]++; // bestOther was pushed down one level
    return 1+reduce_max(cdepth); 
  }
Пример #12
0
    size_t BVHNRotate<4>::rotate(NodeRef parentRef, size_t depth)
    {
      /*! nothing to rotate if we reached a leaf node. */
      if (parentRef.isBarrier()) return 0;
      if (parentRef.isLeaf()) return 0;
      Node* parent = parentRef.node();
      
      /*! rotate all children first */
      vint4 cdepth;
      for (size_t c=0; c<4; c++)
	cdepth[c] = (int)rotate(parent->child(c),depth+1);
      
      /* compute current areas of all children */
      vfloat4 sizeX = parent->upper_x-parent->lower_x;
      vfloat4 sizeY = parent->upper_y-parent->lower_y;
      vfloat4 sizeZ = parent->upper_z-parent->lower_z;
      vfloat4 childArea = sizeX*(sizeY + sizeZ) + sizeY*sizeZ;
      
      /*! get node bounds */
      BBox<vfloat4> child1_0,child1_1,child1_2,child1_3;
      parent->bounds(child1_0,child1_1,child1_2,child1_3);
      
      /*! Find best rotation. We pick a first child (child1) and a sub-child 
	(child2child) of a different second child (child2), and swap child1 
	and child2child. We perform the best such swap. */
      float bestArea = 0;
      size_t bestChild1 = -1, bestChild2 = -1, bestChild2Child = -1;
      for (size_t c2=0; c2<4; c2++)
      {
	/*! ignore leaf nodes as we cannot descent into them */
	if (parent->child(c2).isBarrier()) continue;
	if (parent->child(c2).isLeaf()) continue;
	Node* child2 = parent->child(c2).node();
	
	/*! transpose child bounds */
	BBox<vfloat4> child2c0,child2c1,child2c2,child2c3;
	child2->bounds(child2c0,child2c1,child2c2,child2c3);
	
	/*! put child1_0 at each child2 position */
	float cost00 = halfArea3f(merge(child1_0,child2c1,child2c2,child2c3));
	float cost01 = halfArea3f(merge(child2c0,child1_0,child2c2,child2c3));
	float cost02 = halfArea3f(merge(child2c0,child2c1,child1_0,child2c3));
	float cost03 = halfArea3f(merge(child2c0,child2c1,child2c2,child1_0));
	vfloat4 cost0 = vfloat4(cost00,cost01,cost02,cost03);
	vfloat4 min0 = vreduce_min(cost0);
	int pos0 = (int)__bsf(movemask(min0 == cost0));
	
	/*! put child1_1 at each child2 position */
	float cost10 = halfArea3f(merge(child1_1,child2c1,child2c2,child2c3));
	float cost11 = halfArea3f(merge(child2c0,child1_1,child2c2,child2c3));
	float cost12 = halfArea3f(merge(child2c0,child2c1,child1_1,child2c3));
	float cost13 = halfArea3f(merge(child2c0,child2c1,child2c2,child1_1));
	vfloat4 cost1 = vfloat4(cost10,cost11,cost12,cost13);
	vfloat4 min1 = vreduce_min(cost1);
	int pos1 = (int)__bsf(movemask(min1 == cost1));
	
	/*! put child1_2 at each child2 position */
	float cost20 = halfArea3f(merge(child1_2,child2c1,child2c2,child2c3));
	float cost21 = halfArea3f(merge(child2c0,child1_2,child2c2,child2c3));
	float cost22 = halfArea3f(merge(child2c0,child2c1,child1_2,child2c3));
	float cost23 = halfArea3f(merge(child2c0,child2c1,child2c2,child1_2));
	vfloat4 cost2 = vfloat4(cost20,cost21,cost22,cost23);
	vfloat4 min2 = vreduce_min(cost2);
	int pos2 = (int)__bsf(movemask(min2 == cost2));
	
	/*! put child1_3 at each child2 position */
	float cost30 = halfArea3f(merge(child1_3,child2c1,child2c2,child2c3));
	float cost31 = halfArea3f(merge(child2c0,child1_3,child2c2,child2c3));
	float cost32 = halfArea3f(merge(child2c0,child2c1,child1_3,child2c3));
	float cost33 = halfArea3f(merge(child2c0,child2c1,child2c2,child1_3));
	vfloat4 cost3 = vfloat4(cost30,cost31,cost32,cost33);
	vfloat4 min3 = vreduce_min(cost3);
	int pos3 = (int)__bsf(movemask(min3 == cost3));
	
	/*! find best other child */
	vfloat4 area0123 = vfloat4(extract<0>(min0),extract<0>(min1),extract<0>(min2),extract<0>(min3)) - vfloat4(childArea[c2]);
	int pos[4] = { pos0,pos1,pos2,pos3 };
	const size_t mbd = BVH4::maxBuildDepth;
	vbool4 valid = vint4(int(depth+1))+cdepth <= vint4(mbd); // only select swaps that fulfill depth constraints
	valid &= vint4(c2) != vint4(step);
	if (none(valid)) continue;
	size_t c1 = select_min(valid,area0123);
	float area = area0123[c1]; 
        if (c1 == c2) continue; // can happen if bounds are NANs
	
	/*! accept a swap when it reduces cost and is not swapping a node with itself */
	if (area < bestArea) {
	  bestArea = area;
	  bestChild1 = c1;
	  bestChild2 = c2;
	  bestChild2Child = pos[c1];
	}
      }
      
      /*! if we did not find a swap that improves the SAH then do nothing */
      if (bestChild1 == size_t(-1)) return 1+reduce_max(cdepth);
      
      /*! perform the best found tree rotation */
      Node* child2 = parent->child(bestChild2).node();
      BVH4::swap(parent,bestChild1,child2,bestChild2Child);
      parent->set(bestChild2,child2->bounds());
      BVH4::compact(parent);
      BVH4::compact(child2);
      
      /*! This returned depth is conservative as the child that was
       *  pulled up in the tree could have been on the critical path. */
      cdepth[bestChild1]++; // bestChild1 was pushed down one level
      return 1+reduce_max(cdepth); 
    }