char embree_occluded(Ray *ray, EmbreeScene *scene) { DISABLE_FPE; //NOTE(Vidar): Embree throws various FPE's rtcOccluded(scene->scene,*reinterpret_cast<RTCRay*>(ray)); ENABLE_FPE; return ray->geomID == 0; }
/* task that renders a single screen tile */ Vec3fa renderPixelStandard(float x, float y, const Vec3fa& vx, const Vec3fa& vy, const Vec3fa& vz, const Vec3fa& p) { /* initialize ray */ RTCRay 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 = 0; /* intersect ray with scene */ rtcIntersect(g_scene,ray); /* shade pixels */ Vec3fa color = Vec3fa(0.0f); if (ray.geomID != RTC_INVALID_GEOMETRY_ID) { Vec3fa diffuse = ray.geomID != 0 ? Vec3fa(0.9f,0.6f,0.5f) : Vec3fa(0.8f,0.0f,0.0f); color = color + diffuse*0.5f; Vec3fa lightDir = normalize(Vec3fa(-1,-1,-1)); Vec3fa Ng = normalize(ray.Ng); #if ENABLE_SMOOTH_NORMALS Vec3fa P = ray.org + ray.tfar*ray.dir; if (ray.geomID > 0) { Vec3fa dPdu,dPdv; int geomID = ray.geomID; { rtcInterpolate(g_scene,geomID,ray.primID,ray.u,ray.v,RTC_VERTEX_BUFFER,nullptr,&dPdu.x,&dPdv.x,3); } Ng = normalize(cross(dPdv,dPdu)); dPdu = dPdu + Ng*displacement_du(P,dPdu); dPdv = dPdv + Ng*displacement_dv(P,dPdv); Ng = normalize(cross(dPdv,dPdu)); } #endif /* initialize shadow ray */ RTCRay shadow; shadow.org = ray.org + ray.tfar*ray.dir; shadow.dir = neg(lightDir); shadow.tnear = 0.001f; shadow.tfar = inf; shadow.geomID = RTC_INVALID_GEOMETRY_ID; shadow.primID = RTC_INVALID_GEOMETRY_ID; shadow.mask = -1; shadow.time = 0; /* trace shadow ray */ rtcOccluded(g_scene,shadow); /* add light contribution */ if (shadow.geomID == RTC_INVALID_GEOMETRY_ID) color = color + diffuse*clamp(-(dot(lightDir,Ng)),0.0f,1.0f); } return color; }
/* task that renders a single screen tile */ Vec3fa renderPixelStandard(float x, float y, const ISPCCamera& camera) { /* initialize ray */ RTCRay ray; ray.org = Vec3fa(camera.xfm.p); ray.dir = Vec3fa(normalize(x*camera.xfm.l.vx + y*camera.xfm.l.vy + camera.xfm.l.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 = 0; /* intersect ray with scene */ rtcIntersect(g_scene,ray); /* shade pixels */ Vec3fa color = Vec3fa(0.0f); if (ray.geomID != RTC_INVALID_GEOMETRY_ID) { /* interpolate diffuse color */ Vec3fa diffuse = Vec3fa(1.0f,0.0f,0.0f); if (ray.geomID > 0) { unsigned int geomID = ray.geomID; { rtcInterpolate(g_scene,geomID,ray.primID,ray.u,ray.v,RTC_USER_VERTEX_BUFFER0,&diffuse.x,nullptr,nullptr,3); } diffuse = 0.5f*diffuse; } /* calculate smooth shading normal */ Vec3fa Ng = normalize(ray.Ng); color = color + diffuse*0.5f; Vec3fa lightDir = normalize(Vec3fa(-1,-1,-1)); /* initialize shadow ray */ RTCRay shadow; shadow.org = ray.org + ray.tfar*ray.dir; shadow.dir = neg(lightDir); shadow.tnear = 0.001f; shadow.tfar = inf; shadow.geomID = 1; shadow.primID = 0; shadow.mask = -1; shadow.time = 0; /* trace shadow ray */ rtcOccluded(g_scene,shadow); /* add light contribution */ if (shadow.geomID) { Vec3fa r = normalize(reflect(ray.dir,Ng)); float s = pow(clamp(dot(r,lightDir),0.0f,1.0f),10.0f); float d = clamp(-dot(lightDir,Ng),0.0f,1.0f); color = color + diffuse*d + 0.5f*Vec3fa(s); } } return color; }
/* renders a single pixel with ambient occlusion shading */ Vec3fa renderPixelAmbientOcclusion(float x, float y, const Vec3fa& vx, const Vec3fa& vy, const Vec3fa& vz, const Vec3fa& p) { /* initialize ray */ RTCRay 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 = 0; /* intersect ray with scene */ rtcIntersect(g_scene,ray); /* return black if nothing hit */ if (ray.geomID == RTC_INVALID_GEOMETRY_ID) return Vec3fa(0.0f); /* calculate hit point */ float intensity = 0; Vec3fa hitPos = ray.org + ray.tfar*ray.dir; /* trace some ambient occlusion rays */ int seed = 34*x+12*y; for (int i=0; i<32; i++) { Vec3fa dir; const float oneOver10000f = 1.f/10000.f; seed = 1103515245 * seed + 12345; dir.x = (seed%10000)*oneOver10000f; seed = 1103515245 * seed + 12345; dir.y = (seed%10000)*oneOver10000f; seed = 1103515245 * seed + 12345; dir.z = (seed%10000)*oneOver10000f; /* initialize shadow ray */ RTCRay shadow; shadow.org = hitPos; shadow.dir = dir; shadow.tnear = 0.001f; shadow.tfar = inf; shadow.geomID = 1; shadow.primID = 0; shadow.mask = -1; shadow.time = 0; /* trace shadow ray */ rtcOccluded(g_scene,shadow); /* add light contribution */ intensity += shadow.geomID; } intensity *= 1.0f/32.0f; /* shade pixel */ return Vec3fa(intensity); }
void instanceOccludedFunc(LazyGeometry* instance, RTCRay& ray, size_t item) { /* create the object if it is not yet created */ if (instance->state != LAZY_VALID) lazyCreate(instance); /* trace ray inside object */ rtcOccluded(instance->object,ray); }
/* task that renders a single screen tile */ Vec3fa renderPixelStandard(float x, float y, const ISPCCamera& camera, RayStats& stats) { /* initialize ray */ RTCRay ray; ray.org = Vec3fa(camera.xfm.p); ray.dir = Vec3fa(normalize(x*camera.xfm.l.vx + y*camera.xfm.l.vy + camera.xfm.l.vz)); ray.tnear = 0.0f; ray.tfar = (float)(inf); ray.geomID = RTC_INVALID_GEOMETRY_ID; ray.primID = RTC_INVALID_GEOMETRY_ID; ray.instID = -1; ray.mask = -1; ray.time = 0; /* intersect ray with scene */ rtcIntersect(g_scene,ray); RayStats_addRay(stats); /* shade pixels */ Vec3fa color = Vec3fa(0.0f); if (ray.geomID != RTC_INVALID_GEOMETRY_ID) { /* calculate shading normal in world space */ Vec3fa Ns = ray.Ng; if (ray.instID != RTC_INVALID_GEOMETRY_ID) Ns = xfmVector(normal_xfm[ray.instID],Ns); Ns = normalize(Ns); /* calculate diffuse color of geometries */ Vec3fa diffuse = Vec3fa(1,1,1); if (ray.instID != RTC_INVALID_GEOMETRY_ID) diffuse = colors[ray.instID][ray.geomID]; color = color + diffuse*0.5; /* initialize shadow ray */ Vec3fa lightDir = normalize(Vec3fa(-1,-1,-1)); RTCRay shadow; shadow.org = ray.org + ray.tfar*ray.dir; shadow.dir = neg(lightDir); shadow.tnear = 0.001f; shadow.tfar = (float)(inf); shadow.geomID = 1; shadow.primID = 0; shadow.mask = -1; shadow.time = 0; /* trace shadow ray */ rtcOccluded(g_scene,shadow); RayStats_addShadowRay(stats); /* add light contribution */ if (shadow.geomID) color = color + diffuse*clamp(-dot(lightDir,Ns),0.0f,1.0f); } return color; }
void instanceOccludedFunc(const Instance* instance, RTCRay& ray, size_t item) { const Vec3f ray_org = ray.org; const Vec3f ray_dir = ray.dir; ray.org = xfmPoint (instance->world2local,ray_org); ray.dir = xfmVector(instance->world2local,ray_dir); rtcOccluded(instance->object,ray); ray.org = ray_org; ray.dir = ray_dir; }
Vec3fa occluded(RTCScene scene, RTCRay2& ray) { ray.geomID = RTC_INVALID_GEOMETRY_ID; ray.primID = RTC_INVALID_GEOMETRY_ID; ray.mask = -1; ray.filter = (RTCFilterFunc) &occlusionFilter; ray.transparency = Vec3fa(1.0f); rtcOccluded(scene,*((RTCRay*)&ray)); // FIXME: use (RTCRay&) cast return ray.transparency; }
/* task that renders a single screen tile */ Vec3fa renderPixelStandard(int x, int y, const Vec3fa& vx, const Vec3fa& vy, const Vec3fa& vz, const Vec3fa& p) { /* initialize ray */ RTCRay ray; ray.org = p; ray.dir = normalize(add(mul(x,vx), mul(y,vy), vz)); ray.tnear = 0.0f; ray.tfar = inf; ray.geomID = RTC_INVALID_GEOMETRY_ID; ray.primID = RTC_INVALID_GEOMETRY_ID; ray.instID = 4; // set default instance ID ray.mask = -1; ray.time = 0; /* intersect ray with scene */ rtcIntersect(g_scene,ray); /* shade pixels */ Vec3f color = Vec3f(0.0f); if (ray.geomID != RTC_INVALID_GEOMETRY_ID) { Vec3f diffuse = Vec3f(0.0f); if (ray.instID == 0) diffuse = colors[ray.instID][ray.primID]; else diffuse = colors[ray.instID][ray.geomID]; color = add(color,mul(diffuse,0.5)); Vec3f lightDir = normalize(Vec3f(-1,-1,-1)); /* initialize shadow ray */ RTCRay shadow; shadow.org = add(ray.org,mul(ray.tfar,ray.dir)); shadow.dir = neg(lightDir); shadow.tnear = 0.001f; shadow.tfar = inf; shadow.geomID = 1; shadow.primID = 0; shadow.mask = -1; shadow.time = 0; /* trace shadow ray */ rtcOccluded(g_scene,shadow); /* add light contribution */ if (shadow.geomID) color = add(color,mul(diffuse,clamp(-dot(lightDir,normalize(ray.Ng)),0.0f,1.0f))); } return color; }
/* task that renders a single screen tile */ Vec3fa renderPixelStandard(float x, float y, const Vec3fa& vx, const Vec3fa& vy, const Vec3fa& vz, const Vec3fa& p) { /* initialize ray */ RTCRay 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.instID = -1; ray.mask = -1; ray.time = 0; /* intersect ray with scene */ rtcIntersect(g_scene,ray); /* shade pixels */ Vec3fa color = Vec3fa(0.0f); if (ray.geomID != RTC_INVALID_GEOMETRY_ID) { Vec3fa diffuse = Vec3fa(1,1,1); if (ray.instID != -1) diffuse = colors[ray.instID][ray.geomID]; color = color + diffuse*0.5; // FIXME: += Vec3fa lightDir = normalize(Vec3fa(-1,-1,-1)); /* initialize shadow ray */ RTCRay shadow; shadow.org = ray.org + ray.tfar*ray.dir; shadow.dir = neg(lightDir); shadow.tnear = 0.001f; shadow.tfar = inf; shadow.geomID = 1; shadow.primID = 0; shadow.mask = -1; shadow.time = 0; /* trace shadow ray */ rtcOccluded(g_scene,shadow); /* add light contribution */ if (shadow.geomID) color = color + diffuse*clamp(-dot(lightDir,normalize(ray.Ng)),0.0f,1.0f); // FIXME: += } return color; }
/* renders a single pixel casting with ambient occlusion */ Vec3fa renderPixelAmbientOcclusion(float x, float y, const Vec3fa& vx, const Vec3fa& vy, const Vec3fa& vz, const Vec3fa& p) { /* initialize ray */ RTCRay 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 = g_debug; /* intersect ray with scene */ rtcIntersect(g_scene,ray); /* shade pixel */ if (ray.geomID == RTC_INVALID_GEOMETRY_ID) return Vec3fa(0.0f); Vec3fa Ng = normalize(ray.Ng); Vec3fa col = Vec3fa(min(1.f,.3f+.8f*abs(dot(Ng,normalize(ray.dir))))); /* calculate hit point */ float intensity = 0; Vec3fa hitPos = ray.org + ray.tfar * ray.dir; #define AMBIENT_OCCLUSION_SAMPLES 64 /* trace some ambient occlusion rays */ int seed = 34*x+12*y; for (int i=0; i<AMBIENT_OCCLUSION_SAMPLES; i++) { Vec3fa dir; const float oneOver10000f = 1.f/10000.f; seed = 1103515245 * seed + 12345; dir.x = (seed%10000)*oneOver10000f; seed = 1103515245 * seed + 12345; dir.y = (seed%10000)*oneOver10000f; seed = 1103515245 * seed + 12345; dir.z = (seed%10000)*oneOver10000f; /* initialize shadow ray */ RTCRay shadow; shadow.org = hitPos; shadow.dir = dir; shadow.tnear = 0.001f; shadow.tfar = inf; shadow.geomID = RTC_INVALID_GEOMETRY_ID; shadow.primID = RTC_INVALID_GEOMETRY_ID; shadow.mask = -1; shadow.time = 0; /* trace shadow ray */ rtcOccluded(g_scene,shadow); /* add light contribution */ if (shadow.geomID == RTC_INVALID_GEOMETRY_ID) intensity += 1.0f; } intensity *= 1.0f/AMBIENT_OCCLUSION_SAMPLES; /* shade pixel */ return col * intensity; }
/* task that renders a single screen tile */ Vec3fa renderPixelStandard(int x, int y, const Vec3fa& vx, const Vec3fa& vy, const Vec3fa& vz, const Vec3fa& p) { float weight = 1.0f; Vec3f color = Vec3f(0.0f); /* initialize ray */ RTCRay2 primary; primary.org = p; primary.dir = normalize(add(mul(x,vx), mul(y,vy), vz)); primary.tnear = 0.0f; primary.tfar = inf; primary.geomID = RTC_INVALID_GEOMETRY_ID; primary.primID = RTC_INVALID_GEOMETRY_ID; primary.mask = -1; primary.time = 0; primary.transparency = 0.0f; while (true) { /* intersect ray with scene */ rtcIntersect(g_scene,*((RTCRay*)&primary)); /* shade pixels */ if (primary.geomID == RTC_INVALID_GEOMETRY_ID) break; float opacity = 1.0f-primary.transparency; Vec3f diffuse = colors[primary.primID]; Vec3f La = mul(diffuse,0.5f); color = add(color,mul(weight*opacity,La)); Vec3f lightDir = normalize(Vec3f(-1,-1,-1)); /* initialize shadow ray */ RTCRay2 shadow; shadow.org = add(primary.org,mul(primary.tfar,primary.dir)); shadow.dir = neg(lightDir); shadow.tnear = 0.001f; shadow.tfar = inf; shadow.geomID = RTC_INVALID_GEOMETRY_ID; shadow.primID = RTC_INVALID_GEOMETRY_ID; shadow.mask = -1; shadow.time = 0; shadow.transparency = 1.0f; /* trace shadow ray */ rtcOccluded(g_scene,*((RTCRay*)&shadow)); /* add light contribution */ if (shadow.geomID) { Vec3f Ll = mul(diffuse,shadow.transparency*clamp(-dot(lightDir,normalize(primary.Ng)),0.0f,1.0f)); color = add(color,mul(weight*opacity,Ll)); } /* shoot transmission ray */ weight *= primary.transparency; primary.tnear = 1.001f*primary.tfar; primary.tfar = inf; primary.geomID = RTC_INVALID_GEOMETRY_ID; primary.primID = RTC_INVALID_GEOMETRY_ID; primary.transparency = 0.0f; } return color; }
/* renders a single pixel casting with ambient occlusion */ Vec3fa ambientOcclusionShading(int x, int y, RTCRay& ray) { RTCRay rays[AMBIENT_OCCLUSION_SAMPLES]; Vec3fa Ng = normalize(ray.Ng); if (dot(ray.dir,Ng) > 0.0f) Ng = neg(Ng); Vec3fa col = Vec3fa(min(1.0f,0.3f+0.8f*abs(dot(Ng,normalize(ray.dir))))); /* calculate hit point */ float intensity = 0; Vec3fa hitPos = ray.org + ray.tfar * ray.dir; RandomSampler sampler; RandomSampler_init(sampler,x,y,0); /* enable only valid rays */ for (int i=0; i<AMBIENT_OCCLUSION_SAMPLES; i++) { /* sample random direction */ Vec2f s = RandomSampler_get2D(sampler); Sample3f dir; dir.v = cosineSampleHemisphere(s); dir.pdf = cosineSampleHemispherePDF(dir.v); dir.v = frame(Ng) * dir.v; /* initialize shadow ray */ RTCRay& shadow = rays[i]; shadow.org = hitPos; shadow.dir = dir.v; bool mask = 1; { // invalidate inactive rays shadow.tnear = mask ? 0.001f : (float)(pos_inf); shadow.tfar = mask ? (float)(inf) : (float)(neg_inf); } shadow.geomID = RTC_INVALID_GEOMETRY_ID; shadow.primID = RTC_INVALID_GEOMETRY_ID; shadow.mask = -1; shadow.time = 0; // FIXME: invalidate inactive rays } RTCIntersectContext context; context.flags = RAYN_FLAGS; /* trace occlusion rays */ #if USE_INTERFACE == 0 rtcOccluded1M(g_scene,&context,rays,AMBIENT_OCCLUSION_SAMPLES,sizeof(RTCRay)); #elif USE_INTERFACE == 1 for (size_t i=0; i<AMBIENT_OCCLUSION_SAMPLES; i++) rtcOccluded(g_scene,rays[i]); #else for (size_t i=0; i<AMBIENT_OCCLUSION_SAMPLES; i++) rtcOccluded1M(g_scene,&context,&rays[i],1,sizeof(RTCRay)); #endif /* accumulate illumination */ for (int i=0; i<AMBIENT_OCCLUSION_SAMPLES; i++) { if (rays[i].geomID == RTC_INVALID_GEOMETRY_ID) intensity += 1.0f; } /* shade pixel */ return col * (intensity/AMBIENT_OCCLUSION_SAMPLES); }
/* task that renders a single screen tile */ Vec3fa renderPixelStandard(float x, float y, const ISPCCamera& camera, RayStats& stats) { float weight = 1.0f; Vec3fa color = Vec3fa(0.0f); /* initialize ray */ RTCRay2 primary; primary.org = Vec3fa(camera.xfm.p); primary.dir = Vec3fa(normalize(x*camera.xfm.l.vx + y*camera.xfm.l.vy + camera.xfm.l.vz)); primary.tnear = 0.0f; primary.tfar = (float)(inf); primary.geomID = RTC_INVALID_GEOMETRY_ID; primary.primID = RTC_INVALID_GEOMETRY_ID; primary.mask = -1; primary.time = 0; primary.transparency = 0.0f; while (true) { /* intersect ray with scene */ rtcIntersect(g_scene,*((RTCRay*)&primary)); RayStats_addRay(stats); /* shade pixels */ if (primary.geomID == RTC_INVALID_GEOMETRY_ID) break; float opacity = 1.0f-primary.transparency; Vec3fa diffuse = colors[primary.primID]; Vec3fa La = diffuse*0.5f; color = color + weight*opacity*La; Vec3fa lightDir = normalize(Vec3fa(-1,-1,-1)); /* initialize shadow ray */ RTCRay2 shadow; shadow.org = primary.org + primary.tfar*primary.dir; shadow.dir = neg(lightDir); shadow.tnear = 0.001f; shadow.tfar = (float)(inf); shadow.geomID = RTC_INVALID_GEOMETRY_ID; shadow.primID = RTC_INVALID_GEOMETRY_ID; shadow.mask = -1; shadow.time = 0; shadow.transparency = 1.0f; shadow.firstHit = 0; shadow.lastHit = 0; /* trace shadow ray */ rtcOccluded(g_scene,*((RTCRay*)&shadow)); RayStats_addShadowRay(stats); /* add light contribution */ if (shadow.geomID) { Vec3fa Ll = diffuse*shadow.transparency*clamp(-dot(lightDir,normalize(primary.Ng)),0.0f,1.0f); color = color + weight*opacity*Ll; } /* shoot transmission ray */ weight *= primary.transparency; primary.tnear = 1.001f*primary.tfar; primary.tfar = (float)(inf); primary.geomID = RTC_INVALID_GEOMETRY_ID; primary.primID = RTC_INVALID_GEOMETRY_ID; primary.transparency = 0.0f; } 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; }
extern "C" void ispcOccluded1 (RTCScene scene, RTCRay& ray) { rtcOccluded(scene,ray); }
/* task that renders a single screen tile */ Vec3fa renderPixelStandard(float x, float y, const Vec3fa& vx, const Vec3fa& vy, const Vec3fa& vz, const Vec3fa& p) { float weight = 1.0f; Vec3f color = Vec3f(0.0f); /* initialize ray */ RTCRay2 primary; primary.org = p; primary.dir = normalize(x*vx + y*vy + vz); primary.tnear = 0.0f; primary.tfar = inf; primary.geomID = RTC_INVALID_GEOMETRY_ID; primary.primID = RTC_INVALID_GEOMETRY_ID; primary.mask = -1; primary.time = 0; primary.transparency = 0.0f; while (true) { /* intersect ray with scene */ rtcIntersect(g_scene,*((RTCRay*)&primary)); // FIXME: use (RTCRay&) cast /* shade pixels */ if (primary.geomID == RTC_INVALID_GEOMETRY_ID) break; float opacity = 1.0f-primary.transparency; Vec3f diffuse = colors[primary.primID]; Vec3f La = diffuse*0.5f; color = color + weight*opacity*La; // FIXME: += Vec3f lightDir = normalize(Vec3f(-1,-1,-1)); /* initialize shadow ray */ RTCRay2 shadow; shadow.org = primary.org + primary.tfar*primary.dir; shadow.dir = neg(lightDir); shadow.tnear = 0.001f; shadow.tfar = inf; shadow.geomID = RTC_INVALID_GEOMETRY_ID; shadow.primID = RTC_INVALID_GEOMETRY_ID; shadow.mask = -1; shadow.time = 0; shadow.transparency = 1.0f; /* trace shadow ray */ rtcOccluded(g_scene,*((RTCRay*)&shadow)); // FIXME: use (RTCRay&) cast /* add light contribution */ if (shadow.geomID) { Vec3f Ll = diffuse*shadow.transparency*clamp(-dot(lightDir,normalize(primary.Ng)),0.0f,1.0f); color = color + weight*opacity*Ll; // FIXME: += } /* shoot transmission ray */ weight *= primary.transparency; primary.tnear = 1.001f*primary.tfar; primary.tfar = inf; primary.geomID = RTC_INVALID_GEOMETRY_ID; primary.primID = RTC_INVALID_GEOMETRY_ID; primary.transparency = 0.0f; } return color; }
Color vplIntegrator::Li(LightPath& lightPath, const Ref<BackendScene>& scene, IntegratorState& state) { /*! Traverse ray. */ DifferentialGeometry dg; //scene->intersector->intersect(lightPath.lastRay); rtcIntersect(scene->scene,(RTCRay&)lightPath.lastRay); scene->postIntersect(lightPath.lastRay,dg); state.numRays++; Color L = zero; const Vector3f wo = -lightPath.lastRay.dir; BRDFType directLightingBRDFTypes = (BRDFType)(ALL); /*! 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); /*! 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->vpls.size(); i++) { LightSample ls; ls.L = scene->vpls[i].sample(dg, ls.wi, ls.tMax); /*! 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, ALL); 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); TIMESTART(stats.atomic.timeRT,rt0); rtcOccluded(scene->scene,(RTCRay&)shadowRay); TIMESTOP(stats.atomic.timeRT,rt0); state.numRays++; if (shadowRay) continue; /*! Evaluate BRDF. */ L += ls.L * brdf * rcp(ls.wi.pdf); } } return L; }