void sun_lightmap::add(sun_lightmap::rays& r, float raylen, yaw_pitch dir2) const { const vector half(0.5, 0.5, 0.5); for (int d(0); d < 6; ++d) { vector normal(dir_vector[d]); vector origin(half + normal * 0.6f); vector dir(from_spherical(dir2.x, dir2.y)); float weight(dot_prod(dir, normal)); if (weight > 0) r[d].add(voxel_raycast(origin, origin + dir * raylen), weight); } }
ambient_occlusion_lightmap::rays ambient_occlusion_lightmap::precalc (float ambient_raylen, unsigned int count) const { rays result; vector center (0.5f, 0.5f, 0.5f); for (auto v : golden_spiral(count)) { for (int i (0); i < 5; ++i) { vector normal (dir_vector[i]); // Weight is calculated according to Lambert's cosine law: // intensity = cos theta = a . b (for unit vectors) float weight (dot_prod(v, normal)); if (weight <= 0) continue; // The ray's origin is set to somewhat above the center of the // surface. (Not too close: this darkens corners too much.) auto origin (center + normal * 0.8f); auto dir (v * ambient_raylen); result[i].add(voxel_raycast(origin, origin + dir), weight); } } float max (0); for (int i(0); i < 5; ++i) { if (result[i].weight > max) max = result[i].weight; } max = 1.0f / max; for (int i(0); i < 5; ++i) result[i].multiply_weight(max); return result; }