/* non diffuse first shot */ #include "mcradP.h" #include "edf.h" #include "statistics.h" #include "scene.h" #include "localline.h" #include "render.h" static struct LIGHTSOURCETABLE { PATCH *patch; double flux; } *lights; static int nrlights, nrsamples; static double totalflux; static void InitLight(struct LIGHTSOURCETABLE* light, PATCH *l, double flux) { light->patch = l; light->flux = flux; } static void MakeLightSourceTable(void) { int i=0; totalflux = 0.; nrlights = nrlightsources; lights = (struct LIGHTSOURCETABLE*)Alloc(nrlights * sizeof(struct LIGHTSOURCETABLE)); ForAllPatches(l, LightSourcePatches) { COLOR emitted_rad = PatchAverageEmittance(l, ALL_COMPONENTS); double flux = M_PI * l->area * COLORSUMABSCOMPONENTS(emitted_rad); totalflux += flux; InitLight(&lights[i], l, flux); i++; } EndForAll; ForAllPatches(P, Patches) { CLEARCOEFFICIENTS(RAD(P), BAS(P)); CLEARCOEFFICIENTS(UNSHOT_RAD(P), BAS(P)); CLEARCOEFFICIENTS(RECEIVED_RAD(P), BAS(P)); COLORCLEAR(SOURCE_RAD(P)); } EndForAll; } static void NextLightSample(PATCH* patch, double* zeta) { double *xi = Sample4D(RAY_INDEX(patch)++); if (patch->nrvertices == 3) { double u = xi[0], v = xi[1]; FoldSampleF(&u, &v); zeta[0] = u; zeta[1] = v; } else { zeta[0] = xi[0]; zeta[1] = xi[1]; } zeta[2] = xi[2]; zeta[3] = xi[3]; } static RAY SampleLightRay(PATCH* patch, COLOR *emitted_rad, double *point_selection_pdf, double *dir_selection_pdf) { RAY ray; do { double zeta[4]; HITREC hit; NextLightSample(patch, zeta); PatchUniformPoint(patch, zeta[0], zeta[1], &ray.pos); InitHit(&hit, patch, (GEOM*)0, &ray.pos, &patch->normal, patch->surface->material, 0.); ray.dir = EdfSample(patch->surface->material->edf, &hit, ALL_COMPONENTS, zeta[2], zeta[3], emitted_rad, dir_selection_pdf); } while (*dir_selection_pdf == 0.); /* TODO: the following is only correct if no rejections would result in the */ /* loop above, i.o.w. the surface is not textured, or it is textured, but there */ /* are no areas that are non-selfemitting. */ *point_selection_pdf = 1./patch->area; /* uniform area sampling */ return ray; } static void SampleLight(struct LIGHTSOURCETABLE* light, double light_selection_pdf) { COLOR rad; double point_selection_pdf, dir_selection_pdf; RAY ray = SampleLightRay(light->patch, &rad, &point_selection_pdf, &dir_selection_pdf); HITREC hitstore, *hit; mcr.traced_rays ++; hit = McrShootRay(light->patch, &ray, &hitstore); if (hit) { double pdf = light_selection_pdf * point_selection_pdf * dir_selection_pdf; double outcos = VECTORDOTPRODUCT(ray.dir, light->patch->normal); COLOR rcvrad, Rd = REFLECTANCE(hit->patch); COLORSCALE((outcos/(M_PI * hit->patch->area * pdf * nrsamples)), rad, rcvrad); COLORPROD(Rd, rcvrad, rcvrad); COLORADD(RAD(hit->patch)[0], rcvrad, RAD(hit->patch)[0]); COLORADD(UNSHOT_RAD(hit->patch)[0], rcvrad, UNSHOT_RAD(hit->patch)[0]); COLORADD(SOURCE_RAD(hit->patch), rcvrad, SOURCE_RAD(hit->patch)); } } static void SampleLightSources(int nr_samples) { double rnd = drand48(); int count = 0, i; double p_cumul = 0.; nrsamples = nr_samples; fprintf(stderr, "Shooting %d light rays ", nrsamples); fflush(stderr); for (i=0; iarea, UNSHOT_RAD(P)[0], mcr.unshot_flux); COLORADDSCALED(mcr.total_flux, M_PI*P->area, RAD(P)[0], mcr.total_flux); #ifdef IDMCR COLORADDSCALED(mcr.imp_unshot_flux, M_PI*P->area*(IMP(P)-SOURCE_IMP(P)), UNSHOT_RAD(P)[0], mcr.imp_unshot_flux); mcr.unshot_ymp += P->area * fabs(UNSHOT_IMP(P)); mcr.total_ymp += P->area * IMP(P); mcr.source_ymp += P->area * SOURCE_IMP(P); #endif McrPatchComputeNewColor(P); } EndForAll; } void DoNonDiffuseFirstShot(void) { MakeLightSourceTable(); SampleLightSources(mcr.initial_ls_samples * nrlights); Summarize(); RenderScene(); }