static Vector hemisphereSample(const Vector& normal) { Random& rnd = getRandomGen(); double u = rnd.randdouble(); double v = rnd.randdouble(); double theta = 2 * PI * u; double phi = acos(2 * v - 1); Vector vec( cos(theta) * sin(phi), cos(phi), sin(theta) * sin(phi) ); if (dot(vec, normal) < 0) vec = -vec; return vec; }
Color Refl::shade(const Ray& ray, const IntersectionInfo& info) { Vector n = faceforward(ray.dir, info.normal); if (glossiness == 1) { Ray newRay = ray; newRay.start = info.ip + n * 0.000001; newRay.dir = reflect(ray.dir, n); newRay.depth++; return raytrace(newRay) * multiplier; } else { Random& rnd = getRandomGen(); Color result(0, 0, 0); int count = numSamples; if (ray.depth > 0) count = 2; for (int i = 0; i < count; i++) { Vector a, b; orthonormalSystem(n, a, b); double x, y, scaling; rnd.unitDiscSample(x, y); // scaling = tan((1 - glossiness) * PI/2); x *= scaling; y *= scaling; Vector modifiedNormal = n + a * x + b * y; Ray newRay = ray; newRay.start = info.ip + n * 0.000001; newRay.dir = reflect(ray.dir, modifiedNormal); newRay.depth++; result += raytrace(newRay) * multiplier; } return result / count; } }
void RectLight::getNthSample(int sampleIdx, const Vector& hitPos, Vector& samplePos, Color& color) { Random& rnd = getRandomGen(); // stratified sampling: subdivide the unit square into xSubd * ySubd subrectangles // and take a random points from each one of them. I.e., getNthSample() gets a random sample // from one of those subrectangles. The subrectangle in question is determined by sampleIdx. float x = (sampleIdx % xSubd + rnd.randfloat()) / (float) xSubd; float y = (sampleIdx / xSubd + rnd.randfloat()) / (float) ySubd; // create the sample in local space - in the (-0.5, 0, -0.5) -- (0.5, 0, 0.5) square Vector sample(x - 0.5, 0, y - 0.5); samplePos = T.transformPoint(sample); // transform the sample into world space // transform the point that is to be shaded into local space first Vector hitPos_LS = IT.transformPoint(hitPos); if (hitPos_LS.y > 0) { color.makeZero(); // point is behind the light - unilluminated. } else { // otherwise, return light color, attenuated by the angle of incidence // (the cosine between the light's direction and the normed ray toward the hitpos) color = this->col * float((area * dot(Vector(0, -1, 0), hitPos_LS) / hitPos_LS.length())); } }
Random& getRandomGen() { return getRandomGen(SDL_ThreadID()); }