/** * Computes the radiance returned by tracing the ray r. */ void PhotonMapper::trace(const Ray& ray, int depth, const Color& flux) { Intersection is; Color lIndirect = Color(0.0f, 0.0f, 0.0f); if (mScene->intersect(ray, is)){ if (depth != 0){ Hitpoint hp; hitpointBVH.intersect(is, flux); float type = uniform(); float reflectivity = is.mMaterial->getReflectivity(is); float transparency = is.mMaterial->getTransparency(is); if (type <= reflectivity){ trace(is.getReflectedRay(), depth + 1, flux); return; } else if (type - reflectivity <= transparency){ trace(is.getRefractedRay(), depth + 1, flux); return; } } if (depth < maxDepth || uniform() > p_abs){ float theta = acos(sqrt(1 - uniform())); float phi = 2 * M_PI * uniform(); float x = sin(theta) * cos(phi); float y = sin(theta) * sin(phi); float z = cos(theta); Vector3D nvec(1.0f, 0.0f, 0.0f); Vector3D mvec(0.0f, 1.0f, 0.0f); Vector3D W = is.mNormal; W.normalize(); Vector3D U = nvec % W; if (U.length() < 0.01f) U = mvec % W; Vector3D V = W % U; Vector3D dir = x * U + y * V + z * W; Ray ray2; ray2.orig = is.mPosition; ray2.dir = dir; Color addFlux = M_PI * is.mMaterial->evalBRDF(is, ray.dir) * flux * (is.mNormal * dir); if (depth >= maxDepth) addFlux *= abs_factor; trace(ray2, depth + 1, addFlux); } } }
void PhotonMapper::forwardPassRay(Ray ray, int x, int y, float weight, int depth){ Intersection is; if (weight > 0 && depth < maxForwardPassDepth && mScene->intersect(ray, is)){ Hitpoint* hp = new Hitpoint(); hp->pixelX = x; hp->pixelY = y; hp->is = is; hp->radius = startRadius; Color reflectedC, refractedC, emittedC; Material* m = is.mMaterial; float reflectivity = m->getReflectivity(is); float transparency = m->getTransparency(is); float diffuse = (1.0f - reflectivity - transparency)*weight; hp->pixelWeight = (1.0f - reflectivity - transparency) * weight; if (reflectivity > 0.0f) { Ray reflectedRay = is.getReflectedRay(); forwardPassRay(reflectedRay, x, y, reflectivity * weight, depth+1); } if (transparency > 0.0f) { Ray refractedRay = is.getRefractedRay(); forwardPassRay(refractedRay, x, y, transparency * weight, depth+1); } if (diffuse){ for (int i = 0; i < mScene->getNumberOfLights(); ++i){ PointLight* l = mScene->getLight(i); if (!mScene->intersect(is.getShadowRay(l))){ Vector3D lightVec = l->getWorldPosition() - is.mPosition; float d2 = lightVec.length2(); lightVec.normalize(); Color radiance = l->getRadiance(); Color brdf = is.mMaterial->evalBRDF(is, lightVec); float angle = max(lightVec * is.mNormal, 0.0f); hp->directIllumination += radiance * brdf * angle / d2; } } vec.push_back(hp); } } }