Ejemplo n.º 1
0
Archivo: BBox.cpp Proyecto: lieff/GIGL
BBox::IntDist BBox::intersect(const rt::Ray& ray) const {
    float t_entr, t_exit, t_y_min, t_y_max, t_z_min, t_z_max;

    const bool sign[3] = {ray.inv_d.x >= 0.0f, ray.inv_d.y >= 0.0f, ray.inv_d.z >= 0.0f};

    t_entr  = (m_bound_pts[1 - sign[0]].x - ray.o.x) * ray.inv_d.x;
    t_exit  = (m_bound_pts[    sign[0]].x - ray.o.x) * ray.inv_d.x;
    t_y_min = (m_bound_pts[1 - sign[1]].y - ray.o.y) * ray.inv_d.y;
    t_y_max = (m_bound_pts[    sign[1]].y - ray.o.y) * ray.inv_d.y;

    if ((t_entr > t_y_max) || (t_y_min > t_exit)) { return BBox::IntDist{}; }

    t_entr  = max(t_entr, t_y_min);
    t_exit  = min(t_exit, t_y_max);

    t_z_min = (m_bound_pts[1 - sign[2]].z - ray.o.z) * ray.inv_d.z;
    t_z_max = (m_bound_pts[    sign[2]].z - ray.o.z) * ray.inv_d.z;

    if ((t_entr > t_z_max) || (t_z_min > t_exit)) { return BBox::IntDist{}; }

    t_entr = max(t_entr, t_z_min);
    t_exit = min(t_exit, t_z_max);

    if (t_entr < ray.t_max && t_exit > ray.t_min) {
        return BBox::IntDist{t_entr, t_exit};
    } else {
        return BBox::IntDist{};
    }
}
Ejemplo n.º 2
0
void DensityField::computePiDensity(const PerspectiveCamera& cam, const Scene& scene) {
    printInfo("Performing fog density preintegration.");
    printInfo("This will take a few seconds. Please wait! :-)");
    const auto& res = m_pi_dens_res = ivec3{cam.resolution(), m_res.z};
    // Allocate storage
    m_pi_dens_data = new float[piDensSize()];
    // Set up render loop
    assert(0 == res.x % PACKET_SZ && 0 == res.y % PACKET_SZ);
    const ivec2 n_packets{cam.resolution() / PACKET_SZ};
    #pragma omp parallel for
    for (int p_j = 0; p_j < n_packets.y; ++p_j)
        for (int p_i = 0; p_i < n_packets.x; ++p_i)
            for (int p_y = 0; p_y < PACKET_SZ; ++p_y)
                for (int p_x = 0; p_x < PACKET_SZ; ++p_x) {
                    const int x{p_x + p_i * PACKET_SZ};
                    const int y{p_y + p_j * PACKET_SZ};
                    // Use pixel center: offset by 0.5
                    rt::Ray ray{cam.getPrimaryRay(x + 0.5f, y + 0.5f)};
                    // Intersect the bounding volume of density field
                    const auto is = m_bbox.intersect(ray);
                    if (is) {
                        // Determine distance to the geometry
                        scene.trace(ray);
                        // Compute parametric ray bounds
                        const float t_min{max(is.entr, 0.0f)};
                        const float t_max{min(is.exit, ray.inters.distance)};
                        // Sample density at interval endpoints
                        const int   n_intervals{res.z * 4};
                        const float dt{(t_max - t_min) / n_intervals};
                        // Perform ray marching
                        float prev_dens{sampleDensity(ray.o + t_min * ray.d)};
                        float dens{0.0f};
                        for (int i = 1; i <= n_intervals; ++i) {
                            // Distance to the end of the interval
                            const float t{t_min + i * dt};
                            const float curr_dens{sampleDensity(ray.o + t * ray.d)};
                            // Use trapezoidal rule for integration
                            dens += 0.5f * (curr_dens + prev_dens);
                            prev_dens = curr_dens;
                            if (2 == i % 4) {
                                // We are in the middle of the camera-space voxel (froxel)
                                const int z{i / 4};
                                m_pi_dens_data[x + y * res.x + z * res.x * res.y] = dens * dt;
                            }
                        }     
                    } else {
                        // Set density to zero along the ray
                        for (int z = 0; z < res.z; ++z) {
                            m_pi_dens_data[x + y * res.x + z * res.x * res.y] = 0.0f;
                        }
                    }
                }
    // Save it to disk
    writePiDens("Assets\\pi_df.3dt");
    // Load data into OpenGL texture
    createPiDensTex();
}
Ejemplo n.º 3
0
inline bool rayAABBIntersection(
        const glm::vec3& origin,
        const glm::vec3& direction,
        const glm::vec3& aabbMin,
        const glm::vec3& aabbMax,
        float& distance)
{
    using glm::max;
    using glm::min;

    // r.dir is unit direction vector of ray
    glm::vec3 dirfrac = 1.0f / direction;

    // lb is the corner of AABB with minimal coordinates - left bottom, rt is maximal corner
    // r.org is origin of ray
    float t1 = (aabbMin.x - origin.x) * dirfrac.x;
    float t2 = (aabbMax.x - origin.x) * dirfrac.x;
    float t3 = (aabbMin.y - origin.y) * dirfrac.y;
    float t4 = (aabbMax.y - origin.y) * dirfrac.y;
    float t5 = (aabbMin.z - origin.z) * dirfrac.z;
    float t6 = (aabbMax.z - origin.z) * dirfrac.z;

    float tmin = max(max(min(t1, t2), min(t3, t4)), min(t5, t6));
    float tmax = min(min(max(t1, t2), max(t3, t4)), max(t5, t6));

    // if tmax < 0, ray (line) is intersecting AABB, but whole AABB is behind us
    if (tmax < 0)
    {
        distance = tmax;
        return false;
    }

    // if tmin > tmax, ray doesn't intersect AABB
    if (tmin > tmax)
    {
        distance = tmax;
        return false;
    }

    distance = tmin;
    return true;
}
Ejemplo n.º 4
0
void GLElementBuffer::loadData(const size_t n_elems, const GLuint* const data,
                               const GLuint offset) {
    m_data_vec.reserve(m_data_vec.size() + n_elems);
    for (auto i = 0; i < n_elems; ++i) {
        const GLuint idx{offset + data[i]};
        m_min_idx = min(m_min_idx, idx);
        m_max_idx = max(m_max_idx, idx);
        m_data_vec.push_back(idx);
    }
    m_is_buffered = false;
}
Ejemplo n.º 5
0
/** Draws a line. */
static void line(double x1, double y1, double x2, double y2, int c) {
    if (x1<0) { 
        if (x2<0) return;
        y1 = (y2*(0-x1) + y1*(x2-0))/(x2-x1);
        x1 = 0;
    }
    if (x2<0) { 
        y2 = (y1*(0-x2) + y2*(x1-0))/(x1-x2);
        x2 = 0;
    }
    if (x1>SCREEN_WIDTH) { 
        if (x2>SCREEN_WIDTH) return;
        y1 = (y2*(SCREEN_WIDTH-x1) + y1*(x2-SCREEN_WIDTH))/(x2-x1);
        x1 = SCREEN_WIDTH;
    }
    if (x2>SCREEN_WIDTH) { 
        y2 = (y1*(SCREEN_WIDTH-x2) + y2*(x1-SCREEN_WIDTH))/(x1-x2);
        x2 = SCREEN_WIDTH;
    }
    
    if (y1<0) { 
        if (y2<0) return;
        x1 = (x2*(0-y1) + x1*(y2-0))/(y2-y1);
        y1 = 0;
    }
    if (y2<0) { 
        x2 = (x1*(0-y2) + x2*(y1-0))/(y1-y2);
        y2 = 0;
    }
    if (y1>SCREEN_HEIGHT) { 
        if (y2>SCREEN_HEIGHT) return;
        x1 = (x2*(SCREEN_HEIGHT-y1) + x1*(y2-SCREEN_HEIGHT))/(y2-y1);
        y1 = SCREEN_HEIGHT;
    }
    if (y2>SCREEN_HEIGHT) { 
        x2 = (x1*(SCREEN_HEIGHT-y2) + x2*(y1-SCREEN_HEIGHT))/(y1-y2);
        y2 = SCREEN_HEIGHT;
    }
    
    int d = (int)(1+max(abs(x1-x2),abs(y1-y2)));
    for (int i=0; i<=d; i++) {
        double x=(x1+(x2-x1)*i/d);
        double y=(y1+(y2-y1)*i/d);
        if (x<SCREEN_WIDTH && y<SCREEN_HEIGHT) pixel(x,y,c);
    }
}
Ejemplo n.º 6
0
DensityField::DensityField(const BBox& bb, const int(&res)[3], const float freq, const float ampl,
                           const PerspectiveCamera& cam, const Scene& scene):
                           m_bbox{bb}, m_res{res[0], res[1], res[2]},
                           m_data{new GLubyte[res[0] * res[1] * res[2]]},
                           m_pi_dens_data{nullptr} {
    // Validate parameters
    assert(m_res.x > 0 && m_res.y > 0 && m_res.z > 0);
    assert(freq > 0.0f && 0.0f < ampl && ampl <= 1.0f);
    // Initialize maximal density
    float max_dens{0.0f};
    // Compute normalization factors
    const float x_norm{1.0f / (m_res.x - 1)};
    const float y_norm{1.0f / (m_res.y - 1)};
    const float z_norm{1.0f / (m_res.z - 1)};
    printInfo("The renderer has been started for the first time.");
    printInfo("Procedurally computing fog density values using simplex noise.");
    // Compute per-pixel noise values
    #pragma omp parallel for
    for (int z = 0; z < m_res[2]; ++z)
    for (int y = 0; y < m_res[1]; ++y)
    for (int x = 0; x < m_res[0]; ++x) {
        const vec3 norm_pos{x * x_norm, y * y_norm, z * z_norm};
        float sum{0.0f};
        float curr_freq{freq};
        float curr_ampl{ampl};
        // Compute value for each octave
        for (int oct = 0; oct < N_OCTAVES; ++oct) {
            // Value in range [-1, 1]
            float val{glm::simplex(curr_freq * norm_pos)};
            // Now mapped to [0, 0.5]
            val = 0.25f * (val + 1.0f);
            // curr_ampl <= 1
            // Therefore, sum is range [0, 1): at most 0.5 + 0.25 + 0.125 + ...
            sum += curr_ampl * val;
            // Double the frequency, half the amplitude
            curr_freq *= 2.0f;
            curr_ampl /= 2.0f;
        }
        const float   dens_val{sum / N_OCTAVES};
        const GLubyte byte_dens{static_cast<GLubyte>(255.0f * dens_val)};
        max_dens = max(max_dens, dens_val);
        m_data[x + y * m_res.x + z * m_res.x * m_res.y] = byte_dens;
    }
    const float inv_max_dens{1.0f / max_dens};
    // Initialize minimal, average, maximal densities
    float min_dens{FLT_MAX}, avg_dens{0.0f};
    max_dens = 0.0f;
    // Linearly rescale the values
    for (int z = 0; z < m_res[2]; ++z)
    for (int y = 0; y < m_res[1]; ++y)
    for (int x = 0; x < m_res[0]; ++x) {
        const GLubyte old_byte_dens{m_data[x + y * m_res.x + z * m_res.x * m_res.y]};
        const float   new_dens{min(old_byte_dens * inv_max_dens / 255.0f, 1.0f)};
        const GLubyte new_byte_dens{static_cast<GLubyte>(255.0f * new_dens)};
        min_dens  = min(min_dens, new_dens);
        max_dens  = max(max_dens, new_dens);
        avg_dens += new_dens;
        m_data[x + y * m_res.x + z * m_res.x * m_res.y] = new_byte_dens;
    }
    #ifndef NDEBUG
        printInfo("Minimal density: %.2f", min_dens);
        printInfo("Maximal density: %.2f", max_dens);
        printInfo("Average density: %.2f", avg_dens / static_cast<float>(m_res.x * m_res.y * m_res.z));
    #endif
    // Save it to disk
    write("Assets\\df.3dt");
    // Load data into OpenGL texture
    createTex();
    // Preintegrate density values along primary rays
    computePiDensity(cam, scene);
}
Ejemplo n.º 7
0
Archivo: BBox.cpp Proyecto: lieff/GIGL
void BBox::extend(const vec3& p) {
    for (auto axis = 0; axis < 3; ++axis) {
        m_bound_pts[0][axis] = min(m_bound_pts[0][axis], p[axis]);
        m_bound_pts[1][axis] = max(m_bound_pts[1][axis], p[axis]);
    }
}