Beispiel #1
0
bool EDF::on_frame_begin(
    const Project&      project,
    const Assembly&     assembly,
    IAbortSwitch*       abort_switch)
{
    m_flags = 0;

    if (m_params.get_optional<bool>("cast_indirect_light", true))
        m_flags |= CastIndirectLight;

    m_light_near_start = get_uncached_light_near_start();

    if (m_light_near_start < 0.0)
    {
        RENDERER_LOG_WARNING(
            "edf \"%s\" has a negative light near start value; expect artifacts and/or slowdowns.",
            get_path().c_str());
    }

    if (get_uncached_importance_multiplier() <= 0.0)
    {
        RENDERER_LOG_WARNING(
            "edf \"%s\" has negative or zero importance; expect artifacts and/or slowdowns.",
            get_path().c_str());
    }

    return true;
}
Beispiel #2
0
bool EDF::on_frame_begin(
    const Project&          project,
    const BaseGroup*        parent,
    OnFrameBeginRecorder&   recorder,
    IAbortSwitch*           abort_switch)
{
    if (!ConnectableEntity::on_frame_begin(project, parent, recorder, abort_switch))
        return false;

    m_flags = 0;

    if (m_params.get_optional<bool>("cast_indirect_light", true))
        m_flags |= CastIndirectLight;

    m_light_near_start = get_uncached_light_near_start();

    if (m_light_near_start < 0.0)
    {
        RENDERER_LOG_WARNING(
            "edf \"%s\" has a negative light near start value; expect artifacts and/or slowdowns.",
            get_path().c_str());
    }

    if (get_uncached_importance_multiplier() <= 0.0f)
    {
        RENDERER_LOG_WARNING(
            "edf \"%s\" has negative or zero importance; expect artifacts and/or slowdowns.",
            get_path().c_str());
    }

    return true;
}
Beispiel #3
0
void ShaderGroup::get_shadergroup_globals_info(OSLShadingSystem& shading_system)
{
    // Assume the shader group uses all globals.
    m_flags |= UsesAllGlobals;

    int num_globals = 0;
    if (!shading_system.getattribute(
            impl->m_shader_group_ref.get(),
            "num_globals_needed",
            num_globals))
    {
        RENDERER_LOG_WARNING(
            "getattribute: num_globals_needed call failed for shader group \"%s\"; "
            "assuming shader group uses all globals.",
            get_path().c_str());
        return;
    }

    if (num_globals != 0)
    {
        OIIO::ustring* globals = nullptr;
        if (!shading_system.getattribute(
                impl->m_shader_group_ref.get(),
                "globals_needed",
                OIIO::TypeDesc::PTR,
                &globals))
        {
            RENDERER_LOG_WARNING(
                "getattribute: globals_needed call failed for shader group \"%s\"; "
                "assuming shader group uses all globals.",
                get_path().c_str());
            return;
        }

        // Clear all globals flags.
        m_flags &= ~UsesAllGlobals;

        // Set the globals flags.
        for (int i = 0; i < num_globals; ++i)
        {
            if (globals[i] == g_dPdtime_str)
                m_flags |= UsesdPdTime;
        }
    }
    else
    {
        // The shader group uses no globals.
        m_flags &= ~UsesAllGlobals;
    }
}
Beispiel #4
0
void EnvironmentEDF::warn_exitance_input_null() const
{
    RENDERER_LOG_WARNING(
        "environment edf \"%s\" has a zero exitance and will slow down rendering "
        "without contributing to the lighting.",
        get_name());
}
void ConnectableEntity::warn_zero_radiance() const
{
    RENDERER_LOG_WARNING(
        "\"%s\" has a null emitted radiance and will slow down rendering "
        "without contributing to the lighting.",
        get_name());
}
Beispiel #6
0
void OIIOErrorHandler::operator()(int errcode, const std::string& msg)
{
    switch (errcode)
    {
      case EH_WARNING:
        RENDERER_LOG_WARNING("%s", msg.c_str());
        break;

      case EH_ERROR:
        RENDERER_LOG_ERROR("%s", msg.c_str());
        break;

      case EH_SEVERE:
        RENDERER_LOG_FATAL("%s", msg.c_str());
        break;

      case EH_DEBUG:
        RENDERER_LOG_DEBUG("%s", msg.c_str());
        break;

      default:
        RENDERER_LOG_INFO("%s", msg.c_str());
        break;
    }
}
Beispiel #7
0
bool ObjectInstance::on_frame_begin(
    const Project&          project,
    const BaseGroup*        parent,
    OnFrameBeginRecorder&   recorder,
    IAbortSwitch*           abort_switch)
{
    if (!Entity::on_frame_begin(project, parent, recorder, abort_switch))
        return false;

    m_transform_swaps_handedness = get_transform().swaps_handedness();

    const EntityDefMessageContext context("object instance", this);

    if (uses_alpha_mapping())
    {
        if (m_front_materials != m_back_materials)
        {
            RENDERER_LOG_WARNING(
                "%s: object instance uses alpha mapping on one side (or both) but materials are different on front and back faces; "
                "this may lead to unexpected or unphysical results since the direction of shadow rays is unpredictable.",
                context.get());
        }
    }

    return true;
}
Beispiel #8
0
bool Material::on_frame_begin(
    const Project&      project,
    const Assembly&     assembly)
{
    m_surface_shader = get_uncached_surface_shader();
    m_bsdf = get_uncached_bsdf();
    m_edf = get_uncached_edf();
    m_alpha_map = get_uncached_alpha_map();

    const Source* displacement_source = m_inputs.source("displacement_map");

    if (displacement_source)
    {
        if (dynamic_cast<const TextureSource*>(displacement_source) == 0)
        {
            RENDERER_LOG_ERROR(
                "while defining material \"%s\": a texture instance must be bound "
                "to the \"displacement_map\" input; disabling displacement map for this material.",
                get_name());
        }
        else
        {
            const TextureSource* displacement_map = static_cast<const TextureSource*>(displacement_source);
            const Texture& texture = displacement_map->get_texture_instance().get_texture();

            if (texture.get_color_space() != ColorSpaceLinearRGB)
            {
                RENDERER_LOG_WARNING(
                    "while defining material \"%s\": color space for displacement map \"%s\" "
                    "should be \"%s\" but is \"%s\" instead; expect artifacts and/or slowdowns.",
                    get_name(),
                    texture.get_name(),
                    color_space_name(ColorSpaceLinearRGB),
                    color_space_name(texture.get_color_space()));
            }

            // Retrieve the displacement method and create the normal modifier.
            const string displacement_method =
                m_params.get_required<string>("displacement_method", "bump");
            if (displacement_method == "bump")
            {
                const double amplitude = m_params.get_optional<double>("bump_amplitude", 1.0);
                m_normal_modifier = new BumpMappingModifier(displacement_map, 2.0, amplitude);
            }
            else if (displacement_method == "normal")
                m_normal_modifier = new NormalMappingModifier(displacement_map);
            else
            {
                RENDERER_LOG_ERROR(
                    "while defining material \"%s\": invalid value \"%s\" for parameter "
                    "\"displacement_method\"; disabling displacement map for this material.",
                    get_name(),
                    displacement_method.c_str());
            }
        }
    }

    return true;
}
Beispiel #9
0
IBasisModifier* Material::create_basis_modifier(const MessageContext& context) const
{
    // Retrieve the source bound to the displacement map input.
    const Source* displacement_source = m_inputs.source("displacement_map");

    // Nothing to do if there is no displacement source.
    if (displacement_source == 0)
        return 0;

    // Only texture instances can be bound to the displacement map input.
    if (dynamic_cast<const TextureSource*>(displacement_source) == 0)
    {
        RENDERER_LOG_ERROR(
            "%s: a texture instance must be bound to the \"displacement_map\" input.",
            context.get());
        return 0;
    }

    // Retrieve the displacement texture.
    const TextureSource* displacement_map = static_cast<const TextureSource*>(displacement_source);
    const Texture& texture = displacement_map->get_texture_instance().get_texture();

    // Print a warning if the displacement texture is not expressed in the linear RGB color space.
    if (texture.get_color_space() != ColorSpaceLinearRGB)
    {
        RENDERER_LOG_WARNING(
            "%s: color space for displacement map \"%s\" "
            "should be \"%s\" but is \"%s\" instead; expect artifacts and/or slowdowns.",
            context.get(),
            texture.get_path().c_str(),
            color_space_name(ColorSpaceLinearRGB),
            color_space_name(texture.get_color_space()));
    }

    // Retrieve the displacement method.
    const string displacement_method =
        m_params.get_required<string>(
            "displacement_method",
            "bump",
            make_vector("bump", "normal"),
            context);

    // Create the basis modifier.
    if (displacement_method == "bump")
    {
        const float offset = m_params.get_optional<float>("bump_offset", 2.0f);
        const float amplitude = m_params.get_optional<float>("bump_amplitude", 1.0f);
        return new BumpMappingModifier(displacement_map, offset, amplitude);
    }
    else
    {
        const NormalMappingModifier::UpVector up_vector =
            m_params.get_optional<string>("normal_map_up", "z", make_vector("y", "z"), context) == "y"
                ? NormalMappingModifier::UpVectorY
                : NormalMappingModifier::UpVectorZ;
        return new NormalMappingModifier(displacement_map, up_vector);
    }
}
PixelRendererBase::~PixelRendererBase()
{
    if (m_invalid_sample_count > 0)
    {
        RENDERER_LOG_WARNING(
            "found %s pixel sample%s with NaN or negative values",
            pretty_uint(m_invalid_sample_count).c_str(),
            m_invalid_sample_count > 1 ? "s" : "");
    }
}
Beispiel #11
0
void ShaderGroup::get_shadergroup_globals_info(OSL::ShadingSystem& shading_system)
{
    m_uses_dPdtime = true;

    int num_globals = 0;
    if (!shading_system.getattribute(
            impl->m_shader_group_ref.get(),
            "num_globals_needed",
            num_globals))
    {
        RENDERER_LOG_WARNING(
            "getattribute: num_globals_needed call failed for shader group %s; "
            "assuming shader group uses all globals.",
            get_name());
        return;
    }

    if (num_globals != 0)
    {
        OIIO::ustring* globals = 0;
        if (!shading_system.getattribute(
                impl->m_shader_group_ref.get(),
                "globals_needed",
                OIIO::TypeDesc::PTR,
                &globals))
        {
            RENDERER_LOG_WARNING(
                "getattribute: globals_needed call failed for shader group %s; "
                "assuming shader group uses all globals.",
                get_name());
            return;
        }

        m_uses_dPdtime = false;

        for (int i = 0; i < num_globals; ++i)
        {
            if (globals[i] == g_dPdtime_str)
                m_uses_dPdtime = true;
        }
    }
}
Beispiel #12
0
bool Camera::on_frame_begin(
    const Project&      project,
    IAbortSwitch*       abort_switch)
{
    m_transform_sequence.optimize();

    if (!m_transform_sequence.prepare())
        RENDERER_LOG_WARNING("camera \"%s\" has one or more invalid transforms.", get_path().c_str());

    return true;
}
Beispiel #13
0
void CompositeClosure::do_add_closure(
    const ClosureID             closure_type,
    const Color3f&              weight,
    const Vector3d&             normal,
    bool                        has_tangent,
    const Vector3d&             tangent,
    const InputValues&          params)
{
    // Check that InputValues is included in our type list.
    typedef typename boost::mpl::contains<InputValuesTypeList, InputValues>::type value_in_list;
    BOOST_STATIC_ASSERT(value_in_list::value);

    // Make sure we have enough space.
    if (get_num_closures() >= MaxClosureEntries)
    {
        RENDERER_LOG_WARNING("maximum number of closures in OSL shadergroup exceeded; ignoring closure.");
        return;
    }

    assert(m_num_bytes + sizeof(InputValues) <= MaxPoolSize);

    // We use the luminance of the weight as the BSDF weight.
    const double w = luminance(weight);

    // Ignore zero or negative weights.
    if (w <= 0.0)
        return;

    m_cdf[m_num_closures] = w;
    linear_rgb_reflectance_to_spectrum_unclamped(weight, m_spectrum_multipliers[m_num_closures]);
    m_normals[m_num_closures] = normalize(normal);

    // If the tangent is zero, ignore it.
    // This can happen when using the isotropic microfacet closure overload, for example.
    if (square_norm(tangent) == 0.0)
        has_tangent = false;

    m_has_tangent[m_num_closures] = has_tangent;

    if (has_tangent)
        m_tangents[m_num_closures] = normalize(tangent);

    m_closure_types[m_num_closures] = closure_type;

    char* values_ptr = m_pool + m_num_bytes;
    assert(is_aligned(values_ptr, InputValuesAlignment));
    new (values_ptr) InputValues(params);
    m_input_values[m_num_closures] = values_ptr;
    m_num_bytes += align(sizeof(InputValues), InputValuesAlignment);
    ++m_num_closures;
}
    void postprocess(const RenderingResult& rendering_result)
    {
        Frame* frame = m_project.get_frame();
        assert(frame != nullptr);

        // Nothing to do if there are no post-processing stages.
        if (frame->post_processing_stages().empty())
            return;

        // Collect post-processing stages.
        vector<PostProcessingStage*> ordered_stages;
        ordered_stages.reserve(frame->post_processing_stages().size());
        for (auto& stage : frame->post_processing_stages())
            ordered_stages.push_back(&stage);

        // Sort post-processing stages in increasing order.
        sort(
            ordered_stages.begin(),
            ordered_stages.end(),
            [](PostProcessingStage* lhs, PostProcessingStage* rhs)
            {
                return lhs->get_order() < rhs->get_order();
            });

        // Detect post-processing stages with equal order.
        size_t previous_stage_index = 0;
        int previous_order = ordered_stages[0]->get_order();
        for (size_t i = 1, e = ordered_stages.size(); i < e; ++i)
        {
            const int order = ordered_stages[i]->get_order();
            if (order == previous_order)
            {
                RENDERER_LOG_WARNING(
                    "post-processing stages \"%s\" and \"%s\" have equal order (%d); results will be unpredictable.",
                    ordered_stages[previous_stage_index]->get_path().c_str(),
                    ordered_stages[i]->get_path().c_str(),
                    order);
            }
        }

        // Execute post-processing stages.
        for (auto stage : ordered_stages)
        {
            RENDERER_LOG_INFO("executing \"%s\" post-processing stage with order %d on frame \"%s\"...",
                stage->get_path().c_str(), stage->get_order(), frame->get_path().c_str());
            stage->execute(*frame);
            invoke_tile_callbacks(*frame);
        }
    }
Beispiel #15
0
bool Camera::on_frame_begin(
    const Project&          project,
    const BaseGroup*        parent,
    OnFrameBeginRecorder&   recorder,
    IAbortSwitch*           abort_switch)
{
    if (!ConnectableEntity::on_frame_begin(project, parent, recorder, abort_switch))
        return false;

    m_transform_sequence.optimize();

    if (!m_transform_sequence.prepare())
        RENDERER_LOG_WARNING("camera \"%s\" has one or more invalid transforms.", get_path().c_str());

    return true;
}
Beispiel #16
0
void Camera::extract_focal_distance(
    bool&               autofocus_enabled,
    Vector2d&           autofocus_target,
    double&             focal_distance) const
{
    const Vector2d DefaultAFTarget(0.5);        // in NDC
    const double DefaultFocalDistance = 1.0;    // in meters

    if (has_param("focal_distance"))
    {
        if (has_param("autofocus_target"))
        {
            RENDERER_LOG_WARNING(
                "while defining camera \"%s\": autofocus is enabled; \"focal_distance\" parameter "
                "will be ignored.",
                get_path().c_str());

            autofocus_enabled = true;
            autofocus_target = m_params.get_required<Vector2d>("autofocus_target", DefaultAFTarget);
            focal_distance = 0.0;
        }
        else
        {
            autofocus_enabled = false;
            autofocus_target = DefaultAFTarget;
            focal_distance = m_params.get_required<double>("focal_distance", DefaultFocalDistance);
        }
    }
    else if (has_param("autofocus_target"))
    {
        autofocus_enabled = true;
        autofocus_target = m_params.get_required<Vector2d>("autofocus_target", DefaultAFTarget);
        focal_distance = 0.0;
    }
    else
    {
        RENDERER_LOG_ERROR(
            "while defining camera \"%s\": no \"focal_distance\" or \"autofocus_target\" parameter found; "
            "using default focal distance value \"%f\".",
            get_path().c_str(),
            DefaultFocalDistance);

        autofocus_enabled = false;
        autofocus_target = DefaultAFTarget;
        focal_distance = DefaultFocalDistance;
    }
}
Beispiel #17
0
bool ObjectInstance::on_frame_begin(
    const Project&          project,
    const Assembly&         assembly,
    IAbortSwitch*           abort_switch)
{
    const EntityDefMessageContext context("object instance", this);

    if (uses_alpha_mapping())
    {
        if (m_front_materials != m_back_materials)
        {
            RENDERER_LOG_WARNING(
                "%s: object instance uses alpha mapping on one side (or both) but materials are different on front and back faces; "
                "this may lead to unexpected or unphysical results since the direction of shadow rays is unpredictable.",
                context.get());
        }
    }

    return true;
}
Beispiel #18
0
double Camera::extract_focal_length(const double film_width) const
{
    const double DefaultFocalLength = 0.035;    // in meters
    const double DefaultHFov = 54.0;            // in degrees

    if (has_param("focal_length"))
    {
        if (has_param("horizontal_fov"))
        {
            RENDERER_LOG_WARNING(
                "while defining camera \"%s\": the parameter \"horizontal_fov\" "
                "has precedence over \"focal_length\".",
                get_path().c_str());

            const double hfov = get_greater_than_zero("horizontal_fov", DefaultHFov);
            return hfov_to_focal_length(film_width, hfov);
        }
        else
        {
            return get_greater_than_zero("focal_length", DefaultFocalLength);
        }
    }
    else if (has_param("horizontal_fov"))
    {
        const double hfov = get_greater_than_zero("horizontal_fov", DefaultHFov);
        return hfov_to_focal_length(film_width, hfov);
    }
    else
    {
        RENDERER_LOG_ERROR(
            "while defining camera \"%s\": no \"horizontal_fov\" or \"focal_length\" parameter found; "
            "using default focal length value \"%f\".",
            get_path().c_str(),
            DefaultFocalLength);

        return DefaultFocalLength;
    }
}
Beispiel #19
0
void CompositeSubsurfaceClosure::add_closure(
    const ClosureID             closure_type,
    const Color3f&              weight,
    const InputValues&          params)
{
    // Check that InputValues is included in our type list.
    typedef typename boost::mpl::contains<InputValuesTypeList, InputValues>::type value_in_list;
    BOOST_STATIC_ASSERT(value_in_list::value);

    // Make sure we have enough space.
    if (get_num_closures() >= MaxClosureEntries)
    {
        RENDERER_LOG_WARNING("maximum number of subsurface closures in osl shader group exceeded; ignoring closure.");
        return;
    }

    assert(m_num_bytes + sizeof(InputValues) <= MaxPoolSize);

    // We use the luminance of the weight as the BSSRDF weight.
    const double w = luminance(weight);

    // Ignore zero or negative weights.
    if (w <= 0.0)
        return;

    m_pdf_weights[m_num_closures] = w;
    m_weights[m_num_closures] = weight;
    m_closure_types[m_num_closures] = closure_type;

    char* values_ptr = m_pool + m_num_bytes;
    assert(is_aligned(values_ptr, InputValuesAlignment));
    new (values_ptr) InputValues(params);
    m_input_values[m_num_closures] = values_ptr;
    m_num_bytes += align(sizeof(InputValues), InputValuesAlignment);
    ++m_num_closures;
}
Beispiel #20
0
void ShaderGroup::get_shadergroup_closures_info(OSL::ShadingSystem& shading_system)
{
    m_has_emission = true;
    m_has_transparency = true;
    m_has_subsurface = true;
    m_has_holdout = true;
    m_has_debug = true;

    int num_unknown_closures = 0;
    if (!shading_system.getattribute(
            impl->m_shader_group_ref.get(),
            "unknown_closures_needed",
            num_unknown_closures))
    {
        RENDERER_LOG_WARNING(
            "getattribute: unknown_closures_needed call failed for shader group %s; "
            "assuming shader group has all kinds of closures.",
            get_name());
        return;
    }

    if (num_unknown_closures != 0)
    {
        RENDERER_LOG_WARNING(
            "shader group %s has unknown closures; "
            "assuming shader group has all kinds of closures.",
            get_name());
        return;
    }

    int num_closures = 0;
    if (!shading_system.getattribute(
            impl->m_shader_group_ref.get(),
            "num_closures_needed",
            num_closures))
    {
        RENDERER_LOG_WARNING(
            "getattribute: num_closures_needed call failed for shader group %s; "
            "assuming shader group has all kinds of closures.",
            get_name());
    }

    if (num_closures != 0)
    {
        OIIO::ustring* closures = 0;
        if (!shading_system.getattribute(
                impl->m_shader_group_ref.get(),
                "closures_needed",
                OIIO::TypeDesc::PTR,
                &closures))
        {
            RENDERER_LOG_WARNING(
                "getattribute: closures_needed call failed for shader group %s; "
                "assuming shader group has all kinds of closures.",
                get_name());
            return;
        }

        m_has_emission = false;
        m_has_transparency = false;
        m_has_subsurface = false;
        m_has_holdout = false;
        m_has_debug = false;

        for (int i = 0; i < num_closures; ++i)
        {
            if (closures[i] == g_emission_str)
                m_has_emission = true;

            if (closures[i] == g_transparent_str)
                m_has_transparency = true;

            if (closures[i] == g_subsurface_str)
                m_has_subsurface = true;

            if (closures[i] == g_holdout_str)
                m_has_holdout = true;

            if (closures[i] == g_debug_str)
                m_has_debug = true;
        }
    }
}
Beispiel #21
0
const ShadingPoint& Tracer::do_trace_between(
    const Vector3d&             origin,
    const Vector3d&             target,
    const ShadingRay::Time&     ray_time,
    const VisibilityFlags::Type ray_flags,
    const ShadingRay::DepthType ray_depth,
    float&                      transmission,
    const ShadingPoint*         parent_shading_point)
{
    transmission = 1.0f;

    const ShadingPoint* shading_point_ptr = parent_shading_point;
    size_t shading_point_index = 0;
    Vector3d point = origin;
    size_t iterations = 0;

    while (true)
    {
        // Put a hard limit on the number of iterations.
        if (++iterations >= m_max_iterations)
        {
            RENDERER_LOG_WARNING(
                "reached hard iteration limit (%s), breaking trace loop.",
                pretty_int(m_max_iterations).c_str());
            break;
        }

        // Construct the visibility ray.
        const Vector3d direction = target - point;
        const double dist = norm(direction);

        const ShadingRay ray(
            point,
            direction / dist,
            0.0,                    // ray tmin
            dist * (1.0 - 1.0e-6),  // ray tmax
            ray_time,
            ray_flags,
            ray_depth);         // ray depth does not increase when passing through an alpha-mapped surface

        // Trace the ray.
        m_shading_points[shading_point_index].clear();
        m_intersector.trace(
            ray,
            m_shading_points[shading_point_index],
            shading_point_ptr);

        // Update the pointers to the shading points.
        shading_point_ptr = &m_shading_points[shading_point_index];
        shading_point_index = 1 - shading_point_index;

        // Stop if the ray reached the target point.
        if (!shading_point_ptr->hit())
            break;

        // Retrieve the material at the shading point.
        const Material* material = shading_point_ptr->get_material();
        if (material == 0)
            break;

        // Evaluate the alpha map at the shading point.
        Alpha alpha;
        evaluate_alpha(*material, *shading_point_ptr, alpha);

        // Stop at the first fully opaque occluder.
        if (alpha[0] >= 1.0f)
            break;

        // Update the transmission factor.
        transmission *= 1.0f - alpha[0];

        // Stop once we hit full opacity.
        if (transmission < m_transmission_threshold)
            break;

        // Move past this partial occluder.
        point = shading_point_ptr->get_point();
    }

    return *shading_point_ptr;
}
void PythonInterpreter::initialize(OutputRedirector redirector)
{
    //
    // When using Boost.Python as a shared libray, Boost.Python's C++ <-> Python registry
    // is shared between all loaded Boost.Python extension modules, and objects can be
    // converted between modules.
    //
    // When using Boost.Python as a static library however, each module has its own
    // registry and attempting to convert objects between modules fails.
    //
    // To summarize:
    //  - When using compiled modules with static Boost.Python, there are 2 registries.
    //  - When using compiled modules with shared Boost.Python, there is 1 registry.
    //
    // The solution is to build all extension modules into appleseed.studio such that
    // we get a single registry. That way appleseed.studio module can find a converter
    // from e.g. renderer::Project to appleseedpython.Project.
    //

    PyImport_AppendInittab("_appleseedpythonbuiltin", init_appleseedpythonbuiltin);
    PyImport_AppendInittab("_appleseedstudio", init_appleseedstudio);
    Py_Initialize();

    bpy::object main_module = bpy::import("__main__");
    m_main_namespace = main_module.attr("__dict__");

    // Locate the path to Python's site-packages/ directory.
    const bf::path site_packages_path = compute_site_packages_path();
    if (bf::is_directory(site_packages_path))
    {
        RENDERER_LOG_INFO("Python's site-packages directory found at %s.",
            site_packages_path.string().c_str());
    }
    else
    {
        RENDERER_LOG_WARNING(
            "Python's site-packages directory does not exist: %s",
            site_packages_path.string().c_str());
    }

    // Locate the path to appleseed Python module's directory.
    const bf::path appleseed_python_module_path = compute_appleseed_python_module_path();
    if (bf::is_directory(appleseed_python_module_path))
    {
        RENDERER_LOG_INFO(
            "appleseed Python module's directory found at %s.",
            appleseed_python_module_path.string().c_str());
    }
    else
    {
        RENDERER_LOG_WARNING(
            "appleseed Python module's directory does not exist: %s",
            appleseed_python_module_path.string().c_str());
    }

    // Add paths to Python's site-packages/ and appleseed Python module's directory to sys.path.
    bpy::import("sys").attr("path").attr("append")(site_packages_path.string());
    bpy::import("sys").attr("path").attr("append")(appleseed_python_module_path.string());

    // Redirect stdout and stderr to the output panel.
    bpy::class_<OutputRedirector>("OutputRedirector", bpy::no_init)
        .def("write", &OutputRedirector::write);

    bpy::object sys_module = bpy::import("sys");
    sys_module.attr("stdout") = redirector;
    sys_module.attr("stderr") = redirector;

    // Import Python modules.
    import_python_module("appleseed", "asr");
    import_python_module("appleseed.studio", "studio");
}
Beispiel #23
0
const ShadingPoint& Tracer::do_trace(
    const Vector3d&             origin,
    const Vector3d&             direction,
    const double                time,
    const ShadingRay::Type      ray_type,
    const ShadingRay::DepthType ray_depth,
    double&                     transmission,
    const ShadingPoint*         parent_shading_point)
{
    transmission = 1.0;

    const ShadingPoint* shading_point_ptr = parent_shading_point;
    size_t shading_point_index = 0;
    Vector3d point = origin;
    size_t iterations = 0;

    while (true)
    {
        // Put a hard limit on the number of iterations.
        if (++iterations >= m_max_iterations)
        {
            RENDERER_LOG_WARNING(
                "reached hard iteration limit (%s), breaking trace loop.",
                pretty_int(m_max_iterations).c_str());
            break;
        }

        // Construct the visibility ray.
        const ShadingRay ray(
            point,
            direction,
            time,
            m_ray_dtime,
            ray_type,
            ray_depth);         // ray depth does not increase when passing through an alpha-mapped surface

        // Trace the ray.
        m_shading_points[shading_point_index].clear();
        m_intersector.trace(
            ray,
            m_shading_points[shading_point_index],
            shading_point_ptr);

        // Update the pointers to the shading points.
        shading_point_ptr = &m_shading_points[shading_point_index];
        shading_point_index = 1 - shading_point_index;

        // Stop if the ray escaped the scene.
        if (!shading_point_ptr->hit())
            break;

        // Retrieve the material at the shading point.
        const Material* material = shading_point_ptr->get_material();
        if (material == 0)
            break;

        Alpha alpha;
        evaluate_alpha(*material, *shading_point_ptr, alpha);

        // Stop at the first fully opaque occluder.
        if (alpha[0] >= 1.0f)
            break;

        // Update the transmission factor.
        transmission *= 1.0 - static_cast<double>(alpha[0]);

        // Stop once we hit full opacity.
        if (transmission < m_transmission_threshold)
            break;

        // Move past this partial occluder.
        point = shading_point_ptr->get_point();
    }

    return *shading_point_ptr;
}
Beispiel #24
0
void ShaderGroup::get_shadergroup_closures_info(OSLShadingSystem& shading_system)
{
    // Assume the shader group has all closure types.
    m_flags |= HasAllClosures;

    int num_unknown_closures = 0;
    if (!shading_system.getattribute(
            impl->m_shader_group_ref.get(),
            "unknown_closures_needed",
            num_unknown_closures))
    {
        RENDERER_LOG_WARNING(
            "getattribute: unknown_closures_needed call failed for shader group \"%s\"; "
            "assuming shader group has all kinds of closures.",
            get_path().c_str());
        return;
    }

    if (num_unknown_closures != 0)
    {
        RENDERER_LOG_WARNING(
            "shader group \"%s\" has unknown closures; "
            "assuming shader group has all kinds of closures.",
            get_path().c_str());
        return;
    }

    int num_closures = 0;
    if (!shading_system.getattribute(
            impl->m_shader_group_ref.get(),
            "num_closures_needed",
            num_closures))
    {
        RENDERER_LOG_WARNING(
            "getattribute: num_closures_needed call failed for shader group \"%s\"; "
            "assuming shader group has all kinds of closures.",
            get_path().c_str());
    }

    if (num_closures != 0)
    {
        OIIO::ustring* closures = nullptr;
        if (!shading_system.getattribute(
                impl->m_shader_group_ref.get(),
                "closures_needed",
                OIIO::TypeDesc::PTR,
                &closures))
        {
            RENDERER_LOG_WARNING(
                "getattribute: closures_needed call failed for shader group \"%s\"; "
                "assuming shader group has all kinds of closures.",
                get_path().c_str());
            return;
        }

        // Clear all closure flags.
        m_flags &= ~HasAllClosures;

        // Set the closure flags.
        for (int i = 0; i < num_closures; ++i)
        {
            if (closures[i] == g_emission_str)
                m_flags |= HasEmission;
            else if (closures[i] == g_transparent_str)
                m_flags |= HasTransparency;
            else if (is_subsurface_closure(closures[i]))
                m_flags |= HasSubsurface;
            else if (closures[i] == g_debug_str)
                m_flags |= HasDebug;
            else if (closures[i] == g_npr_shading_str)
                m_flags |= HasNPR;
            else if (closures[i] == g_npr_contour_str)
                m_flags |= HasNPR;
            else if (
                closures[i] == g_matte_str ||
                closures[i] == g_holdout_str)
                m_flags |= HasMatte;
            else
                m_flags |= HasBSDFs;
        }
    }
    else
    {
        // Shader group uses no closures.
        m_flags &= ~HasAllClosures;
    }
}
void PixelRendererBase::signal_invalid_sample()
{
    // todo: mark pixel as faulty in the diagnostic map.
    if (m_invalid_sample_count++ == 0)
        RENDERER_LOG_WARNING("found at least one pixel sample with NaN or negative values.");
}