Initial Grease Pencil 3.0 stage #106848

Merged
Falk David merged 224 commits from filedescriptor/blender:grease-pencil-v3 into main 2023-05-30 11:14:22 +02:00
13 changed files with 106 additions and 14 deletions
Showing only changes of commit 72f4d7b40c - Show all commits

View File

@ -38,6 +38,8 @@ void BlenderSync::sync_light(BL::Object &b_parent,
}
}
light->name = b_light.name().c_str();
/* type */
switch (b_light.type()) {
case BL::Light::type_POINT: {

View File

@ -396,7 +396,7 @@ ccl_device Spectrum bsdf_microfacet_eval(ccl_private const ShaderClosure *sc,
* - Purely reflective closures can't have refraction.
* - Purely refractive closures can't have reflection.
*/
if ((cos_NI <= 0) || (alpha_x * alpha_y <= 1e-7f) || ((cos_NgO < 0.0f) != is_refraction) ||
if ((cos_NI <= 0) || (alpha_x * alpha_y <= 5e-7f) || ((cos_NgO < 0.0f) != is_refraction) ||
(is_refraction && !m_refractive) || (!is_refraction && m_refractive && !m_glass))
{
*pdf = 0.0f;
@ -478,7 +478,7 @@ ccl_device int bsdf_microfacet_sample(ccl_private const ShaderClosure *sc,
const bool m_refractive = CLOSURE_IS_REFRACTIVE(bsdf->type);
const float alpha_x = bsdf->alpha_x;
const float alpha_y = bsdf->alpha_y;
bool m_singular = (m_type == MicrofacetType::SHARP) || (alpha_x * alpha_y <= 1e-7f);
bool m_singular = (m_type == MicrofacetType::SHARP) || (alpha_x * alpha_y <= 5e-7f);
const float3 N = bsdf->N;
const float cos_NI = dot(N, wi);

View File

@ -32,6 +32,14 @@ ccl_device_inline void integrate_camera_sample(KernelGlobals kg,
path_rng_3D(kg, rng_hash, sample, PRNG_LENS_TIME) :
zero_float3();
/* We use x for time and y,z for lens because in practice with Sobol
* sampling this seems to give better convergence when an object is
* both motion blurred and out of focus, without significantly harming
* convergence for focal blur alone. This is a little surprising,
* because one would expect using x,y for lens (the 2d part) would be
* best, since x,y are the best stratified. Since it's not entirely
* clear why this is, this is probably worth revisiting at some point
* to investigate further. */
const float rand_time = rand_time_lens.x;
const float2 rand_lens = make_float2(rand_time_lens.y, rand_time_lens.z);

View File

@ -13,6 +13,20 @@ CCL_NAMESPACE_BEGIN
* this single threaded on a CPU for repeatable results. */
//#define __DEBUG_CORRELATION__
/*
* The `path_rng_*()` functions below use a shuffled scrambled Sobol
* sequence to generate their samples. Sobol samplers have a property
* that is worth being aware of when choosing how to use the sample
* dimensions:
*
* 1. In general, earlier sets of dimensions are better stratified. So
* prefer e.g. x,y over y,z over z,w for the things that are most
* important to sample well.
* 2. As a rule of thumb, dimensions that are closer to each other are
* better stratified than dimensions that are far. So prefer e.g.
* x,y over x,z.
*/
ccl_device_forceinline float path_rng_1D(KernelGlobals kg,
uint rng_hash,
int sample,

View File

@ -174,6 +174,24 @@ bool Light::has_contribution(Scene *scene)
return !is_zero(effective_shader->emission_estimate);
}
bool Light::has_light_linking() const
{
if (get_light_set_membership() != LIGHT_LINK_MASK_ALL) {
return true;
}
return false;
}
bool Light::has_shadow_linking() const
{
if (get_shadow_set_membership() != LIGHT_LINK_MASK_ALL) {
return true;
}
return false;
}
/* Light Manager */
LightManager::LightManager()

View File

@ -82,6 +82,10 @@ class Light : public Node {
/* Check whether the light has contribution the scene. */
bool has_contribution(Scene *scene);
/* Check whether this light participates in light or shadow linking. */
bool has_light_linking() const;
bool has_shadow_linking() const;
friend class LightManager;
friend class LightTree;
};

View File

@ -276,6 +276,7 @@ struct LightTreeNode {
__forceinline void add(const LightTreeEmitter &emitter)
{
measure.add(emitter.measure);
light_link.add(emitter.light_set_membership);
}
__forceinline Leaf &get_leaf()

View File

@ -403,6 +403,32 @@ bool Object::usable_as_light() const
return false;
}
bool Object::has_light_linking() const
{
if (get_receiver_light_set()) {
return true;
}
if (get_light_set_membership() != LIGHT_LINK_MASK_ALL) {
return true;
}
return false;
}
bool Object::has_shadow_linking() const
{
if (get_blocker_shadow_set()) {
return true;
}
if (get_shadow_set_membership() != LIGHT_LINK_MASK_ALL) {
return true;
}
return false;
}
/* Object Manager */
ObjectManager::ObjectManager()

View File

@ -113,6 +113,11 @@ class Object : public Node {
/* Check whether this object can be used as light-emissive. */
bool usable_as_light() const;
/* Check whether the object participates in light or shadow linking, either as a receiver/blocker
* or emitter. */
bool has_light_linking() const;
bool has_shadow_linking() const;
protected:
/* Specifies the position of the object in scene->objects and
* in the device vectors. Gets set in device_update. */

View File

@ -491,10 +491,10 @@ void Scene::update_kernel_features()
else if (geom->is_pointcloud()) {
kernel_features |= KERNEL_FEATURE_POINTCLOUD;
}
if (object->get_receiver_light_set()) {
if (object->has_light_linking()) {
kernel_features |= KERNEL_FEATURE_LIGHT_LINKING;
}
if (object->get_blocker_shadow_set()) {
if (object->has_shadow_linking()) {
kernel_features |= KERNEL_FEATURE_SHADOW_LINKING;
}
}
@ -503,6 +503,13 @@ void Scene::update_kernel_features()
if (light->get_use_caustics()) {
has_caustics_light = true;
}
if (light->has_light_linking()) {
kernel_features |= KERNEL_FEATURE_LIGHT_LINKING;
}
if (light->has_shadow_linking()) {
kernel_features |= KERNEL_FEATURE_SHADOW_LINKING;
}
}
dscene.data.integrator.use_caustics = false;

View File

@ -4207,7 +4207,7 @@ void BKE_lib_override_library_main_operations_restore(Main *bmain, int *r_report
ID *id;
FOREACH_MAIN_ID_BEGIN (bmain, id) {
if (!(!ID_IS_LINKED(id) && ID_IS_OVERRIDE_LIBRARY_REAL(id) &&
if (!(!ID_IS_LINKED(id) && ID_IS_OVERRIDE_LIBRARY_REAL(id) && id->override_library->runtime &&
(id->override_library->runtime->tag & LIBOVERRIDE_TAG_NEEDS_RESTORE) != 0))
{
continue;

View File

@ -106,7 +106,7 @@ struct Object *DEG_get_original_object(struct Object *object);
struct ID *DEG_get_original_id(struct ID *id);
/**
* Check whether given ID is an original,
* Check whether given ID is an original.
*
* Original IDs are considered all the IDs which are not covered by copy-on-write system and are
* not out-of-main localized data-blocks.

View File

@ -61,6 +61,13 @@ template<class T> static inline const T *get_original(const T *id)
return reinterpret_cast<T *>(DEG_get_original_id(const_cast<ID *>(&id->id)));
}
/* Check whether the ID is suitable to be an input of the dependency graph. */
/* TODO(sergey): Move the function and check to a more generic place. */
bool is_valid_input_id(const ID &id)
{
return (id.tag & LIB_TAG_LOCALIZED) || DEG_is_original_id(&id);
}
} // namespace
namespace blender::deg::light_linking {
@ -153,7 +160,7 @@ void EmitterDataMap::clear()
EmitterData *EmitterDataMap::ensure_data_if_possible(const Scene &scene, const Object &emitter)
{
BLI_assert(DEG_is_original_id(&emitter.id));
BLI_assert(is_valid_input_id(emitter.id));
const Collection *collection = get_collection(emitter);
BLI_assert(collection);
@ -209,7 +216,7 @@ const EmitterData *EmitterDataMap::get_data(const Object &emitter) const
bool EmitterDataMap::can_skip_emitter(const Object &emitter) const
{
BLI_assert(DEG_is_original_id(&emitter.id));
BLI_assert(is_valid_input_id(emitter.id));
const Collection *collection = get_collection(emitter);
@ -249,7 +256,7 @@ void LinkingData::link_object(const EmitterData &emitter_data,
LightSet &LinkingData::ensure_light_set_for(const Object &object)
{
BLI_assert(DEG_is_original_id(&object.id));
BLI_assert(is_valid_input_id(object.id));
return light_linked_sets_.lookup_or_add_as(&object);
}
@ -363,7 +370,7 @@ void Cache::clear()
void Cache::add_emitter(const Scene &scene, const Object &emitter)
{
BLI_assert(DEG_is_original_id(&emitter.id));
BLI_assert(is_valid_input_id(emitter.id));
add_light_linking_emitter(scene, emitter);
add_shadow_linking_emitter(scene, emitter);
@ -371,7 +378,7 @@ void Cache::add_emitter(const Scene &scene, const Object &emitter)
void Cache::add_light_linking_emitter(const Scene &scene, const Object &emitter)
{
BLI_assert(DEG_is_original_id(&emitter.id));
BLI_assert(is_valid_input_id(emitter.id));
if (light_emitter_data_map_.can_skip_emitter(emitter)) {
return;
@ -390,7 +397,7 @@ void Cache::add_light_linking_emitter(const Scene &scene, const Object &emitter)
void Cache::add_shadow_linking_emitter(const Scene &scene, const Object &emitter)
{
BLI_assert(DEG_is_original_id(&emitter.id));
BLI_assert(is_valid_input_id(emitter.id));
if (shadow_emitter_data_map_.can_skip_emitter(emitter)) {
return;
@ -411,7 +418,7 @@ void Cache::add_receiver_object(const EmitterData &emitter_data,
const CollectionLightLinking &collection_light_linking,
const Object &receiver)
{
BLI_assert(DEG_is_original_id(&receiver.id));
BLI_assert(is_valid_input_id(receiver.id));
if (!can_link_to_emitter(receiver)) {
return;
@ -425,7 +432,7 @@ void Cache::add_blocker_object(const EmitterData &emitter_data,
const CollectionLightLinking &collection_light_linking,
const Object &blocker)
{
BLI_assert(DEG_is_original_id(&blocker.id));
BLI_assert(is_valid_input_id(blocker.id));
if (!can_link_to_emitter(blocker)) {
return;