Example #1
0
bool Intersector::trace_same_material(
    const ShadingRay&               ray,
    const ShadingPoint&             parent_shading_point,
    const bool                      offset_origin,
    ShadingPoint&                   shading_point) const
{
    if (do_trace_same_material(ray, parent_shading_point, offset_origin, shading_point))
    {
        // do_trace_same_material() intersects only with triangles
        // whose normal points in the same direction as the ray.
        // Triangles are intersected from the inside of the object and
        // shading_point.get_shading_normal() points inside the object.

        // todo: we maybe need a better way to flip the shading normal here.
        const Basis3d& basis = shading_point.get_shading_basis();
        shading_point.set_shading_basis(
            Basis3d(
                -basis.get_normal(),
                -basis.get_tangent_u(),
                 basis.get_tangent_v()));

        return true;
    }

    return false;
}
Example #2
0
void ShadingEngine::shade_environment(
    SamplingContext&        sampling_context,
    const ShadingContext&   shading_context,
    const ShadingPoint&     shading_point,
    ShadingResult&          shading_result) const
{
    // Retrieve the environment shader of the scene.
    const EnvironmentShader* environment_shader =
        shading_point.get_scene().get_environment()->get_environment_shader();

    if (environment_shader)
    {
        // There is an environment shader: execute it.
        InputEvaluator input_evaluator(shading_context.get_texture_cache());
        const ShadingRay& ray = shading_point.get_ray();
        const Vector3d direction = normalize(ray.m_dir);
        environment_shader->evaluate(
            input_evaluator,
            direction,
            shading_result);

        // Set environment shader AOV.
        shading_result.set_entity_aov(*environment_shader);
    }
    else
    {
        // No environment shader: shade as transparent black.
        shading_result.set_main_to_transparent_black_linear_rgba();
        shading_result.set_aovs_to_transparent_black_linear_rgba();
    }
}
Example #3
0
bool Intersector::trace(
    const ShadingRay&   ray,
    ShadingPoint&       shading_point,
    const ShadingPoint* parent_shading_point) const
{
    assert(shading_point.m_scene == 0);
    assert(shading_point.hit() == false);
    assert(parent_shading_point == 0 || parent_shading_point != &shading_point);
    assert(parent_shading_point == 0 || parent_shading_point->hit());

    // Update ray casting statistics.
    ++m_ray_count;

    // Initialize the shading point.
    shading_point.m_region_kit_cache = &m_region_kit_cache;
    shading_point.m_tess_cache = &m_tess_cache;
    shading_point.m_scene = &m_trace_context.get_scene();
    shading_point.m_ray = ray;

    // Compute ray info once for the entire traversal.
    const ShadingRay::RayInfoType ray_info(shading_point.m_ray);

    // Refine and offset the previous intersection point.
    if (parent_shading_point &&
        parent_shading_point->hit() &&
        !(parent_shading_point->m_members & ShadingPoint::HasRefinedPoints))
        parent_shading_point->refine_and_offset();

    // Retrieve assembly tree.
    const AssemblyTree& assembly_tree = m_trace_context.get_assembly_tree();

    // Check the intersection between the ray and the assembly tree.
    AssemblyLeafVisitor visitor(
        shading_point,
        assembly_tree,
        m_region_tree_cache,
        m_triangle_tree_cache,
        parent_shading_point
#ifdef FOUNDATION_BSP_ENABLE_TRAVERSAL_STATS
        , m_triangle_bsp_traversal_stats
#endif
        );
    AssemblyLeafIntersector intersector;
    intersector.intersect(
        assembly_tree,
        shading_point.m_ray,
        ray_info,
        visitor
#ifdef FOUNDATION_BVH_ENABLE_TRAVERSAL_STATS
        , m_assembly_bvh_traversal_stats
#endif
        );

    // Detect and report self-intersections.
    if (m_report_self_intersections)
        report_self_intersection(shading_point, parent_shading_point);

    return shading_point.hit();
}
Example #4
0
float BSSRDF::compute_eta(
    const ShadingPoint&     shading_point,
    const float             ior)
{
    const float outside_ior =
        shading_point.is_entering()
            ? shading_point.get_ray().get_current_ior()
            : shading_point.get_ray().get_previous_ior();

    return outside_ior / ior;
}
Example #5
0
double LightSampler::evaluate_pdf(const ShadingPoint& shading_point) const
{
    assert(shading_point.is_triangle_primitive());

    const EmittingTriangleKey triangle_key(
        shading_point.get_assembly_instance().get_uid(),
        shading_point.get_object_instance_index(),
        shading_point.get_region_index(),
        shading_point.get_primitive_index());

    const EmittingTriangle* triangle = m_emitting_triangle_hash_table.get(triangle_key);
    return triangle->m_triangle_prob * triangle->m_rcp_area;
}
Example #6
0
void Intersector::trace_back_sides(
    ShadingRay                          ray,
    ShadingPoint&                       shading_point) const
{
    while (trace(ray, shading_point))
    {
        if (dot(ray.m_dir, shading_point.get_original_shading_normal()) > 0.0)
            break;

        shading_point.refine_and_offset();
        ray.m_org = shading_point.get_offset_point(ray.m_dir);
        shading_point.clear();
    }
}
Example #7
0
        void add_back_lighting(
            const InputValues&      values,
            SamplingContext&        sampling_context,
            const PixelContext&     pixel_context,
            const ShadingContext&   shading_context,
            const ShadingPoint&     shading_point,
            Spectrum&               radiance,
            SpectrumStack&          aovs) const
        {
            const Vector3d& p = shading_point.get_point();
            const Vector3d& n = shading_point.get_original_shading_normal();
            const Vector3d& d = shading_point.get_ray().m_dir;

            // Construct a ray perpendicular to the other side of the surface.
            ShadingRay back_ray(shading_point.get_ray());
            back_ray.m_tmax *= norm(d);
            back_ray.m_dir = dot(d, n) > 0.0 ? -n : n;
            back_ray.m_org = p - back_ray.m_tmax * back_ray.m_dir;

            ShadingPoint back_shading_point(shading_point);
            back_shading_point.set_ray(back_ray);

            Spectrum back_radiance(0.0f);
            SpectrumStack back_aovs(aovs.size(), 0.0f);

            // Compute back lighting.
            for (size_t i = 0; i < m_back_lighting_samples; ++i)
            {
                shading_context.get_lighting_engine()->compute_lighting(
                    sampling_context,
                    pixel_context,
                    shading_context,
                    back_shading_point,
                    back_radiance,
                    back_aovs);
            }

            // Apply translucency factor.
            back_radiance *= values.m_translucency;
            back_aovs *= values.m_translucency;

            // Divide by the number of samples.
            const float rcp_sample_count = 1.0f / static_cast<float>(m_back_lighting_samples);
            back_radiance *= rcp_sample_count;
            back_aovs *= rcp_sample_count;

            // Add back lighting contribution.
            radiance += back_radiance;
            aovs += back_aovs;
        }
Example #8
0
    void do_compute_lighting(
        SamplingContext&        sampling_context,
        const ShadingContext&   shading_context,
        const ShadingPoint&     shading_point,
        Spectrum&               radiance,               // output radiance, in W.sr^-1.m^-2
        SpectrumStack&          aovs)
    {
        PathVisitor path_visitor(
            m_params,
            m_light_sampler,
            sampling_context,
            shading_context,
            shading_point.get_scene(),
            radiance,
            aovs);

        PathTracer<PathVisitor, false> path_tracer(     // false = not adjoint
            path_visitor,
            m_params.m_rr_min_path_length,
            m_params.m_max_path_length,
            shading_context.get_max_iterations());

        const size_t path_length =
            path_tracer.trace(
                sampling_context,
                shading_context,
                shading_point);

        // Update statistics.
        ++m_path_count;
        m_path_length.insert(path_length);
    }
Example #9
0
void BSDF::evaluate_inputs(
    InputEvaluator&     input_evaluator,
    const ShadingPoint& shading_point,
    const size_t        offset) const
{
    input_evaluator.evaluate(get_inputs(), shading_point.get_uv(0), offset);
}
Example #10
0
void Tracer::evaluate_alpha(
    const Material&     material,
    const ShadingPoint& shading_point,
    Alpha&              alpha) const
{
    // Init to fully opaque.
    alpha.set(1.0f);

    // Evaluate the alpha map at the shading point.
    if (const Source* alpha_map = material.get_alpha_map())
    {
        alpha_map->evaluate(
            m_texture_cache,
            shading_point.get_uv(0),
            alpha);
    }

#ifdef WITH_OSL
    if (const ShaderGroup* sg = material.get_osl_surface())
    {
        if (sg->has_transparency())
        {
            Alpha a;
            m_shadergroup_exec.execute_transparency(
                *sg,
                shading_point,
                a);

            alpha *= a;
        }
    }
#endif
}
Example #11
0
        void apply_aerial_perspective(
            const InputValues&      values,
            const ShadingContext&   shading_context,
            const PixelContext&     pixel_context,
            const ShadingPoint&     shading_point,
            ShadingResult&          shading_result) const
        {
            Spectrum sky_color;

            if (m_aerial_persp_mode == AerialPerspSkyColor)
                sky_color = values.m_aerial_persp_sky_color;
            else
            {
                // Retrieve the environment shader of the scene.
                const Scene& scene = shading_point.get_scene();
                const EnvironmentShader* environment_shader =
                    scene.get_environment()->get_environment_shader();

                if (environment_shader)
                {
                    // Execute the environment shader to obtain the sky color in the direction of the ray.
                    InputEvaluator input_evaluator(shading_context.get_texture_cache());
                    const ShadingRay& ray = shading_point.get_ray();
                    const Vector3d direction = normalize(ray.m_dir);
                    ShadingResult sky;
                    environment_shader->evaluate(
                        shading_context,
                        pixel_context,
                        input_evaluator,
                        direction,
                        sky);
                    sky_color = sky.m_main.m_color;
                }
                else sky_color.set(0.0f);
            }

            // Compute the blend factor.
            const double d = shading_point.get_distance() * m_aerial_persp_rcp_distance;
            const double k = m_aerial_persp_intensity * exp(d);
            const double blend = min(k, 1.0);

            // Blend the shading result and the sky color.
            sky_color *= static_cast<float>(blend);
            shading_result.m_main.m_color *= static_cast<float>(1.0 - blend);
            shading_result.m_main.m_color += sky_color;
        }
void OSLShaderGroupExec::do_execute(
    const ShaderGroup&              shader_group,
    const ShadingPoint&             shading_point,
    const VisibilityFlags::Type     ray_flags) const
{
    assert(m_osl_shading_context);
    assert(m_osl_thread_info);

    shading_point.initialize_osl_shader_globals(
        shader_group,
        ray_flags,
        m_osl_shading_system.renderer());

    m_osl_shading_system.execute(
        m_osl_shading_context,
        *reinterpret_cast<OSL::ShaderGroup*>(shader_group.osl_shader_group()),
        shading_point.get_osl_shader_globals());
}
void OSLShaderGroupExec::choose_bsdf_closure_shading_basis(
    const ShadingPoint&             shading_point,
    const Vector2f&                 s) const
{
    CompositeSurfaceClosure c(
        Basis3f(shading_point.get_shading_basis()),
        shading_point.get_osl_shader_globals().Ci,
        m_arena);

    float pdfs[CompositeSurfaceClosure::MaxClosureEntries];
    const size_t num_closures = c.compute_pdfs(ScatteringMode::All, pdfs);
    if (num_closures == 0)
        return;

    const size_t index = c.choose_closure(s[1], num_closures, pdfs);
    shading_point.set_shading_basis(
        Basis3d(c.get_closure_shading_basis(index)));
}
void OSLShaderGroupExec::execute_shading(
    const ShaderGroup&              shader_group,
    const ShadingPoint&             shading_point) const
{
    do_execute(
        shader_group,
        shading_point,
        shading_point.get_ray().m_flags);
}
Example #15
0
void BSSRDF::evaluate_inputs(
    const ShadingContext&   shading_context,
    InputEvaluator&         input_evaluator,
    const ShadingPoint&     shading_point,
    const size_t            offset) const
{
    input_evaluator.evaluate(get_inputs(), shading_point.get_uv(0), offset);
    prepare_inputs(input_evaluator.data() + offset);
}
void OSLShaderGroupExec::execute_shading(
    const ShaderGroup&          shader_group,
    const ShadingPoint&         shading_point) const
{
    assert(m_osl_shading_context);
    assert(m_osl_thread_info);

    m_osl_shading_system.execute(
        *m_osl_shading_context,
        *shader_group.shadergroup_ref(),
        shading_point.get_osl_shader_globals());
}
void OSLShaderGroupExec::execute_transparency(
    const ShaderGroup&              shader_group,
    const ShadingPoint&             shading_point,
    Alpha&                          alpha) const
{
    do_execute(
        shader_group,
        shading_point,
        VisibilityFlags::TransparencyRay);

    process_transparency_tree(shading_point.get_osl_shader_globals().Ci, alpha);
}
void OSLShaderGroupExec::execute_transparency(
    const ShaderGroup&  shader_group,
    const ShadingPoint& shading_point,
    Alpha&              alpha,
    float*              holdout) const
{
    // Switch temporary the ray type to Shadow.
    ShadingRay::TypeType saved_type = shading_point.m_ray.m_type;
    shading_point.m_ray.m_type = ShadingRay::ShadowRay;

    m_osl_shading_system.execute(
        *m_osl_shading_context,
        *shader_group.shadergroup_ref(),
        shading_point.get_osl_shader_globals());

    process_transparency_tree(shading_point.get_osl_shader_globals().Ci, alpha);

    if (holdout)
        *holdout = process_holdout_tree(shading_point.get_osl_shader_globals().Ci);

    // Restore the original ray type.
    shading_point.m_ray.m_type = saved_type;
}
Example #19
0
        Color3d update_and_evaluate(
            const ShadingPoint&     shading_point,
            OIIO::TextureSystem&    texture_system)
        {
            for (each<ptr_vector<TextureSeExprFunc> > it = m_functions_x; it; ++it)
                it->set_texture_system(&texture_system);

            const Vector2d& uv = shading_point.get_uv(0);
            m_vars["u"] = Var(uv[0]);
            m_vars["v"] = Var(uv[1]);

            const SeVec3d result = evaluate();
            return Color3d(result[0], result[1], result[2]);
        }
Example #20
0
        Color3d update_and_evaluate(
            const ShadingPoint&     shading_point,
            OIIO::TextureSystem&    texture_system)
        {
            for (each<ptr_vector<TextureSeExprFunc> > i = m_functions_x; i; ++i)
                i->set_texture_system(&texture_system);

            const Vector2d& uv = shading_point.get_uv(0);
            m_u_var.m_val = uv[0];
            m_v_var.m_val = uv[1];

            const SeVec3d result = evaluate();
            return Color3d(result[0], result[1], result[2]);
        }
void OSLShaderGroupExec::execute_bump(
    const ShaderGroup&              shader_group,
    const ShadingPoint&             shading_point,
    const Vector2f&                 s) const
{
    // Choose between BSSRDF and BSDF.
    if (shader_group.has_subsurface() && s[0] < 0.5f)
    {
        do_execute(
            shader_group,
            shading_point,
            VisibilityFlags::SubsurfaceRay);

        CompositeSubsurfaceClosure c(
            Basis3f(shading_point.get_shading_basis()),
            shading_point.get_osl_shader_globals().Ci,
            m_arena);

        // Pick a shading basis from one of the BSSRDF closures.
        if (c.get_closure_count() > 0)
        {
            const size_t index = c.choose_closure(s[1]);
            shading_point.set_shading_basis(
                Basis3d(c.get_closure_shading_basis(index)));
        }
    }
    else
    {
        do_execute(
            shader_group,
            shading_point,
            VisibilityFlags::CameraRay);

        choose_bsdf_closure_shading_basis(shading_point, s);
    }
}
Example #22
0
void Tracer::evaluate_alpha(
    const Material&             material,
    const ShadingPoint&         shading_point,
    Alpha&                      alpha) const
{
    alpha = shading_point.get_alpha();

    // Apply OSL transparency if needed.
    if (const ShaderGroup* sg = material.get_render_data().m_shader_group)
    {
        if (sg->has_transparency())
        {
            Alpha a;
            m_shadergroup_exec.execute_shadow(*sg, shading_point, a);
            alpha *= a;
        }
    }
}
Example #23
0
void compute_ibl_bsdf_sampling(
    SamplingContext&        sampling_context,
    const ShadingContext&   shading_context,
    const EnvironmentEDF&   environment_edf,
    const ShadingPoint&     shading_point,
    const Vector3d&         outgoing,
    const BSDF&             bsdf,
    const void*             bsdf_data,
    const int               bsdf_sampling_modes,
    const size_t            bsdf_sample_count,
    const size_t            env_sample_count,
    Spectrum&               radiance)
{
    assert(is_normalized(outgoing));

    const Vector3d& geometric_normal = shading_point.get_geometric_normal();
    const Basis3d& shading_basis = shading_point.get_shading_basis();

    radiance.set(0.0f);

    for (size_t i = 0; i < bsdf_sample_count; ++i)
    {
        // Sample the BSDF.
        // todo: rendering will be incorrect if the BSDF value returned by the sample() method
        // includes the contribution of a specular component since these are explicitly rejected
        // afterward. We need a mechanism to indicate that we want the contribution of some of
        // the components only.
        Vector3d incoming;
        Spectrum bsdf_value;
        double bsdf_prob;
        const BSDF::Mode bsdf_mode =
            bsdf.sample(
                sampling_context,
                bsdf_data,
                false,              // not adjoint
                true,               // multiply by |cos(incoming, normal)|
                geometric_normal,
                shading_basis,
                outgoing,
                incoming,
                bsdf_value,
                bsdf_prob);

        // Filter scattering modes.
        if (!(bsdf_sampling_modes & bsdf_mode))
            return;

        // Discard occluded samples.
        const double transmission =
            shading_context.get_tracer().trace(
                shading_point,
                incoming,
                ShadingRay::ShadowRay);
        if (transmission == 0.0)
            continue;

        // Evaluate the environment's EDF.
        InputEvaluator input_evaluator(shading_context.get_texture_cache());
        Spectrum env_value;
        double env_prob;
        environment_edf.evaluate(
            input_evaluator,
            incoming,
            env_value,
            env_prob);

        // Apply all weights, including MIS weight.
        if (bsdf_mode == BSDF::Specular)
            env_value *= static_cast<float>(transmission);
        else
        {
            const double mis_weight =
                mis_power2(
                    bsdf_sample_count * bsdf_prob,
                    env_sample_count * env_prob);
            env_value *= static_cast<float>(transmission / bsdf_prob * mis_weight);
        }

        // Add the contribution of this sample to the illumination.
        env_value *= bsdf_value;
        radiance += env_value;
    }

    if (bsdf_sample_count > 1)
        radiance /= static_cast<float>(bsdf_sample_count);
}
Example #24
0
void compute_ibl_bssrdf_sampling(
    SamplingContext&        sampling_context,
    const ShadingContext&   shading_context,
    const EnvironmentEDF&   environment_edf,
    const BSSRDF&           bssrdf,
    const void*             bssrdf_data,
    const ShadingPoint&     incoming_point,
    const ShadingPoint&     outgoing_point,
    const Dual3d&           outgoing,
    const size_t            bssrdf_sample_count,
    const size_t            env_sample_count,
    Spectrum&               radiance)
{
    assert(is_normalized(outgoing.get_value()));

    radiance.set(0.0f);

    sampling_context.split_in_place(2, bssrdf_sample_count);

    for (size_t i = 0; i < bssrdf_sample_count; ++i)
    {
        // Generate a uniform sample in [0,1)^2.
        const Vector2d s = sampling_context.next_vector2<2>();

        // Sample the BSSRDF (hemisphere cosine).
        Vector3d incoming = sample_hemisphere_cosine(s);
        const double cos_in = incoming.y;
        const double bssrdf_prob = cos_in * RcpPi;
        incoming = incoming_point.get_shading_basis().transform_to_parent(incoming);
        if (incoming_point.get_side() == ObjectInstance::BackSide)
            incoming = -incoming;
        assert(is_normalized(incoming));

        // Discard occluded samples.
        const double transmission =
            shading_context.get_tracer().trace(
                incoming_point,
                incoming,
                VisibilityFlags::ShadowRay);
        if (transmission == 0.0)
            continue;

        // Evaluate the BSSRDF.
        Spectrum bssrdf_value;
        bssrdf.evaluate(
            bssrdf_data,
            outgoing_point,
            outgoing.get_value(),
            incoming_point,
            incoming,
            bssrdf_value);

        // Evaluate the environment's EDF.
        InputEvaluator input_evaluator(shading_context.get_texture_cache());
        Spectrum env_value;
        double env_prob;
        environment_edf.evaluate(
            shading_context,
            input_evaluator,
            incoming,
            env_value,
            env_prob);

        // Compute MIS weight.
        const double mis_weight =
            mis_power2(
                bssrdf_sample_count * bssrdf_prob,
                env_sample_count * env_prob);

        // Add the contribution of this sample to the illumination.
        env_value *= static_cast<float>(transmission * cos_in / bssrdf_prob * mis_weight);
        env_value *= bssrdf_value;
        radiance += env_value;
    }

    if (bssrdf_sample_count > 1)
        radiance /= static_cast<float>(bssrdf_sample_count);
}
Example #25
0
void compute_ibl_environment_sampling(
    SamplingContext&        sampling_context,
    const ShadingContext&   shading_context,
    const EnvironmentEDF&   environment_edf,
    const BSSRDF&           bssrdf,
    const void*             bssrdf_data,
    const ShadingPoint&     incoming_point,
    const ShadingPoint&     outgoing_point,
    const Dual3d&           outgoing,
    const size_t            bssrdf_sample_count,
    const size_t            env_sample_count,
    Spectrum&               radiance)
{
    assert(is_normalized(outgoing.get_value()));

    const Basis3d& shading_basis = incoming_point.get_shading_basis();

    radiance.set(0.0f);

    sampling_context.split_in_place(2, env_sample_count);

    for (size_t i = 0; i < env_sample_count; ++i)
    {
        // Generate a uniform sample in [0,1)^2.
        const Vector2d s = sampling_context.next_vector2<2>();

        // Sample the environment.
        InputEvaluator input_evaluator(shading_context.get_texture_cache());
        Vector3d incoming;
        Spectrum env_value;
        double env_prob;
        environment_edf.sample(
            shading_context,
            input_evaluator,
            s,
            incoming,
            env_value,
            env_prob);

        // Cull samples behind the shading surface.
        assert(is_normalized(incoming));
        const double cos_in = dot(incoming, shading_basis.get_normal());
        if (cos_in <= 0.0)
            continue;

        // Discard occluded samples.
        const double transmission =
            shading_context.get_tracer().trace(
                incoming_point,
                incoming,
                VisibilityFlags::ShadowRay);
        if (transmission == 0.0)
            continue;

        // Evaluate the BSSRDF.
        Spectrum bssrdf_value;
        bssrdf.evaluate(
            bssrdf_data,
            outgoing_point,
            outgoing.get_value(),
            incoming_point,
            incoming,
            bssrdf_value);

        // Compute MIS weight.
        const double bssrdf_prob = cos_in * RcpPi;
        const double mis_weight =
            mis_power2(
                env_sample_count * env_prob,
                bssrdf_sample_count * bssrdf_prob);

        // Add the contribution of this sample to the illumination.
        env_value *= static_cast<float>(transmission * cos_in / env_prob * mis_weight);
        env_value *= bssrdf_value;
        radiance += env_value;
    }

    if (env_sample_count > 1)
        radiance /= static_cast<float>(env_sample_count);
}
Example #26
0
void ShadingEngine::shade_hit_point(
    SamplingContext&        sampling_context,
    const PixelContext&     pixel_context,
    const ShadingContext&   shading_context,
    const ShadingPoint&     shading_point,
    ShadingResult&          shading_result) const
{
    // Retrieve the material of the intersected surface.
    const Material* material = shading_point.get_material();

    // Compute the alpha channel of the main output.
    if (material && material->get_alpha_map())
    {
        // There is an alpha map: evaluate it.
        material->get_alpha_map()->evaluate(
            shading_context.get_texture_cache(),
            shading_point.get_uv(0),
            shading_result.m_main.m_alpha);
    }
    else
    {
        // No alpha map: solid sample.
        shading_result.m_main.m_alpha = Alpha(1.0f);
    }

#ifdef WITH_OSL
    if (material && material->get_osl_surface() && material->get_osl_surface()->has_transparency())
    {
        Alpha a;
        shading_context.execute_osl_transparency(
            *material->get_osl_surface(),
            shading_point,
            a);

        shading_result.m_main.m_alpha *= a;
    }
#endif

    if (shading_result.m_main.m_alpha[0] > 0.0f || material->shade_alpha_cutouts())
    {
        // Use the diagnostic surface shader if there is one.
        const SurfaceShader* surface_shader = m_diagnostic_surface_shader.get();

        if (surface_shader == 0)
        {
            if (material == 0)
            {
                // The intersected surface has no material: return solid pink.
                shading_result.set_main_to_opaque_pink_linear_rgba();
                shading_result.set_aovs_to_transparent_black_linear_rgba();
                return;
            }

            // Use the surface shader of the intersected surface.
            surface_shader = material->get_surface_shader();

            if (surface_shader == 0)
            {
                // The intersected surface has no surface shader: return solid pink.
                shading_result.set_main_to_opaque_pink_linear_rgba();
                shading_result.set_aovs_to_transparent_black_linear_rgba();
                return;
            }
        }

        // Execute the surface shader.
        surface_shader->evaluate(
            sampling_context,
            pixel_context,
            shading_context,
            shading_point,
            shading_result);

        // Set AOVs.
        shading_result.set_entity_aov(shading_point.get_assembly());
        shading_result.set_entity_aov(shading_point.get_assembly_instance());
        shading_result.set_entity_aov(shading_point.get_object());
        shading_result.set_entity_aov(shading_point.get_object_instance());
        if (material)
            shading_result.set_entity_aov(*material);
        shading_result.set_entity_aov(*surface_shader);
    }
    else
    {
        // Alpha is zero: shade as transparent black.
        shading_result.set_main_to_transparent_black_linear_rgba();
        shading_result.set_aovs_to_transparent_black_linear_rgba();
    }
}
Example #27
0
void compute_ibl_environment_sampling(
    SamplingContext&        sampling_context,
    const ShadingContext&   shading_context,
    const EnvironmentEDF&   environment_edf,
    const ShadingPoint&     shading_point,
    const Vector3d&         outgoing,
    const BSDF&             bsdf,
    const void*             bsdf_data,
    const int               env_sampling_modes,
    const size_t            bsdf_sample_count,
    const size_t            env_sample_count,
    Spectrum&               radiance)
{
    assert(is_normalized(outgoing));

    const Vector3d& geometric_normal = shading_point.get_geometric_normal();
    const Basis3d& shading_basis = shading_point.get_shading_basis();

    radiance.set(0.0f);

    // todo: if we had a way to know that a BSDF is purely specular, we could
    // immediately return black here since there will be no contribution from
    // such a BSDF.

    sampling_context.split_in_place(2, env_sample_count);

    for (size_t i = 0; i < env_sample_count; ++i)
    {
        // Generate a uniform sample in [0,1)^2.
        const Vector2d s = sampling_context.next_vector2<2>();

        // Sample the environment.
        InputEvaluator input_evaluator(shading_context.get_texture_cache());
        Vector3d incoming;
        Spectrum env_value;
        double env_prob;
        environment_edf.sample(
            input_evaluator,
            s,
            incoming,
            env_value,
            env_prob);

        // Cull samples behind the shading surface.
        assert(is_normalized(incoming));
        const double cos_in = dot(incoming, shading_basis.get_normal());
        if (cos_in < 0.0)
            continue;

        // Discard occluded samples.
        const double transmission =
            shading_context.get_tracer().trace(
                shading_point,
                incoming,
                ShadingRay::ShadowRay);
        if (transmission == 0.0)
            continue;

        // Evaluate the BSDF.
        Spectrum bsdf_value;
        const double bsdf_prob =
            bsdf.evaluate(
                bsdf_data,
                false,                          // not adjoint
                true,                           // multiply by |cos(incoming, normal)|
                geometric_normal,
                shading_basis,
                outgoing,
                incoming,
                env_sampling_modes,
                bsdf_value);
        if (bsdf_prob == 0.0)
            continue;

        // Compute MIS weight.
        const double mis_weight =
            mis_power2(
                env_sample_count * env_prob,
                bsdf_sample_count * bsdf_prob);

        // Add the contribution of this sample to the illumination.
        env_value *= static_cast<float>(transmission / env_prob * mis_weight);
        env_value *= bsdf_value;
        radiance += env_value;
    }

    if (env_sample_count > 1)
        radiance /= static_cast<float>(env_sample_count);
}
Example #28
0
void EDF::evaluate_inputs(
    InputEvaluator&     input_evaluator,
    const ShadingPoint& shading_point) const
{
    input_evaluator.evaluate(get_inputs(), shading_point.get_uv(0));
}
void DiagnosticSurfaceShader::evaluate(
    SamplingContext&        sampling_context,
    const PixelContext&     pixel_context,
    const ShadingContext&   shading_context,
    const ShadingPoint&     shading_point,
    ShadingResult&          shading_result) const
{
    switch (m_shading_mode)
    {
      case Color:
        {
            shading_result.set_main_to_opaque_pink_linear_rgba();

            const Material* material = shading_point.get_material();
            if (material)
            {
                const Material::RenderData& material_data = material->get_render_data();

#ifdef APPLESEED_WITH_OSL
                // Execute the OSL shader if there is one.
                if (material_data.m_shader_group)
                {
                    shading_context.execute_osl_shading(
                        *material_data.m_shader_group,
                        shading_point);
                }
#endif

                if (material_data.m_bsdf)
                {
                    InputEvaluator input_evaluator(shading_context.get_texture_cache());
                    material_data.m_bsdf->evaluate_inputs(
                        shading_context,
                        input_evaluator,
                        shading_point);

                    const Vector3d direction = -normalize(shading_point.get_ray().m_dir);
                    material_data.m_bsdf->evaluate(
                        input_evaluator.data(),
                        false,
                        false,
                        shading_point.get_geometric_normal(),
                        shading_point.get_shading_basis(),
                        direction,
                        direction,
                        ScatteringMode::All,
                        shading_result.m_main.m_color);

                    shading_result.m_color_space = ColorSpaceSpectral;
                }
            }
        }
        break;

      case Coverage:
        shading_result.set_main_to_linear_rgb(Color3f(1.0f));
        break;

      case Barycentric:
        shading_result.set_main_to_linear_rgb(
            vector2_to_color(shading_point.get_bary()));
        break;

      case UV:
        shading_result.set_main_to_linear_rgb(
            uvs_to_color(shading_point.get_uv(0)));
        break;

      case Tangent:
      case Bitangent:
      case ShadingNormal:
        {
#ifdef APPLESEED_WITH_OSL
            const Material* material = shading_point.get_material();
            if (material)
            {
                const Material::RenderData& material_data = material->get_render_data();

                // Execute the OSL shader if there is one.
                if (material_data.m_shader_group)
                {
                    sampling_context.split_in_place(2, 1);
                    shading_context.execute_osl_bump(
                        *material_data.m_shader_group,
                        shading_point,
                        sampling_context.next_vector2<2>());
                }
            }
#endif

            const Vector3d v =
                m_shading_mode == ShadingNormal ? shading_point.get_shading_basis().get_normal() :
                m_shading_mode == Tangent ? shading_point.get_shading_basis().get_tangent_u() :
                shading_point.get_shading_basis().get_tangent_v();

            shading_result.set_main_to_linear_rgb(vector3_to_color(v));
        }
        break;

      case GeometricNormal:
        shading_result.set_main_to_linear_rgb(
            vector3_to_color(shading_point.get_geometric_normal()));
        break;

      case OriginalShadingNormal:
        shading_result.set_main_to_linear_rgb(
            vector3_to_color(shading_point.get_original_shading_normal()));
        break;

      case WorldSpacePosition:
        {
            const Vector3d& p = shading_point.get_point();
            shading_result.set_main_to_linear_rgb(
                Color3f(Color3d(p.x, p.y, p.z)));
        }
        break;

      case Sides:
        shading_result.set_main_to_linear_rgb(
            shading_point.get_side() == ObjectInstance::FrontSide
                ? Color3f(0.0f, 0.0f, 1.0f)
                : Color3f(1.0f, 0.0f, 0.0f));
        break;

      case Depth:
        shading_result.set_main_to_linear_rgb(
            Color3f(static_cast<float>(shading_point.get_distance())));
        break;

      case ScreenSpaceWireframe:
        {
            // Initialize the shading result to the background color.
            shading_result.set_main_to_linear_rgba(Color4f(0.0f, 0.0f, 0.8f, 0.5f));

            if (shading_point.is_triangle_primitive())
            {
                // Film space thickness of the wires.
                const double SquareWireThickness = square(0.00025);

                // Retrieve the time, the scene and the camera.
                const double time = shading_point.get_time().m_absolute;
                const Scene& scene = shading_point.get_scene();
                const Camera& camera = *scene.get_camera();

                // Compute the film space coordinates of the intersection point.
                Vector2d point_ndc;
                camera.project_point(time, shading_point.get_point(), point_ndc);

                // Loop over the triangle edges.
                for (size_t i = 0; i < 3; ++i)
                {
                    // Retrieve the end points of this edge.
                    const size_t j = (i + 1) % 3;
                    const Vector3d vi = shading_point.get_vertex(i);
                    const Vector3d vj = shading_point.get_vertex(j);

                    // Compute the film space coordinates of the edge's end points.
                    Vector2d vi_ndc, vj_ndc;
                    if (!camera.project_segment(time, vi, vj, vi_ndc, vj_ndc))
                        continue;

                    // Compute the film space distance from the intersection point to the edge.
                    const double d = square_distance_point_segment(point_ndc, vi_ndc, vj_ndc);

                    // Shade with the wire's color if the hit point is close enough to the edge.
                    if (d < SquareWireThickness)
                    {
                        shading_result.set_main_to_linear_rgba(Color4f(1.0f));
                        break;
                    }
                }
            }
            else
            {
                assert(shading_point.is_curve_primitive());

                // todo: implement.
            }
        }
        break;

      case WorldSpaceWireframe:
        {
            // Initialize the shading result to the background color.
            shading_result.set_main_to_linear_rgba(Color4f(0.0f, 0.0f, 0.8f, 0.5f));

            if (shading_point.is_triangle_primitive())
            {
                // World space thickness of the wires.
                const double SquareWireThickness = square(0.0015);

                // Retrieve the world space intersection point.
                const Vector3d& point = shading_point.get_point();

                // Loop over the triangle edges.
                for (size_t i = 0; i < 3; ++i)
                {
                    // Retrieve the end points of this edge.
                    const size_t j = (i + 1) % 3;
                    const Vector3d& vi = shading_point.get_vertex(i);
                    const Vector3d& vj = shading_point.get_vertex(j);

                    // Compute the world space distance from the intersection point to the edge.
                    const double d = square_distance_point_segment(point, vi, vj);

                    // Shade with the wire's color if the hit point is close enough to the edge.
                    if (d < SquareWireThickness)
                    {
                        shading_result.set_main_to_linear_rgba(Color4f(1.0f));
                        break;
                    }
                }
            }
            else
            {
                assert(shading_point.is_curve_primitive());

                // todo: implement.
            }
        }
        break;

      case AmbientOcclusion:
        {
            // Compute the occlusion.
            const double occlusion =
                compute_ambient_occlusion(
                    sampling_context,
                    sample_hemisphere_uniform<double>,
                    shading_context.get_intersector(),
                    shading_point,
                    m_ao_max_distance,
                    m_ao_samples);

            // Return a gray scale value proportional to the accessibility.
            const float accessibility = static_cast<float>(1.0 - occlusion);
            shading_result.set_main_to_linear_rgb(Color3f(accessibility));
        }
        break;

      case AssemblyInstances:
        shading_result.set_main_to_linear_rgb(
            integer_to_color(shading_point.get_assembly_instance().get_uid()));
        break;

      case ObjectInstances:
        shading_result.set_main_to_linear_rgb(
            integer_to_color(shading_point.get_object_instance().get_uid()));
        break;

      case Regions:
        {
            const uint32 h =
                mix_uint32(
                    static_cast<uint32>(shading_point.get_object_instance().get_uid()),
                    static_cast<uint32>(shading_point.get_region_index()));
            shading_result.set_main_to_linear_rgb(integer_to_color(h));
        }
        break;

      case Primitives:
        {
            const uint32 h =
                mix_uint32(
                    static_cast<uint32>(shading_point.get_object_instance().get_uid()),
                    static_cast<uint32>(shading_point.get_region_index()),
                    static_cast<uint32>(shading_point.get_primitive_index()));
            shading_result.set_main_to_linear_rgb(integer_to_color(h));
        }
        break;

      case Materials:
        {
            const Material* material = shading_point.get_material();
            if (material)
                shading_result.set_main_to_linear_rgb(integer_to_color(material->get_uid()));
            else shading_result.set_main_to_opaque_pink_linear_rgba();
        }
        break;

      case RaySpread:
        {
            const ShadingRay& ray = shading_point.get_ray();
            if (!ray.m_has_differentials)
                break;

            const Material* material = shading_point.get_material();
            if (material)
            {
                const Material::RenderData& material_data = material->get_render_data();

#ifdef APPLESEED_WITH_OSL
                // Execute the OSL shader if there is one.
                if (material_data.m_shader_group)
                {
                    shading_context.execute_osl_shading(
                        *material_data.m_shader_group,
                        shading_point);
                }
#endif

                if (material_data.m_bsdf)
                {
                    const Dual3d outgoing(
                        -ray.m_dir,
                        ray.m_dir - ray.m_rx.m_dir,
                        ray.m_dir - ray.m_ry.m_dir);

                    InputEvaluator input_evaluator(shading_context.get_texture_cache());
                    material_data.m_bsdf->evaluate_inputs(
                        shading_context,
                        input_evaluator,
                        shading_point);
                    const void* bsdf_data = input_evaluator.data();

                    BSDFSample sample(shading_point, outgoing);
                    material_data.m_bsdf->sample(
                        sampling_context,
                        bsdf_data,
                        false,
                        false,
                        sample);

                    if (!sample.m_incoming.has_derivatives())
                        break;

                    // The 3.0 factor is chosen so that ray spread from Lambertian BRDFs is approximately 1.
                    const double spread =
                        max(
                            norm(sample.m_incoming.get_dx()),
                            norm(sample.m_incoming.get_dy())) * 3.0;

                    shading_result.set_main_to_linear_rgb(
                        Color3f(static_cast<float>(spread)));
                }
            }
        }
        break;

      case FacingRatio:
        {
            const Vector3d& normal = shading_point.get_shading_normal();
            const Vector3d& view   = shading_point.get_ray().m_dir;

            const double facing = abs(dot(normal, view));

            shading_result.set_main_to_linear_rgb(
                Color3f(static_cast<float>(facing)));
        }
        break;

      default:
        assert(false);
        shading_result.set_main_to_transparent_black_linear_rgba();
        break;
    }
}
Example #30
0
void EmbreeScene::intersect(ShadingPoint& shading_point) const
{
    RTCIntersectContext context;
    rtcInitIntersectContext(&context);

    RTCRayHit rayhit;
    shading_ray_to_embree_ray(shading_point.get_ray(), rayhit.ray);

    rayhit.hit.geomID = RTC_INVALID_GEOMETRY_ID;

    rtcIntersect1(m_scene, &context, &rayhit);

    if (rayhit.hit.geomID != RTC_INVALID_GEOMETRY_ID)
    {
        assert(rayhit.hit.geomID < m_geometry_container.size());

        const auto& geometry_data = m_geometry_container[rayhit.hit.geomID];
        assert(geometry_data);

        shading_point.m_bary[0] = rayhit.hit.u;
        shading_point.m_bary[1] = rayhit.hit.v;

        shading_point.m_object_instance_index = geometry_data->m_object_instance_idx;
        // TODO: remove regions
        shading_point.m_primitive_index = rayhit.hit.primID;
        shading_point.m_primitive_type = ShadingPoint::PrimitiveTriangle;
        shading_point.m_ray.m_tmax = rayhit.ray.tfar;

        const uint32 v0_idx = geometry_data->m_primitives[rayhit.hit.primID * 3];
        const uint32 v1_idx = geometry_data->m_primitives[rayhit.hit.primID * 3 + 1];
        const uint32 v2_idx = geometry_data->m_primitives[rayhit.hit.primID * 3 + 2];

        if (geometry_data->m_motion_steps_count > 1)
        {
            const uint32 last_motion_step_idx = geometry_data->m_motion_steps_count - 1;

            const uint32 motion_step_begin_idx = static_cast<uint32>(rayhit.ray.time * last_motion_step_idx);
            const uint32 motion_step_end_idx = motion_step_begin_idx + 1;

            const uint32 motion_step_begin_offset = motion_step_begin_idx * geometry_data->m_vertices_count;
            const uint32 motion_step_end_offset = motion_step_end_idx * geometry_data->m_vertices_count;

            const float motion_step_begin_time = static_cast<float>(motion_step_begin_idx) / last_motion_step_idx;

            // Linear interpolation coefficients.
            const float p = (rayhit.ray.time - motion_step_begin_time) * last_motion_step_idx;
            const float q = 1.0f - p;

            assert(p > 0.0f && p <= 1.0f);

            const TriangleType triangle(
                Vector3d(
                    geometry_data->m_vertices[motion_step_begin_offset + v0_idx] * q
                    + geometry_data->m_vertices[motion_step_end_offset + v0_idx] * p),
                Vector3d(
                    geometry_data->m_vertices[motion_step_begin_offset + v1_idx] * q
                    + geometry_data->m_vertices[motion_step_end_offset + v1_idx] * p),
                Vector3d(
                    geometry_data->m_vertices[motion_step_begin_offset + v2_idx] * q
                    + geometry_data->m_vertices[motion_step_end_offset + v2_idx] * p));

            shading_point.m_triangle_support_plane.initialize(triangle);
        }
        else
        {
            const TriangleType triangle(
                Vector3d(geometry_data->m_vertices[v0_idx]),
                Vector3d(geometry_data->m_vertices[v1_idx]),
                Vector3d(geometry_data->m_vertices[v2_idx]));

            shading_point.m_triangle_support_plane.initialize(triangle);
        }
    }
}