void ClosurePrimitive::sample_cos_hemisphere (const Vec3 &N, const Vec3 &omega_out, float randu, float randv, Vec3 &omega_in, float &pdf) { // Default closure BSDF implementation: uniformly sample // cosine-weighted hemisphere above the point. to_unit_disk (randu, randv); float costheta = sqrtf (std::max(1 - randu * randu - randv * randv, 0.0f)); Vec3 T, B; make_orthonormals (N, T, B); omega_in = randu * T + randv * B + costheta * N; pdf = costheta * (float) M_1_PI; }
void ClosurePrimitive::sample_uniform_hemisphere (const Vec3 &N, const Vec3 &omega_out, float randu, float randv, Vec3 &omega_in, float &pdf) { float z = randu; float r = sqrtf(std::max(0.f, 1.f - z*z)); float phi = 2.f * M_PI * randv; float x = r * cosf(phi); float y = r * sinf(phi); Vec3 T, B; make_orthonormals (N, T, B); omega_in = x * T + y * B + z * N; pdf = 0.5f * (float) M_1_PI; }
// set up the filter matrix static void gabor_setup_filter (const Dual2<Vec3> &P, GaborParams &gp) { // Make texture-space normal, tangent, bitangent Vec3 n, t, b; n = P.dx().cross (P.dy()); // normal to P if (n.dot(n) < 1.0e-6f) { /* length of deriv < 1/1000 */ // No way to do filter if we have no derivs, and no reason to // do it if it's too small to have any effect. gp.do_filter = false; return; // we won't need anything else if filtering is off } make_orthonormals (n, t, b); // Rotations from tangent<->texture space Matrix33 Mtex_to_tan = make_matrix33_cols (t, b, n); // M3_local Matrix33 Mscreen_to_tex = make_matrix33_cols (P.dx(), P.dy(), Vec3(0.0f,0.0f,0.0f)); Matrix33 Mscreen_to_tan = Mscreen_to_tex * Mtex_to_tan; // M3_scr_tan Matrix22 M_scr_tan (Mscreen_to_tan[0][0], Mscreen_to_tan[0][1], Mscreen_to_tan[1][0], Mscreen_to_tan[1][1]); float sigma_f_scr = 0.5f; Matrix22 Sigma_f_scr (sigma_f_scr * sigma_f_scr, 0.0f, 0.0f, sigma_f_scr * sigma_f_scr); Matrix22 M_scr_tan_t = M_scr_tan.transposed(); Matrix22 Sigma_f_tan = M_scr_tan_t * Sigma_f_scr * M_scr_tan; gp.N = n; gp.filter = Sigma_f_tan; gp.det_filter = determinant(Sigma_f_tan); gp.local = Mtex_to_tan; if (gp.det_filter < 1.0e-18f) { gp.do_filter = false; // Turn off filtering when tiny values will lead to numerical // errors later if we filter. Yes, it's kind of arbitrary. } }