static void trace_pixel(ri_vector_t *radiance, int x, int y) { unsigned char type; double bsdf[3]; ri_ray_t ray; ri_intersection_state_t state; pathnode_t node; ri_vector_t Le; /* first check a ray hits scene object through pixel (x, y) */ ri_vector_copy(&ray.org, cam_pos); sample_pixel(&ray.dir, x, y); ray.thread_num = 0; if (!ri_raytrace(ri_render_get(), &ray, &state)) { /* hits background */ ri_texture_ibl_fetch(radiance, light->texture, ray.dir); return; } node.depth = 2; node.G[0] = 1.0; node.G[1] = 1.0; node.G[2] = 1.0; ri_mem_copy(&node.state, &state, sizeof(ri_intersection_state_t)); ri_vector_copy(&node.indir, ray.dir); // assume that the camera is not located in the transparent object node.interior = 0; trace_path(&node); /* connect the path to the IBL light source */ type = sample_reflection_type(node.state.geom->material); //if (node.interior) printf("???\n"); sample_outdir(&ray.dir, &type, node.interior, node.state.geom->material, node.indir, node.state.Ng); brdf(bsdf, type, &node.state, node.indir, ray.dir, node.state.Ng); node.G[0] *= bsdf[0]; node.G[1] *= bsdf[1]; node.G[2] *= bsdf[2]; ri_vector_copy(&ray.org, node.state.P); light_sample(&Le, ray.org, ray.dir); radiance->f[0] = Le.f[0] * node.G[0]; radiance->f[1] = Le.f[1] * node.G[1]; radiance->f[2] = Le.f[2] * node.G[2]; }
void do_lum(t_obj *obc, t_cod *cor, t_sph *obj_hit, double omeg) { obc->bounce -= 80; if (obc->bri) { normalize(cor->n); normalize(cor->l_x); brdf(cor, obj_hit, obc, omeg); } }
void alsIrradiateSample( VR::VRayContext &rc, DirectionalMessageData *dmd, const VR::Color &diffuse ) { if (dmd->sss_depth >= SSS_MAX_SAMPLES) return; //void *orig_op; //AiStateGetMsgPtr("als_sss_op", &orig_op); // //int als_context = ALS_CONTEXT_NONE; //AiStateGetMsgInt("als_context", &als_context); //AtRay ray; //AtScrSample scrs; // There are a few contexts in which we can be called here: // 1) Intersecting same object with same shader // 2) Intersecting same object with different shader // 3) Intersecting different object with same shader // 4) Intersecting different object with different shader // 5) Called from an indirect ray from another shader while tracing for SSS // 2 and 4 could possibly be because we're running from a layer shader. if we try to evaluate in that context we will simply crash // 5 will cause fireflies so we need to detect this and return // just return if this is a different object. // More elaborate checks may be needed; see VRayFastSSS2 source, considerPointForSSS(). if (rc.parent && rc.rayresult.sb != rc.parent->rayresult.sb) { return; } // if we're in a layered context and running a different shader from the one that's tracing for sss, just return to let the other shader handle it //if (als_context == ALS_CONTEXT_LAYER && (dmd->shader_orig != sg->shader)) //{ // return; //} DiffusionSample& samp = dmd->samples[dmd->sss_depth]; samp.S = (rc.rayresult.wpoint - dmd->Po); samp.r = VR::length(samp.S); samp.Rd.set(0.0f, 0.0f, 0.0f); // The original alSurface line below seems wrong, but looks like has no effect on Arnold; // we probably only want to subtract just the distance from the previous SSS hit to this one. // In the V-Ray version, I'm using the fact that the direction along the SSS ray is a unit // one, so I can just use the hit ray coefficient. // dmd->maxdist -= samp.r; dmd->maxdist -= float(rc.rayresult.wpointCoeff-rc.rayparams.mint); // if we're not using trace sets to explicitly define what objects we want to trace against, then assume we only want to trace against ourselves // or if we're not doing sss in this shader, just continue the ray /* if ((!trace_set_enabled && orig_op != sg->Op) || sssMix == 0.0f) { if (dmd->sss_depth < SSS_MAX_SAMPLES && dmd->maxdist > 0.0f) { AiMakeRay(&ray, AI_RAY_SUBSURFACE, &sg->P, &sg->Rd, dmd->maxdist, sg); AiTrace(&ray, &scrs); } return; }*/ // AiStateSetMsgInt("als_raytype", ALS_RAY_UNDEFINED); // assert(sg->P != dmd->Po); // put normals the right way round VR::Vector Nref = rc.rayresult.normal; matchNormals(Nref, rc.rayresult.gnormal); matchNormals(Nref, rc.rayresult.origNormal); // void* brdf_data = AiOrenNayarMISCreateData(sg, 0.0f); // AiLightsPrepare(sg); VR::Color result_direct(0.0f, 0.0f, 0.0f); VR::Color Rnond(0.0f, 0.0f, 0.0f); bool directional = dmd->directional; // In V-Ray, always compute dipole diffuse reflectance; we use this as approximation // when V-Ray needs to know the diffuse surface color. for (int c = 0; c < dmd->numComponents; ++c) { Rnond += directionalDipole(rc.rayresult.wpoint, rc.rayresult.normal, dmd->Po, dmd->No, rc.rayresult.normal, dmd->No, dmd->sp[c]) * dmd->weights[c]; } // Calculate the direct lighting. ALSIrradiateBRDF brdf(dmd, Rnond, samp, diffuse); result_direct=rc.vray->getSequenceData().directLightManager->eval(rc, brdf); /* while (AiLightsGetSample(sg)) { // get the group assigned to this light from the hash table using the light's pointer int lightGroup = lightGroupMap[sg->Lp]; float diffuse_strength = AiLightGetDiffuse(sg->Lp); // Does not using MIS here get us anything? // AtRGB L = AiEvaluateLightSample(sg, brdf_data, AiOrenNayarMISSample, AiOrenNayarMISBRDF, AiOrenNayarMISPDF); VR::Color L = sg->Li * VR::Max(VR::dotf(sg->Ld, sg->N), 0.0f) * (1.0f/VR::pi()) * sg->we * diffuse_strength; if (L.isBlack()) continue; if (directional) { VR::Color R(0.0f, 0.0f, 0.0f); for (int c=0; c < dmd->numComponents; ++c) { if (samp.r < dmd->sp[c].safe_radius) R += directionalDipole(sg->P, sg->N, dmd->Po, dmd->No, sg->N, dmd->No, dmd->sp[c]) * dmd->weights[c]; else R += directionalDipole(sg->P, sg->N, dmd->Po, dmd->No, sg->Ld, dmd->wo, dmd->sp[c]) * dmd->weights[c]; } L *= R; result_direct += L; vassert(VR::fastfinite(result_direct.sum())); } else { L *= Rnond; result_direct += L; vassert(VR::fastfinite(result_direct.sum())); } }*/ // Calculate the indirect lighting if GI in V-Ray is enabled. VR::Color result_indirect(0.0f, 0.0f, 0.0f); if (rc.vray->getSequenceData().params.gi.indirectOn) { VR::Vector U, V; VR::computeTangentVectors(rc.rayresult.normal, U, V); VR::VRayContext &nrc=rc.newSpawnContext(0, VR::Color(1.0f, 1.0f, 1.0f), VR::RT_INDIRECT | VR::RT_ENVIRONMENT, rc.rayresult.gnormal); for (int i=0; i<1; i++) { float samples[2]; samples[0]=nrc.getDMCValue(); samples[1]=nrc.getDMCValue(); float stheta = sqrtf(float(samples[0])); float phi = float(VR::pi()*2.0f * samples[1]); VR::Vector dir; dir.x = stheta * cosf(phi); dir.y = stheta * sinf(phi); float cs=sqrtf(VR::Max(0.0f, 1.0f - float(samples[0]))); dir.z = cs; dir=dir.x*U+dir.y*V+dir.z*rc.rayresult.normal; nrc.setTracedDir(dir); nrc.rayparams.rayProbability=2.0f*cs; VR::Color giColor=nrc.traceCurrentRay(); VR::Color f; if (directional) { VR::Color R(0.0f, 0.0f, 0.0f); for (int c = 0; c < dmd->numComponents; ++c) { R += directionalDipole(rc.rayresult.wpoint, rc.rayresult.normal, dmd->Po, dmd->No, dir, dmd->wo, dmd->sp[c]) * dmd->weights[c]; } f = R; result_indirect += giColor * R; vassert(VR::fastfinite(result_indirect.sum())); } else { f = Rnond; result_indirect += giColor * Rnond; vassert(VR::fastfinite(result_indirect.sum())); } } nrc.releaseContext(); } // TODO: this is guaranteed to be 1 in every case, right? // result_indirect *= AiSamplerGetSampleInvCount(sampit); samp.Rd = result_direct + result_indirect; vassert(VR::fastfinite(samp.Rd.sum())); samp.N = rc.rayresult.normal; samp.Ng = rc.rayresult.gnormal; samp.P = rc.rayresult.wpoint; dmd->sss_depth++; //AiStateSetMsgInt("als_raytype", ALS_RAY_SSS); // //if (dmd->sss_depth < SSS_MAX_SAMPLES && dmd->maxdist > 0.0f) //{ // // AiMakeRay(&ray, AI_RAY_SUBSURFACE, &sg->P, &sg->Rd, dmd->maxdist, sg); // AiTrace(&ray, &scrs); //} }
static int trace_path(pathnode_t *path) { unsigned char type; /* type of reflection */ int hit; int prev_interior; double bsdf[3]; ri_vector_t outdir; ri_ray_t ray; ri_intersection_state_t next_state; ri_material_t *material; if (path->depth >= MAX_PATH_VERTICES) { return 0; } material = path->state.geom->material; if (!russian_roulette(material)) { return 0; } type = sample_reflection_type(material); prev_interior = path->interior; if (path->interior && !floateq(material->ior, 1.0f)) { /* ray exits from a transparent object */ path->interior = 0; } sample_outdir(&outdir, &type, path->interior, material, path->indir, path->state.Ng); if (type == 'T' && prev_interior) { /* ray enters into a transparent object */ path->interior = 1; } /* find next surface point where ray hits */ ri_vector_copy(&ray.org, path->state.P); ri_vector_copy(&ray.dir, outdir); ray.thread_num = 0; hit = ri_raytrace(ri_render_get(), &ray, &next_state); if (!hit) { return 0; } brdf(bsdf, type, &path->state, path->indir, outdir, path->state.Ng); path->G[0] *= bsdf[0]; path->G[1] *= bsdf[1]; path->G[2] *= bsdf[2]; path->depth++; ri_vector_copy(&path->indir, outdir); //ri_vector_neg(&path->indir); ri_mem_copy(&path->state, &next_state, sizeof(ri_intersection_state_t)); return trace_path(path); }