Geometry Nodes: make evaluation and logging system aware of zones #109029

Closed
Jacques Lucke wants to merge 93 commits from JacquesLucke/blender:zone-evaluation into main

When changing the target branch, be careful to rebase the branch in your fork to match. See documentation.
142 changed files with 6945 additions and 5244 deletions
Showing only changes of commit e5c5ddce6c - Show all commits

View File

@ -106,7 +106,8 @@ ExternalProject_Add(external_openimageio
CMAKE_GENERATOR ${PLATFORM_ALT_GENERATOR}
PREFIX ${BUILD_DIR}/openimageio
PATCH_COMMAND ${PATCH_CMD} -p 1 -N -d ${BUILD_DIR}/openimageio/src/external_openimageio/ < ${PATCH_DIR}/openimageio.diff &&
${PATCH_CMD} -p 1 -N -d ${BUILD_DIR}/openimageio/src/external_openimageio/ < ${PATCH_DIR}/oiio_3832.diff
${PATCH_CMD} -p 1 -N -d ${BUILD_DIR}/openimageio/src/external_openimageio/ < ${PATCH_DIR}/oiio_3832.diff &&
${PATCH_CMD} -p 1 -N -d ${BUILD_DIR}/openimageio/src/external_openimageio/ < ${PATCH_DIR}/oiio_deadlock.diff
CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${LIBDIR}/openimageio ${DEFAULT_CMAKE_FLAGS} ${OPENIMAGEIO_EXTRA_ARGS}
INSTALL_DIR ${LIBDIR}/openimageio
)

View File

@ -0,0 +1,62 @@
diff -Naur orig/src/idiff/idiff.cpp external_openimageio/src/idiff/idiff.cpp
--- orig/src/idiff/idiff.cpp 2023-06-07 07:47:42 -0600
+++ external_openimageio/src/idiff/idiff.cpp 2023-06-07 09:46:47 -0600
@@ -399,5 +399,6 @@
imagecache->invalidate_all(true);
ImageCache::destroy(imagecache);
+ default_thread_pool()->resize(0);
return ret;
}
diff -Naur orig/src/libutil/thread.cpp external_openimageio/src/libutil/thread.cpp
--- orig/src/libutil/thread.cpp 2023-06-07 07:47:42 -0600
+++ external_openimageio/src/libutil/thread.cpp 2023-06-07 09:45:39 -0600
@@ -151,9 +151,10 @@
this->set_thread(i);
}
} else { // the number of threads is decreased
+ std::vector<std::unique_ptr<std::thread>> terminating_threads;
for (int i = oldNThreads - 1; i >= nThreads; --i) {
*this->flags[i] = true; // this thread will finish
- this->terminating_threads.push_back(
+ terminating_threads.push_back(
std::move(this->threads[i]));
this->threads.erase(this->threads.begin() + i);
}
@@ -162,6 +163,11 @@
std::unique_lock<std::mutex> lock(this->mutex);
this->cv.notify_all();
}
+ // wait for the terminated threads to finish
+ for (auto& thread : terminating_threads) {
+ if (thread->joinable())
+ thread->join();
+ }
this->threads.resize(
nThreads); // safe to delete because the threads are detached
this->flags.resize(
@@ -238,16 +244,10 @@
if (thread->joinable())
thread->join();
}
- // wait for the terminated threads to finish
- for (auto& thread : this->terminating_threads) {
- if (thread->joinable())
- thread->join();
- }
// if there were no threads in the pool but some functors in the queue, the functors are not deleted by the threads
// therefore delete them here
this->clear_queue();
this->threads.clear();
- this->terminating_threads.clear();
this->flags.clear();
}
@@ -349,7 +349,6 @@
}
std::vector<std::unique_ptr<std::thread>> threads;
- std::vector<std::unique_ptr<std::thread>> terminating_threads;
std::vector<std::shared_ptr<std::atomic<bool>>> flags;
mutable pvt::ThreadsafeQueue<std::function<void(int id)>*> q;
std::atomic<bool> isDone;

View File

@ -873,6 +873,7 @@ static ShaderNode *add_node(Scene *scene,
voronoi->set_dimensions(b_voronoi_node.voronoi_dimensions());
voronoi->set_feature((NodeVoronoiFeature)b_voronoi_node.feature());
voronoi->set_metric((NodeVoronoiDistanceMetric)b_voronoi_node.distance());
voronoi->set_normalize(b_voronoi_node.normalize());
BL::TexMapping b_texture_mapping(b_voronoi_node.texture_mapping());
get_tex_mapping(voronoi, b_texture_mapping);
node = voronoi;

View File

@ -307,7 +307,12 @@ ccl_device_inline void bsdf_roughness_eta(const KernelGlobals kg,
case CLOSURE_BSDF_MICROFACET_BECKMANN_GLASS_ID: {
ccl_private const MicrofacetBsdf *bsdf = (ccl_private const MicrofacetBsdf *)sc;
*roughness = make_float2(bsdf->alpha_x, bsdf->alpha_y);
*eta = CLOSURE_IS_REFRACTIVE(bsdf->type) ? 1.0f / bsdf->ior : bsdf->ior;
if (CLOSURE_IS_REFRACTION(bsdf->type) || CLOSURE_IS_GLASS(bsdf->type)) {
*eta = 1.0f / bsdf->ior;
}
else {
*eta = bsdf->ior;
}
break;
}
case CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID: {
@ -594,7 +599,9 @@ ccl_device void bsdf_blur(KernelGlobals kg, ccl_private ShaderClosure *sc, float
}
ccl_device_inline Spectrum bsdf_albedo(ccl_private const ShaderData *sd,
ccl_private const ShaderClosure *sc)
ccl_private const ShaderClosure *sc,
const bool reflection,
const bool transmission)
{
Spectrum albedo = sc->weight;
/* Some closures include additional components such as Fresnel terms that cause their albedo to
@ -608,12 +615,16 @@ ccl_device_inline Spectrum bsdf_albedo(ccl_private const ShaderData *sd,
* extra overhead though. */
#if defined(__SVM__) || defined(__OSL__)
if (CLOSURE_IS_BSDF_MICROFACET(sc->type)) {
albedo *= bsdf_microfacet_estimate_fresnel(sd, (ccl_private const MicrofacetBsdf *)sc);
albedo *= bsdf_microfacet_estimate_fresnel(
sd, (ccl_private const MicrofacetBsdf *)sc, reflection, transmission);
}
else if (sc->type == CLOSURE_BSDF_PRINCIPLED_SHEEN_ID) {
kernel_assert(reflection);
albedo *= ((ccl_private const PrincipledSheenBsdf *)sc)->avg_value;
}
else if (sc->type == CLOSURE_BSDF_HAIR_PRINCIPLED_ID) {
/* TODO(lukas): Principled Hair could also be split into a glossy and a transmission component,
* similar to Glass BSDFs. */
albedo *= bsdf_principled_hair_albedo(sd, sc);
}
#endif

View File

@ -338,17 +338,20 @@ ccl_device_inline void microfacet_ggx_preserve_energy(KernelGlobals kg,
* For better results, we'd be blending between this and Fss based on roughness, but that
* would involve storing or recomputing Fss, which is probably not worth it. */
ccl_device Spectrum bsdf_microfacet_estimate_fresnel(ccl_private const ShaderData *sd,
ccl_private const MicrofacetBsdf *bsdf)
ccl_private const MicrofacetBsdf *bsdf,
const bool reflection,
const bool transmission)
{
const bool is_glass = CLOSURE_IS_GLASS(bsdf->type);
const bool is_refractive = CLOSURE_IS_REFRACTIVE(bsdf->type);
const bool m_refraction = CLOSURE_IS_REFRACTION(bsdf->type);
const bool m_glass = CLOSURE_IS_GLASS(bsdf->type);
const bool m_reflection = !(m_refraction || m_glass);
Spectrum albedo = zero_spectrum();
if (!is_refractive || is_glass) {
if (reflection && (m_reflection || m_glass)) {
/* BSDF has a reflective lobe. */
albedo += microfacet_fresnel(bsdf, sd->wi, bsdf->N, false);
}
if (is_refractive) {
if (transmission && (m_refraction || m_glass)) {
/* BSDF has a refractive lobe (unless there's TIR). */
albedo += microfacet_fresnel(bsdf, sd->wi, bsdf->N, true);
}
@ -455,8 +458,12 @@ ccl_device Spectrum bsdf_microfacet_eval(ccl_private const ShaderClosure *sc,
}
ccl_private const MicrofacetBsdf *bsdf = (ccl_private const MicrofacetBsdf *)sc;
const bool m_refractive = CLOSURE_IS_REFRACTIVE(bsdf->type);
/* Refraction: Only consider BTDF
* Glass: Consider both BRDF and BTDF, mix based on Fresnel
* Reflection: Only consider BRDF */
const bool m_refraction = CLOSURE_IS_REFRACTION(bsdf->type);
const bool m_glass = CLOSURE_IS_GLASS(bsdf->type);
const bool m_reflection = !(m_refraction || m_glass);
const float3 N = bsdf->N;
const float cos_NI = dot(N, wi);
@ -466,7 +473,7 @@ ccl_device Spectrum bsdf_microfacet_eval(ccl_private const ShaderClosure *sc,
const float alpha_x = bsdf->alpha_x;
const float alpha_y = bsdf->alpha_y;
const bool is_refraction = (cos_NO < 0.0f);
const bool is_transmission = (cos_NO < 0.0f);
/* Check whether the pair of directions is valid for evaluation:
* - Incoming direction has to be in the upper hemisphere (Cycles convention)
@ -475,15 +482,15 @@ 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 <= 5e-7f) || ((cos_NgO < 0.0f) != is_refraction) ||
(is_refraction && !m_refractive) || (!is_refraction && m_refractive && !m_glass))
if ((cos_NI <= 0) || (alpha_x * alpha_y <= 5e-7f) || ((cos_NgO < 0.0f) != is_transmission) ||
(is_transmission && m_reflection) || (!is_transmission && m_refraction))
{
*pdf = 0.0f;
return zero_spectrum();
}
/* Compute half vector. */
float3 H = is_refraction ? -(bsdf->ior * wo + wi) : (wi + wo);
float3 H = is_transmission ? -(bsdf->ior * wo + wi) : (wi + wo);
const float inv_len_H = 1.0f / len(H);
H *= inv_len_H;
@ -491,7 +498,7 @@ ccl_device Spectrum bsdf_microfacet_eval(ccl_private const ShaderClosure *sc,
float D, lambdaI, lambdaO;
/* TODO: add support for anisotropic transmission. */
if (alpha_x == alpha_y || is_refraction) { /* Isotropic. */
if (alpha_x == alpha_y || is_transmission) { /* Isotropic. */
float alpha2 = alpha_x * alpha_y;
if (bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID) {
@ -523,19 +530,19 @@ ccl_device Spectrum bsdf_microfacet_eval(ccl_private const ShaderClosure *sc,
}
float common = D / cos_NI *
(is_refraction ? sqr(bsdf->ior * inv_len_H) * fabsf(dot(H, wi) * dot(H, wo)) :
0.25f);
(is_transmission ? sqr(bsdf->ior * inv_len_H) * fabsf(dot(H, wi) * dot(H, wo)) :
0.25f);
float lobe_pdf = 1.0f;
if (m_glass) {
float fresnel = fresnel_dielectric_cos(dot(H, wi), bsdf->ior);
float reflect_pdf = (fresnel == 1.0f) ? 1.0f : clamp(fresnel, 0.125f, 0.875f);
lobe_pdf = is_refraction ? (1.0f - reflect_pdf) : reflect_pdf;
lobe_pdf = is_transmission ? (1.0f - reflect_pdf) : reflect_pdf;
}
*pdf = common * lobe_pdf / (1.0f + lambdaI);
const Spectrum F = microfacet_fresnel(bsdf, wi, H, is_refraction);
const Spectrum F = microfacet_fresnel(bsdf, wi, H, is_transmission);
return F * common / (1.0f + lambdaO + lambdaI);
}
@ -554,7 +561,9 @@ ccl_device int bsdf_microfacet_sample(ccl_private const ShaderClosure *sc,
ccl_private const MicrofacetBsdf *bsdf = (ccl_private const MicrofacetBsdf *)sc;
const float m_eta = bsdf->ior;
const bool m_refractive = CLOSURE_IS_REFRACTIVE(bsdf->type);
const bool m_refraction = CLOSURE_IS_REFRACTION(bsdf->type);
const bool m_glass = CLOSURE_IS_GLASS(bsdf->type);
const bool m_reflection = !(m_refraction || m_glass);
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 <= 5e-7f);
@ -564,7 +573,7 @@ ccl_device int bsdf_microfacet_sample(ccl_private const ShaderClosure *sc,
if (cos_NI <= 0) {
*eval = zero_spectrum();
*pdf = 0.0f;
return (m_refractive ? LABEL_TRANSMIT : LABEL_REFLECT) |
return (m_reflection ? LABEL_REFLECT : LABEL_TRANSMIT) |
(m_singular ? LABEL_SINGULAR : LABEL_GLOSSY);
}
@ -603,13 +612,13 @@ ccl_device int bsdf_microfacet_sample(ccl_private const ShaderClosure *sc,
bool valid;
bool do_refract;
float lobe_pdf;
if (m_refractive) {
if (m_refraction || m_glass) {
bool inside;
float fresnel = fresnel_dielectric(m_eta, H, wi, wo, &inside);
valid = !inside;
/* For glass closures, we decide between reflection and refraction here. */
if (CLOSURE_IS_GLASS(bsdf->type)) {
if (m_glass) {
if (fresnel == 1.0f) {
/* TIR, reflection is the only option. */
do_refract = false;
@ -725,7 +734,7 @@ ccl_device void bsdf_microfacet_setup_fresnel_conductor(KernelGlobals kg,
{
bsdf->fresnel_type = MicrofacetFresnel::CONDUCTOR;
bsdf->fresnel = fresnel;
bsdf->sample_weight *= average(bsdf_microfacet_estimate_fresnel(sd, bsdf));
bsdf->sample_weight *= average(bsdf_microfacet_estimate_fresnel(sd, bsdf, true, true));
if (preserve_energy) {
/* In order to estimate Fss of the conductor, we fit the F82-tint model to it based on the
@ -748,7 +757,7 @@ ccl_device void bsdf_microfacet_setup_fresnel_dielectric_tint(
{
bsdf->fresnel_type = MicrofacetFresnel::DIELECTRIC_TINT;
bsdf->fresnel = fresnel;
bsdf->sample_weight *= average(bsdf_microfacet_estimate_fresnel(sd, bsdf));
bsdf->sample_weight *= average(bsdf_microfacet_estimate_fresnel(sd, bsdf, true, true));
if (preserve_energy) {
/* Assume that the transmissive tint makes up most of the overall color. */
@ -765,7 +774,7 @@ ccl_device void bsdf_microfacet_setup_fresnel_generalized_schlick(
{
bsdf->fresnel_type = MicrofacetFresnel::GENERALIZED_SCHLICK;
bsdf->fresnel = fresnel;
bsdf->sample_weight *= average(bsdf_microfacet_estimate_fresnel(sd, bsdf));
bsdf->sample_weight *= average(bsdf_microfacet_estimate_fresnel(sd, bsdf, true, true));
if (preserve_energy) {
Spectrum Fss = one_spectrum();
@ -852,7 +861,7 @@ ccl_device int bsdf_microfacet_ggx_clearcoat_setup(ccl_private MicrofacetBsdf *b
bsdf->fresnel_type = MicrofacetFresnel::DIELECTRIC;
bsdf->energy_scale = 1.0f;
bsdf->type = CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID;
bsdf->sample_weight *= average(bsdf_microfacet_estimate_fresnel(sd, bsdf));
bsdf->sample_weight *= average(bsdf_microfacet_estimate_fresnel(sd, bsdf, true, true));
return SD_BSDF | SD_BSDF_HAS_EVAL;
}

View File

@ -67,7 +67,7 @@ ccl_device_forceinline void film_write_denoising_features_surface(KernelGlobals
}
}
Spectrum closure_albedo = bsdf_albedo(sd, sc);
Spectrum closure_albedo = bsdf_albedo(sd, sc, true, true);
if (bsdf_get_specular_roughness_squared(sc) > sqr(0.075f)) {
diffuse_albedo += closure_albedo;
sum_nonspecular_weight += sc->sample_weight;

View File

@ -20,36 +20,61 @@ CCL_NAMESPACE_BEGIN
* them separately. */
ccl_device_inline void bsdf_eval_init(ccl_private BsdfEval *eval,
const ClosureType closure_type,
const ShaderClosure *sc,
const float3 wo,
Spectrum value)
{
eval->diffuse = zero_spectrum();
eval->glossy = zero_spectrum();
if (CLOSURE_IS_BSDF_DIFFUSE(closure_type)) {
if (CLOSURE_IS_BSDF_DIFFUSE(sc->type)) {
eval->diffuse = value;
}
else if (CLOSURE_IS_BSDF_GLOSSY(closure_type)) {
else if (CLOSURE_IS_BSDF_GLOSSY(sc->type)) {
eval->glossy = value;
}
else if (CLOSURE_IS_GLASS(sc->type)) {
/* Glass can count as glossy or transmission, depending on which side we end up on. */
if (dot(sc->N, wo) > 0.0f) {
eval->glossy = value;
}
}
eval->sum = value;
}
ccl_device_inline void bsdf_eval_init(ccl_private BsdfEval *eval, Spectrum value)
{
eval->diffuse = zero_spectrum();
eval->glossy = zero_spectrum();
eval->sum = value;
}
ccl_device_inline void bsdf_eval_accum(ccl_private BsdfEval *eval,
const ClosureType closure_type,
const ShaderClosure *sc,
const float3 wo,
Spectrum value)
{
if (CLOSURE_IS_BSDF_DIFFUSE(closure_type)) {
if (CLOSURE_IS_BSDF_DIFFUSE(sc->type)) {
eval->diffuse += value;
}
else if (CLOSURE_IS_BSDF_GLOSSY(closure_type)) {
else if (CLOSURE_IS_BSDF_GLOSSY(sc->type)) {
eval->glossy += value;
}
else if (CLOSURE_IS_GLASS(sc->type)) {
if (dot(sc->N, wo) > 0.0f) {
eval->glossy += value;
}
}
eval->sum += value;
}
ccl_device_inline void bsdf_eval_accum(ccl_private BsdfEval *eval, Spectrum value)
{
eval->sum += value;
}
ccl_device_inline bool bsdf_eval_is_zero(ccl_private BsdfEval *eval)
{
return is_zero(eval->sum);

View File

@ -979,7 +979,7 @@ ccl_device_forceinline int kernel_path_mnee_sample(KernelGlobals kg,
bool found_refractive_microfacet_bsdf = false;
for (int ci = 0; ci < sd_mnee->num_closure; ci++) {
ccl_private ShaderClosure *bsdf = &sd_mnee->closure[ci];
if (CLOSURE_IS_REFRACTIVE(bsdf->type)) {
if (CLOSURE_IS_REFRACTION(bsdf->type) || CLOSURE_IS_GLASS(bsdf->type)) {
/* Note that Glass closures are treated as refractive further below. */
found_refractive_microfacet_bsdf = true;

View File

@ -140,11 +140,12 @@ ccl_device_inline void surface_shader_prepare_closures(KernelGlobals kg,
{
/* Filter out closures. */
if (kernel_data.integrator.filter_closures) {
if (kernel_data.integrator.filter_closures & FILTER_CLOSURE_EMISSION) {
const int filter_closures = kernel_data.integrator.filter_closures;
if (filter_closures & FILTER_CLOSURE_EMISSION) {
sd->closure_emission_background = zero_spectrum();
}
if (kernel_data.integrator.filter_closures & FILTER_CLOSURE_DIRECT_LIGHT) {
if (filter_closures & FILTER_CLOSURE_DIRECT_LIGHT) {
sd->flag &= ~SD_BSDF_HAS_EVAL;
}
@ -152,19 +153,20 @@ ccl_device_inline void surface_shader_prepare_closures(KernelGlobals kg,
for (int i = 0; i < sd->num_closure; i++) {
ccl_private ShaderClosure *sc = &sd->closure[i];
if ((CLOSURE_IS_BSDF_DIFFUSE(sc->type) &&
(kernel_data.integrator.filter_closures & FILTER_CLOSURE_DIFFUSE)) ||
(CLOSURE_IS_BSDF_GLOSSY(sc->type) &&
(kernel_data.integrator.filter_closures & FILTER_CLOSURE_GLOSSY)) ||
(CLOSURE_IS_BSDF_TRANSMISSION(sc->type) &&
(kernel_data.integrator.filter_closures & FILTER_CLOSURE_TRANSMISSION)))
const bool filter_diffuse = (filter_closures & FILTER_CLOSURE_DIFFUSE);
const bool filter_glossy = (filter_closures & FILTER_CLOSURE_GLOSSY);
const bool filter_transmission = (filter_closures & FILTER_CLOSURE_TRANSMISSION);
const bool filter_glass = filter_glossy && filter_transmission;
if ((CLOSURE_IS_BSDF_DIFFUSE(sc->type) && filter_diffuse) ||
(CLOSURE_IS_BSDF_GLOSSY(sc->type) && filter_glossy) ||
(CLOSURE_IS_BSDF_TRANSMISSION(sc->type) && filter_transmission) ||
(CLOSURE_IS_GLASS(sc->type) && filter_glass))
{
sc->type = CLOSURE_NONE_ID;
sc->sample_weight = 0.0f;
}
else if ((CLOSURE_IS_BSDF_TRANSPARENT(sc->type) &&
(kernel_data.integrator.filter_closures & FILTER_CLOSURE_TRANSPARENT)))
{
(filter_closures & FILTER_CLOSURE_TRANSPARENT))) {
sc->type = CLOSURE_HOLDOUT_ID;
sc->sample_weight = 0.0f;
sd->flag |= SD_HOLDOUT;
@ -268,6 +270,13 @@ ccl_device_forceinline bool _surface_shader_exclude(ClosureType type, uint light
return true;
}
}
/* Glass closures are both glossy and transmissive, so only exclude them if both are filtered. */
const uint exclude_glass = SHADER_EXCLUDE_TRANSMIT | SHADER_EXCLUDE_GLOSSY;
if ((light_shader_flags & exclude_glass) == exclude_glass) {
if (CLOSURE_IS_GLASS(type)) {
return true;
}
}
return false;
}
@ -295,7 +304,7 @@ ccl_device_inline float _surface_shader_bsdf_eval_mis(KernelGlobals kg,
Spectrum eval = bsdf_eval(kg, sd, sc, wo, &bsdf_pdf);
if (bsdf_pdf != 0.0f) {
bsdf_eval_accum(result_eval, sc->type, eval * sc->weight);
bsdf_eval_accum(result_eval, sc, wo, eval * sc->weight);
sum_pdf += bsdf_pdf * sc->sample_weight;
}
}
@ -318,7 +327,7 @@ ccl_device_inline float surface_shader_bsdf_eval_pdfs(const KernelGlobals kg,
* factors drop out when using balance heuristic weighting. */
float sum_pdf = 0.0f;
float sum_sample_weight = 0.0f;
bsdf_eval_init(result_eval, CLOSURE_NONE_ID, zero_spectrum());
bsdf_eval_init(result_eval, zero_spectrum());
for (int i = 0; i < sd->num_closure; i++) {
ccl_private const ShaderClosure *sc = &sd->closure[i];
@ -328,7 +337,7 @@ ccl_device_inline float surface_shader_bsdf_eval_pdfs(const KernelGlobals kg,
Spectrum eval = bsdf_eval(kg, sd, sc, wo, &bsdf_pdf);
kernel_assert(bsdf_pdf >= 0.0f);
if (bsdf_pdf != 0.0f) {
bsdf_eval_accum(result_eval, sc->type, eval * sc->weight);
bsdf_eval_accum(result_eval, sc, wo, eval * sc->weight);
sum_pdf += bsdf_pdf * sc->sample_weight;
kernel_assert(bsdf_pdf * sc->sample_weight >= 0.0f);
pdfs[i] = bsdf_pdf * sc->sample_weight;
@ -369,7 +378,7 @@ ccl_device_inline
ccl_private BsdfEval *bsdf_eval,
const uint light_shader_flags)
{
bsdf_eval_init(bsdf_eval, CLOSURE_NONE_ID, zero_spectrum());
bsdf_eval_init(bsdf_eval, zero_spectrum());
float pdf = _surface_shader_bsdf_eval_mis(
kg, sd, wo, NULL, bsdf_eval, 0.0f, 0.0f, light_shader_flags);
@ -499,7 +508,7 @@ ccl_device int surface_shader_bsdf_guided_sample_closure_mis(KernelGlobals kg,
/* Initialize to zero. */
int label = LABEL_NONE;
Spectrum eval = zero_spectrum();
bsdf_eval_init(bsdf_eval, CLOSURE_NONE_ID, eval);
bsdf_eval_init(bsdf_eval, eval);
*unguided_bsdf_pdf = 0.0f;
float guide_pdf = 0.0f;
@ -570,7 +579,7 @@ ccl_device int surface_shader_bsdf_guided_sample_closure_mis(KernelGlobals kg,
# endif
if (*unguided_bsdf_pdf != 0.0f) {
bsdf_eval_init(bsdf_eval, sc->type, eval * sc->weight);
bsdf_eval_init(bsdf_eval, sc, *wo, eval * sc->weight);
kernel_assert(reduce_min(bsdf_eval_sum(bsdf_eval)) >= 0.0f);
@ -622,7 +631,7 @@ ccl_device int surface_shader_bsdf_guided_sample_closure_ris(KernelGlobals kg,
/* Initialize to zero. */
int label = LABEL_NONE;
Spectrum eval = zero_spectrum();
bsdf_eval_init(bsdf_eval, CLOSURE_NONE_ID, eval);
bsdf_eval_init(bsdf_eval, eval);
*unguided_bsdf_pdf = 0.0f;
float guide_pdf = 0.0f;
@ -652,7 +661,8 @@ ccl_device int surface_shader_bsdf_guided_sample_closure_ris(KernelGlobals kg,
&ris_samples[0].sampled_roughness,
&ris_samples[0].eta);
bsdf_eval_init(&ris_samples[0].bsdf_eval, sc->type, ris_samples[0].eval * sc->weight);
bsdf_eval_init(
&ris_samples[0].bsdf_eval, sc, ris_samples[0].wo, ris_samples[0].eval * sc->weight);
if (ris_samples[0].bsdf_pdf > 0.0f) {
if (sd->num_closure > 1) {
float sweight = sc->sample_weight;
@ -679,7 +689,7 @@ ccl_device int surface_shader_bsdf_guided_sample_closure_ris(KernelGlobals kg,
// generate the second RIS candidate using a sample from the guiding distribution
// ------------------------------------------------------------------------------
float unguided_bsdf_pdfs[MAX_CLOSURE];
bsdf_eval_init(&ris_samples[1].bsdf_eval, CLOSURE_NONE_ID, eval);
bsdf_eval_init(&ris_samples[1].bsdf_eval, eval);
ris_samples[1].guide_pdf = guiding_bsdf_sample(
kg, state, float3_to_float2(ris_samples[1].rand), &ris_samples[1].wo);
ris_samples[1].guide_pdf *= (1.0f - bssrdf_sampling_prob);
@ -812,7 +822,7 @@ ccl_device int surface_shader_bsdf_guided_sample_closure_ris(KernelGlobals kg,
# endif
if (*unguided_bsdf_pdf != 0.0f) {
bsdf_eval_init(bsdf_eval, sc->type, eval * sc->weight);
bsdf_eval_init(bsdf_eval, sc, *wo, eval * sc->weight);
kernel_assert(reduce_min(bsdf_eval_sum(bsdf_eval)) >= 0.0f);
@ -914,7 +924,7 @@ ccl_device int surface_shader_bsdf_sample_closure(KernelGlobals kg,
label = bsdf_sample(kg, sd, sc, path_flag, rand_bsdf, &eval, wo, pdf, sampled_roughness, eta);
if (*pdf != 0.0f) {
bsdf_eval_init(bsdf_eval, sc->type, eval * sc->weight);
bsdf_eval_init(bsdf_eval, sc, *wo, eval * sc->weight);
if (sd->num_closure > 1) {
float sweight = sc->sample_weight;
@ -922,7 +932,7 @@ ccl_device int surface_shader_bsdf_sample_closure(KernelGlobals kg,
}
}
else {
bsdf_eval_init(bsdf_eval, sc->type, zero_spectrum());
bsdf_eval_init(bsdf_eval, zero_spectrum());
}
return label;
@ -994,7 +1004,7 @@ ccl_device Spectrum surface_shader_diffuse(KernelGlobals kg, ccl_private const S
ccl_private const ShaderClosure *sc = &sd->closure[i];
if (CLOSURE_IS_BSDF_DIFFUSE(sc->type) || CLOSURE_IS_BSSRDF(sc->type))
eval += bsdf_albedo(sd, sc);
eval += bsdf_albedo(sd, sc, true, true);
}
return eval;
@ -1007,8 +1017,8 @@ ccl_device Spectrum surface_shader_glossy(KernelGlobals kg, ccl_private const Sh
for (int i = 0; i < sd->num_closure; i++) {
ccl_private const ShaderClosure *sc = &sd->closure[i];
if (CLOSURE_IS_BSDF_GLOSSY(sc->type))
eval += bsdf_albedo(sd, sc);
if (CLOSURE_IS_BSDF_GLOSSY(sc->type) || CLOSURE_IS_GLASS(sc->type))
eval += bsdf_albedo(sd, sc, true, false);
}
return eval;
@ -1021,8 +1031,8 @@ ccl_device Spectrum surface_shader_transmission(KernelGlobals kg, ccl_private co
for (int i = 0; i < sd->num_closure; i++) {
ccl_private const ShaderClosure *sc = &sd->closure[i];
if (CLOSURE_IS_BSDF_TRANSMISSION(sc->type))
eval += bsdf_albedo(sd, sc);
if (CLOSURE_IS_BSDF_TRANSMISSION(sc->type) || CLOSURE_IS_GLASS(sc->type))
eval += bsdf_albedo(sd, sc, false, true);
}
return eval;

View File

@ -217,7 +217,7 @@ ccl_device_inline float _volume_shader_phase_eval_mis(ccl_private const ShaderDa
Spectrum eval = volume_phase_eval(sd, svc, wo, &phase_pdf);
if (phase_pdf != 0.0f) {
bsdf_eval_accum(result_eval, CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID, eval);
bsdf_eval_accum(result_eval, eval);
sum_pdf += phase_pdf * svc->sample_weight;
}
@ -237,7 +237,7 @@ ccl_device float volume_shader_phase_eval(KernelGlobals kg,
Spectrum eval = volume_phase_eval(sd, svc, wo, &phase_pdf);
if (phase_pdf != 0.0f) {
bsdf_eval_accum(phase_eval, CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID, eval);
bsdf_eval_accum(phase_eval, eval);
}
return phase_pdf;
@ -250,7 +250,7 @@ ccl_device float volume_shader_phase_eval(KernelGlobals kg,
const float3 wo,
ccl_private BsdfEval *phase_eval)
{
bsdf_eval_init(phase_eval, CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID, zero_spectrum());
bsdf_eval_init(phase_eval, zero_spectrum());
float pdf = _volume_shader_phase_eval_mis(sd, phases, wo, -1, phase_eval, 0.0f, 0.0f);
@ -300,7 +300,7 @@ ccl_device int volume_shader_phase_guided_sample(KernelGlobals kg,
float guide_pdf = 0.0f;
*sampled_roughness = 1.0f - fabsf(svc->g);
bsdf_eval_init(phase_eval, CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID, zero_spectrum());
bsdf_eval_init(phase_eval, zero_spectrum());
if (sample_guiding) {
/* Sample guiding distribution. */
@ -320,7 +320,7 @@ ccl_device int volume_shader_phase_guided_sample(KernelGlobals kg,
label = volume_phase_sample(sd, svc, rand_phase, &eval, wo, unguided_phase_pdf);
if (*unguided_phase_pdf != 0.0f) {
bsdf_eval_init(phase_eval, CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID, eval);
bsdf_eval_init(phase_eval, eval);
*phase_pdf = *unguided_phase_pdf;
if (use_volume_guiding) {
@ -332,7 +332,7 @@ ccl_device int volume_shader_phase_guided_sample(KernelGlobals kg,
kernel_assert(reduce_min(bsdf_eval_sum(phase_eval)) >= 0.0f);
}
else {
bsdf_eval_init(phase_eval, CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID, zero_spectrum());
bsdf_eval_init(phase_eval, zero_spectrum());
}
kernel_assert(reduce_min(bsdf_eval_sum(phase_eval)) >= 0.0f);
@ -359,7 +359,7 @@ ccl_device int volume_shader_phase_sample(KernelGlobals kg,
int label = volume_phase_sample(sd, svc, rand_phase, &eval, wo, pdf);
if (*pdf != 0.0f) {
bsdf_eval_init(phase_eval, CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID, eval);
bsdf_eval_init(phase_eval, eval);
}
return label;

View File

@ -113,11 +113,13 @@ file(GLOB SRC_OSL_HEADER_DIST ${OSL_SHADER_DIR}/*.h)
set(SRC_OSL_HEADERS
node_color.h
node_color_blend.h
node_fractal_voronoi.h
node_fresnel.h
node_hash.h
node_math.h
node_noise.h
node_ramp_util.h
node_voronoi.h
stdcycles.h
${SRC_OSL_HEADER_DIST}
)

View File

@ -0,0 +1,137 @@
/* SPDX-License-Identifier: Apache-2.0
* Copyright 2011-2022 Blender Foundation */
#include "node_voronoi.h"
#include "stdcycles.h"
#include "vector2.h"
#include "vector4.h"
#define vector3 point
#define FRACTAL_VORONOI_X_FX(T) \
VoronoiOutput fractal_voronoi_x_fx(VoronoiParams params, T coord) \
{ \
float amplitude = 1.0; \
float max_amplitude = 0.0; \
float scale = 1.0; \
\
VoronoiOutput Output; \
Output.Distance = 0.0; \
Output.Color = color(0.0, 0.0, 0.0); \
Output.Position = vector4(0.0, 0.0, 0.0, 0.0); \
int zero_input = params.detail == 0.0 || params.roughness == 0.0 || params.lacunarity == 0.0; \
\
for (int i = 0; i <= ceil(params.detail); ++i) { \
VoronoiOutput octave; \
if (params.feature == "f1") { \
octave = voronoi_f1(params, coord * scale); \
} \
else if (params.feature == "smooth_f1") { \
octave = voronoi_smooth_f1(params, coord * scale); \
} \
else { \
octave = voronoi_f2(params, coord * scale); \
} \
\
if (zero_input) { \
max_amplitude = 1.0; \
Output = octave; \
break; \
} \
else if (i <= params.detail) { \
max_amplitude += amplitude; \
Output.Distance += octave.Distance * amplitude; \
Output.Color += octave.Color * amplitude; \
Output.Position = mix(Output.Position, octave.Position / scale, amplitude); \
scale *= params.lacunarity; \
amplitude *= params.roughness; \
} \
else { \
float remainder = params.detail - floor(params.detail); \
if (remainder != 0.0) { \
max_amplitude = mix(max_amplitude, max_amplitude + amplitude, remainder); \
Output.Distance = mix( \
Output.Distance, Output.Distance + octave.Distance * amplitude, remainder); \
Output.Color = mix(Output.Color, Output.Color + octave.Color * amplitude, remainder); \
Output.Position = mix(Output.Position, \
mix(Output.Position, octave.Position / scale, amplitude), \
remainder); \
} \
} \
} \
\
if (params.normalize) { \
Output.Distance /= max_amplitude * params.max_distance; \
Output.Color /= max_amplitude; \
} \
\
Output.Position = safe_divide(Output.Position, params.scale); \
\
return Output; \
}
#define FRACTAL_VORONOI_DISTANCE_TO_EDGE_FUNCTION(T) \
float fractal_voronoi_distance_to_edge(VoronoiParams params, T coord) \
{ \
float amplitude = 1.0; \
float max_amplitude = 0.5 + 0.5 * params.randomness; \
float scale = 1.0; \
float distance = 8.0; \
\
int zero_input = params.detail == 0.0 || params.roughness == 0.0 || params.lacunarity == 0.0; \
\
for (int i = 0; i <= ceil(params.detail); ++i) { \
float octave_distance = voronoi_distance_to_edge(params, coord * scale); \
\
if (zero_input) { \
distance = octave_distance; \
break; \
} \
else if (i <= params.detail) { \
max_amplitude = mix(max_amplitude, (0.5 + 0.5 * params.randomness) / scale, amplitude); \
distance = mix(distance, min(distance, octave_distance / scale), amplitude); \
scale *= params.lacunarity; \
amplitude *= params.roughness; \
} \
else { \
float remainder = params.detail - floor(params.detail); \
if (remainder != 0.0) { \
float lerp_amplitude = mix( \
max_amplitude, (0.5 + 0.5 * params.randomness) / scale, amplitude); \
max_amplitude = mix(max_amplitude, lerp_amplitude, remainder); \
float lerp_distance = mix(distance, min(distance, octave_distance / scale), amplitude); \
distance = mix(distance, min(distance, lerp_distance), remainder); \
} \
} \
} \
\
if (params.normalize) { \
distance /= max_amplitude; \
} \
\
return distance; \
}
/* **** 1D Fractal Voronoi **** */
FRACTAL_VORONOI_X_FX(float)
FRACTAL_VORONOI_DISTANCE_TO_EDGE_FUNCTION(float)
/* **** 2D Fractal Voronoi **** */
FRACTAL_VORONOI_X_FX(vector2)
FRACTAL_VORONOI_DISTANCE_TO_EDGE_FUNCTION(vector2)
/* **** 3D Fractal Voronoi **** */
FRACTAL_VORONOI_X_FX(vector3)
FRACTAL_VORONOI_DISTANCE_TO_EDGE_FUNCTION(vector3)
/* **** 4D Fractal Voronoi **** */
FRACTAL_VORONOI_X_FX(vector4)
FRACTAL_VORONOI_DISTANCE_TO_EDGE_FUNCTION(vector4)

View File

@ -0,0 +1,920 @@
/* SPDX-License-Identifier: Apache-2.0
* Copyright 2011-2022 Blender Foundation */
#include "node_hash.h"
#include "stdcycles.h"
#include "vector2.h"
#include "vector4.h"
#define vector3 point
struct VoronoiParams {
float scale;
float detail;
float roughness;
float lacunarity;
float smoothness;
float exponent;
float randomness;
float max_distance;
int normalize;
string feature;
string metric;
};
struct VoronoiOutput {
float Distance;
color Color;
vector4 Position;
};
/* **** Distance Functions **** */
float distance(float a, float b)
{
return abs(a - b);
}
float distance(vector2 a, vector2 b)
{
return length(a - b);
}
float distance(vector4 a, vector4 b)
{
return length(a - b);
}
float voronoi_distance(float a, float b)
{
return abs(a - b);
}
float voronoi_distance(vector2 a, vector2 b, VoronoiParams params)
{
if (params.metric == "euclidean") {
return distance(a, b);
}
else if (params.metric == "manhattan") {
return abs(a.x - b.x) + abs(a.y - b.y);
}
else if (params.metric == "chebychev") {
return max(abs(a.x - b.x), abs(a.y - b.y));
}
else if (params.metric == "minkowski") {
return pow(pow(abs(a.x - b.x), params.exponent) + pow(abs(a.y - b.y), params.exponent),
1.0 / params.exponent);
}
else {
return 0.0;
}
}
float voronoi_distance(vector3 a, vector3 b, VoronoiParams params)
{
if (params.metric == "euclidean") {
return distance(a, b);
}
else if (params.metric == "manhattan") {
return abs(a[0] - b[0]) + abs(a[1] - b[1]) + abs(a[2] - b[2]);
}
else if (params.metric == "chebychev") {
return max(abs(a[0] - b[0]), max(abs(a[1] - b[1]), abs(a[2] - b[2])));
}
else if (params.metric == "minkowski") {
return pow(pow(abs(a[0] - b[0]), params.exponent) + pow(abs(a[1] - b[1]), params.exponent) +
pow(abs(a[2] - b[2]), params.exponent),
1.0 / params.exponent);
}
else {
return 0.0;
}
}
float voronoi_distance(vector4 a, vector4 b, VoronoiParams params)
{
if (params.metric == "euclidean") {
return distance(a, b);
}
else if (params.metric == "manhattan") {
return abs(a.x - b.x) + abs(a.y - b.y) + abs(a.z - b.z) + abs(a.w - b.w);
}
else if (params.metric == "chebychev") {
return max(abs(a.x - b.x), max(abs(a.y - b.y), max(abs(a.z - b.z), abs(a.w - b.w))));
}
else if (params.metric == "minkowski") {
return pow(pow(abs(a.x - b.x), params.exponent) + pow(abs(a.y - b.y), params.exponent) +
pow(abs(a.z - b.z), params.exponent) + pow(abs(a.w - b.w), params.exponent),
1.0 / params.exponent);
}
else {
return 0.0;
}
}
/* **** Safe Division **** */
vector2 safe_divide(vector2 a, float b)
{
return vector2((b != 0.0) ? a.x / b : 0.0, (b != 0.0) ? a.y / b : 0.0);
}
vector4 safe_divide(vector4 a, float b)
{
return vector4((b != 0.0) ? a.x / b : 0.0,
(b != 0.0) ? a.y / b : 0.0,
(b != 0.0) ? a.z / b : 0.0,
(b != 0.0) ? a.w / b : 0.0);
}
/*
* SPDX-License-Identifier: MIT
* Original code is copyright (c) 2013 Inigo Quilez.
*
* Smooth Voronoi:
* - https://wiki.blender.org/wiki/User:OmarSquircleArt/GSoC2019/Documentation/Smooth_Voronoi
*
* Distance To Edge based on:
*
* - https://www.iquilezles.org/www/articles/voronoilines/voronoilines.htm
* - https://www.shadertoy.com/view/ldl3W8
*
* With optimization to change -2..2 scan window to -1..1 for better performance,
* as explained in https://www.shadertoy.com/view/llG3zy.
*/
/* **** 1D Voronoi **** */
vector4 voronoi_position(float coord)
{
return vector4(0.0, 0.0, 0.0, coord);
}
VoronoiOutput voronoi_f1(VoronoiParams params, float coord)
{
float cellPosition = floor(coord);
float localPosition = coord - cellPosition;
float minDistance = 8.0;
float targetOffset = 0.0;
float targetPosition = 0.0;
for (int i = -1; i <= 1; i++) {
float cellOffset = i;
float pointPosition = cellOffset +
hash_float_to_float(cellPosition + cellOffset) * params.randomness;
float distanceToPoint = voronoi_distance(pointPosition, localPosition);
if (distanceToPoint < minDistance) {
targetOffset = cellOffset;
minDistance = distanceToPoint;
targetPosition = pointPosition;
}
}
VoronoiOutput octave;
octave.Distance = minDistance;
octave.Color = hash_float_to_color(cellPosition + targetOffset);
octave.Position = voronoi_position(targetPosition + cellPosition);
return octave;
}
VoronoiOutput voronoi_smooth_f1(VoronoiParams params, float coord)
{
float cellPosition = floor(coord);
float localPosition = coord - cellPosition;
float smoothDistance = 8.0;
float smoothPosition = 0.0;
vector3 smoothColor = vector3(0.0, 0.0, 0.0);
for (int i = -2; i <= 2; i++) {
float cellOffset = i;
float pointPosition = cellOffset +
hash_float_to_float(cellPosition + cellOffset) * params.randomness;
float distanceToPoint = voronoi_distance(pointPosition, localPosition);
float h = smoothstep(
0.0, 1.0, 0.5 + 0.5 * (smoothDistance - distanceToPoint) / params.smoothness);
float correctionFactor = params.smoothness * h * (1.0 - h);
smoothDistance = mix(smoothDistance, distanceToPoint, h) - correctionFactor;
correctionFactor /= 1.0 + 3.0 * params.smoothness;
color cellColor = hash_float_to_color(cellPosition + cellOffset);
smoothColor = mix(smoothColor, cellColor, h) - correctionFactor;
smoothPosition = mix(smoothPosition, pointPosition, h) - correctionFactor;
}
VoronoiOutput octave;
octave.Distance = smoothDistance;
octave.Color = smoothColor;
octave.Position = voronoi_position(cellPosition + smoothPosition);
return octave;
}
VoronoiOutput voronoi_f2(VoronoiParams params, float coord)
{
float cellPosition = floor(coord);
float localPosition = coord - cellPosition;
float distanceF1 = 8.0;
float distanceF2 = 8.0;
float offsetF1 = 0.0;
float positionF1 = 0.0;
float offsetF2 = 0.0;
float positionF2 = 0.0;
for (int i = -1; i <= 1; i++) {
float cellOffset = i;
float pointPosition = cellOffset +
hash_float_to_float(cellPosition + cellOffset) * params.randomness;
float distanceToPoint = voronoi_distance(pointPosition, localPosition);
if (distanceToPoint < distanceF1) {
distanceF2 = distanceF1;
distanceF1 = distanceToPoint;
offsetF2 = offsetF1;
offsetF1 = cellOffset;
positionF2 = positionF1;
positionF1 = pointPosition;
}
else if (distanceToPoint < distanceF2) {
distanceF2 = distanceToPoint;
offsetF2 = cellOffset;
positionF2 = pointPosition;
}
}
VoronoiOutput octave;
octave.Distance = distanceF2;
octave.Color = hash_float_to_color(cellPosition + offsetF2);
octave.Position = voronoi_position(positionF2 + cellPosition);
return octave;
}
float voronoi_distance_to_edge(VoronoiParams params, float coord)
{
float cellPosition = floor(coord);
float localPosition = coord - cellPosition;
float midPointPosition = hash_float_to_float(cellPosition) * params.randomness;
float leftPointPosition = -1.0 + hash_float_to_float(cellPosition - 1.0) * params.randomness;
float rightPointPosition = 1.0 + hash_float_to_float(cellPosition + 1.0) * params.randomness;
float distanceToMidLeft = abs((midPointPosition + leftPointPosition) / 2.0 - localPosition);
float distanceToMidRight = abs((midPointPosition + rightPointPosition) / 2.0 - localPosition);
return min(distanceToMidLeft, distanceToMidRight);
}
float voronoi_n_sphere_radius(VoronoiParams params, float coord)
{
float cellPosition = floor(coord);
float localPosition = coord - cellPosition;
float closestPoint = 0.0;
float closestPointOffset = 0.0;
float minDistance = 8.0;
for (int i = -1; i <= 1; i++) {
float cellOffset = i;
float pointPosition = cellOffset +
hash_float_to_float(cellPosition + cellOffset) * params.randomness;
float distanceToPoint = abs(pointPosition - localPosition);
if (distanceToPoint < minDistance) {
minDistance = distanceToPoint;
closestPoint = pointPosition;
closestPointOffset = cellOffset;
}
}
minDistance = 8.0;
float closestPointToClosestPoint = 0.0;
for (int i = -1; i <= 1; i++) {
if (i == 0) {
continue;
}
float cellOffset = i + closestPointOffset;
float pointPosition = cellOffset +
hash_float_to_float(cellPosition + cellOffset) * params.randomness;
float distanceToPoint = abs(closestPoint - pointPosition);
if (distanceToPoint < minDistance) {
minDistance = distanceToPoint;
closestPointToClosestPoint = pointPosition;
}
}
return abs(closestPointToClosestPoint - closestPoint) / 2.0;
}
/* **** 2D Voronoi **** */
vector4 voronoi_position(vector2 coord)
{
return vector4(coord.x, coord.y, 0.0, 0.0);
}
VoronoiOutput voronoi_f1(VoronoiParams params, vector2 coord)
{
vector2 cellPosition = floor(coord);
vector2 localPosition = coord - cellPosition;
float minDistance = 8.0;
vector2 targetOffset = vector2(0.0, 0.0);
vector2 targetPosition = vector2(0.0, 0.0);
for (int j = -1; j <= 1; j++) {
for (int i = -1; i <= 1; i++) {
vector2 cellOffset = vector2(i, j);
vector2 pointPosition = cellOffset + hash_vector2_to_vector2(cellPosition + cellOffset) *
params.randomness;
float distanceToPoint = voronoi_distance(pointPosition, localPosition, params);
if (distanceToPoint < minDistance) {
targetOffset = cellOffset;
minDistance = distanceToPoint;
targetPosition = pointPosition;
}
}
}
VoronoiOutput octave;
octave.Distance = minDistance;
octave.Color = hash_vector2_to_color(cellPosition + targetOffset);
octave.Position = voronoi_position(targetPosition + cellPosition);
return octave;
}
VoronoiOutput voronoi_smooth_f1(VoronoiParams params, vector2 coord)
{
vector2 cellPosition = floor(coord);
vector2 localPosition = coord - cellPosition;
float smoothDistance = 8.0;
vector3 smoothColor = vector3(0.0, 0.0, 0.0);
vector2 smoothPosition = vector2(0.0, 0.0);
for (int j = -2; j <= 2; j++) {
for (int i = -2; i <= 2; i++) {
vector2 cellOffset = vector2(i, j);
vector2 pointPosition = cellOffset + hash_vector2_to_vector2(cellPosition + cellOffset) *
params.randomness;
float distanceToPoint = voronoi_distance(pointPosition, localPosition, params);
float h = smoothstep(
0.0, 1.0, 0.5 + 0.5 * (smoothDistance - distanceToPoint) / params.smoothness);
float correctionFactor = params.smoothness * h * (1.0 - h);
smoothDistance = mix(smoothDistance, distanceToPoint, h) - correctionFactor;
correctionFactor /= 1.0 + 3.0 * params.smoothness;
color cellColor = hash_vector2_to_color(cellPosition + cellOffset);
smoothColor = mix(smoothColor, cellColor, h) - correctionFactor;
smoothPosition = mix(smoothPosition, pointPosition, h) - correctionFactor;
}
}
VoronoiOutput octave;
octave.Distance = smoothDistance;
octave.Color = smoothColor;
octave.Position = voronoi_position(cellPosition + smoothPosition);
return octave;
}
VoronoiOutput voronoi_f2(VoronoiParams params, vector2 coord)
{
vector2 cellPosition = floor(coord);
vector2 localPosition = coord - cellPosition;
float distanceF1 = 8.0;
float distanceF2 = 8.0;
vector2 offsetF1 = vector2(0.0, 0.0);
vector2 positionF1 = vector2(0.0, 0.0);
vector2 offsetF2 = vector2(0.0, 0.0);
vector2 positionF2 = vector2(0.0, 0.0);
for (int j = -1; j <= 1; j++) {
for (int i = -1; i <= 1; i++) {
vector2 cellOffset = vector2(i, j);
vector2 pointPosition = cellOffset + hash_vector2_to_vector2(cellPosition + cellOffset) *
params.randomness;
float distanceToPoint = voronoi_distance(pointPosition, localPosition, params);
if (distanceToPoint < distanceF1) {
distanceF2 = distanceF1;
distanceF1 = distanceToPoint;
offsetF2 = offsetF1;
offsetF1 = cellOffset;
positionF2 = positionF1;
positionF1 = pointPosition;
}
else if (distanceToPoint < distanceF2) {
distanceF2 = distanceToPoint;
offsetF2 = cellOffset;
positionF2 = pointPosition;
}
}
}
VoronoiOutput octave;
octave.Distance = distanceF2;
octave.Color = hash_vector2_to_color(cellPosition + offsetF2);
octave.Position = voronoi_position(positionF2 + cellPosition);
return octave;
}
float voronoi_distance_to_edge(VoronoiParams params, vector2 coord)
{
vector2 cellPosition = floor(coord);
vector2 localPosition = coord - cellPosition;
vector2 vectorToClosest = vector2(0.0, 0.0);
float minDistance = 8.0;
for (int j = -1; j <= 1; j++) {
for (int i = -1; i <= 1; i++) {
vector2 cellOffset = vector2(i, j);
vector2 vectorToPoint = cellOffset +
hash_vector2_to_vector2(cellPosition + cellOffset) *
params.randomness -
localPosition;
float distanceToPoint = dot(vectorToPoint, vectorToPoint);
if (distanceToPoint < minDistance) {
minDistance = distanceToPoint;
vectorToClosest = vectorToPoint;
}
}
}
minDistance = 8.0;
for (int j = -1; j <= 1; j++) {
for (int i = -1; i <= 1; i++) {
vector2 cellOffset = vector2(i, j);
vector2 vectorToPoint = cellOffset +
hash_vector2_to_vector2(cellPosition + cellOffset) *
params.randomness -
localPosition;
vector2 perpendicularToEdge = vectorToPoint - vectorToClosest;
if (dot(perpendicularToEdge, perpendicularToEdge) > 0.0001) {
float distanceToEdge = dot((vectorToClosest + vectorToPoint) / 2.0,
normalize(perpendicularToEdge));
minDistance = min(minDistance, distanceToEdge);
}
}
}
return minDistance;
}
float voronoi_n_sphere_radius(VoronoiParams params, vector2 coord)
{
vector2 cellPosition = floor(coord);
vector2 localPosition = coord - cellPosition;
vector2 closestPoint = vector2(0.0, 0.0);
vector2 closestPointOffset = vector2(0.0, 0.0);
float minDistance = 8.0;
for (int j = -1; j <= 1; j++) {
for (int i = -1; i <= 1; i++) {
vector2 cellOffset = vector2(i, j);
vector2 pointPosition = cellOffset + hash_vector2_to_vector2(cellPosition + cellOffset) *
params.randomness;
float distanceToPoint = distance(pointPosition, localPosition);
if (distanceToPoint < minDistance) {
minDistance = distanceToPoint;
closestPoint = pointPosition;
closestPointOffset = cellOffset;
}
}
}
minDistance = 8.0;
vector2 closestPointToClosestPoint = vector2(0.0, 0.0);
for (int j = -1; j <= 1; j++) {
for (int i = -1; i <= 1; i++) {
if (i == 0 && j == 0) {
continue;
}
vector2 cellOffset = vector2(i, j) + closestPointOffset;
vector2 pointPosition = cellOffset + hash_vector2_to_vector2(cellPosition + cellOffset) *
params.randomness;
float distanceToPoint = distance(closestPoint, pointPosition);
if (distanceToPoint < minDistance) {
minDistance = distanceToPoint;
closestPointToClosestPoint = pointPosition;
}
}
}
return distance(closestPointToClosestPoint, closestPoint) / 2.0;
}
/* **** 3D Voronoi **** */
vector4 voronoi_position(vector3 coord)
{
return vector4(coord.x, coord.y, coord.z, 0.0);
}
VoronoiOutput voronoi_f1(VoronoiParams params, vector3 coord)
{
vector3 cellPosition = floor(coord);
vector3 localPosition = coord - cellPosition;
float minDistance = 8.0;
vector3 targetOffset = vector3(0.0, 0.0, 0.0);
vector3 targetPosition = vector3(0.0, 0.0, 0.0);
for (int k = -1; k <= 1; k++) {
for (int j = -1; j <= 1; j++) {
for (int i = -1; i <= 1; i++) {
vector3 cellOffset = vector3(i, j, k);
vector3 pointPosition = cellOffset + hash_vector3_to_vector3(cellPosition + cellOffset) *
params.randomness;
float distanceToPoint = voronoi_distance(pointPosition, localPosition, params);
if (distanceToPoint < minDistance) {
targetOffset = cellOffset;
minDistance = distanceToPoint;
targetPosition = pointPosition;
}
}
}
}
VoronoiOutput octave;
octave.Distance = minDistance;
octave.Color = hash_vector3_to_color(cellPosition + targetOffset);
octave.Position = voronoi_position(targetPosition + cellPosition);
return octave;
}
VoronoiOutput voronoi_smooth_f1(VoronoiParams params, vector3 coord)
{
vector3 cellPosition = floor(coord);
vector3 localPosition = coord - cellPosition;
float smoothDistance = 8.0;
vector3 smoothColor = vector3(0.0, 0.0, 0.0);
vector3 smoothPosition = vector3(0.0, 0.0, 0.0);
for (int k = -2; k <= 2; k++) {
for (int j = -2; j <= 2; j++) {
for (int i = -2; i <= 2; i++) {
vector3 cellOffset = vector3(i, j, k);
vector3 pointPosition = cellOffset + hash_vector3_to_vector3(cellPosition + cellOffset) *
params.randomness;
float distanceToPoint = voronoi_distance(pointPosition, localPosition, params);
float h = smoothstep(
0.0, 1.0, 0.5 + 0.5 * (smoothDistance - distanceToPoint) / params.smoothness);
float correctionFactor = params.smoothness * h * (1.0 - h);
smoothDistance = mix(smoothDistance, distanceToPoint, h) - correctionFactor;
correctionFactor /= 1.0 + 3.0 * params.smoothness;
color cellColor = hash_vector3_to_color(cellPosition + cellOffset);
smoothColor = mix(smoothColor, cellColor, h) - correctionFactor;
smoothPosition = mix(smoothPosition, pointPosition, h) - correctionFactor;
}
}
}
VoronoiOutput octave;
octave.Distance = smoothDistance;
octave.Color = smoothColor;
octave.Position = voronoi_position(cellPosition + smoothPosition);
return octave;
}
VoronoiOutput voronoi_f2(VoronoiParams params, vector3 coord)
{
vector3 cellPosition = floor(coord);
vector3 localPosition = coord - cellPosition;
float distanceF1 = 8.0;
float distanceF2 = 8.0;
vector3 offsetF1 = vector3(0.0, 0.0, 0.0);
vector3 positionF1 = vector3(0.0, 0.0, 0.0);
vector3 offsetF2 = vector3(0.0, 0.0, 0.0);
vector3 positionF2 = vector3(0.0, 0.0, 0.0);
for (int k = -1; k <= 1; k++) {
for (int j = -1; j <= 1; j++) {
for (int i = -1; i <= 1; i++) {
vector3 cellOffset = vector3(i, j, k);
vector3 pointPosition = cellOffset + hash_vector3_to_vector3(cellPosition + cellOffset) *
params.randomness;
float distanceToPoint = voronoi_distance(pointPosition, localPosition, params);
if (distanceToPoint < distanceF1) {
distanceF2 = distanceF1;
distanceF1 = distanceToPoint;
offsetF2 = offsetF1;
offsetF1 = cellOffset;
positionF2 = positionF1;
positionF1 = pointPosition;
}
else if (distanceToPoint < distanceF2) {
distanceF2 = distanceToPoint;
offsetF2 = cellOffset;
positionF2 = pointPosition;
}
}
}
}
VoronoiOutput octave;
octave.Distance = distanceF2;
octave.Color = hash_vector3_to_color(cellPosition + offsetF2);
octave.Position = voronoi_position(positionF2 + cellPosition);
return octave;
}
float voronoi_distance_to_edge(VoronoiParams params, vector3 coord)
{
vector3 cellPosition = floor(coord);
vector3 localPosition = coord - cellPosition;
vector3 vectorToClosest = vector3(0.0, 0.0, 0.0);
float minDistance = 8.0;
for (int k = -1; k <= 1; k++) {
for (int j = -1; j <= 1; j++) {
for (int i = -1; i <= 1; i++) {
vector3 cellOffset = vector3(i, j, k);
vector3 vectorToPoint = cellOffset +
hash_vector3_to_vector3(cellPosition + cellOffset) *
params.randomness -
localPosition;
float distanceToPoint = dot(vectorToPoint, vectorToPoint);
if (distanceToPoint < minDistance) {
minDistance = distanceToPoint;
vectorToClosest = vectorToPoint;
}
}
}
}
minDistance = 8.0;
for (int k = -1; k <= 1; k++) {
for (int j = -1; j <= 1; j++) {
for (int i = -1; i <= 1; i++) {
vector3 cellOffset = vector3(i, j, k);
vector3 vectorToPoint = cellOffset +
hash_vector3_to_vector3(cellPosition + cellOffset) *
params.randomness -
localPosition;
vector3 perpendicularToEdge = vectorToPoint - vectorToClosest;
if (dot(perpendicularToEdge, perpendicularToEdge) > 0.0001) {
float distanceToEdge = dot((vectorToClosest + vectorToPoint) / 2.0,
normalize((vector)perpendicularToEdge));
minDistance = min(minDistance, distanceToEdge);
}
}
}
}
return minDistance;
}
float voronoi_n_sphere_radius(VoronoiParams params, vector3 coord)
{
vector3 cellPosition = floor(coord);
vector3 localPosition = coord - cellPosition;
vector3 closestPoint = vector3(0.0, 0.0, 0.0);
vector3 closestPointOffset = vector3(0.0, 0.0, 0.0);
float minDistance = 8.0;
for (int k = -1; k <= 1; k++) {
for (int j = -1; j <= 1; j++) {
for (int i = -1; i <= 1; i++) {
vector3 cellOffset = vector3(i, j, k);
vector3 pointPosition = cellOffset + hash_vector3_to_vector3(cellPosition + cellOffset) *
params.randomness;
float distanceToPoint = distance(pointPosition, localPosition);
if (distanceToPoint < minDistance) {
minDistance = distanceToPoint;
closestPoint = pointPosition;
closestPointOffset = cellOffset;
}
}
}
}
minDistance = 8.0;
vector3 closestPointToClosestPoint = vector3(0.0, 0.0, 0.0);
for (int k = -1; k <= 1; k++) {
for (int j = -1; j <= 1; j++) {
for (int i = -1; i <= 1; i++) {
if (i == 0 && j == 0 && k == 0) {
continue;
}
vector3 cellOffset = vector3(i, j, k) + closestPointOffset;
vector3 pointPosition = cellOffset + hash_vector3_to_vector3(cellPosition + cellOffset) *
params.randomness;
float distanceToPoint = distance(closestPoint, pointPosition);
if (distanceToPoint < minDistance) {
minDistance = distanceToPoint;
closestPointToClosestPoint = pointPosition;
}
}
}
}
return distance(closestPointToClosestPoint, closestPoint) / 2.0;
}
/* **** 4D Voronoi **** */
vector4 voronoi_position(vector4 coord)
{
return coord;
}
VoronoiOutput voronoi_f1(VoronoiParams params, vector4 coord)
{
vector4 cellPosition = floor(coord);
vector4 localPosition = coord - cellPosition;
float minDistance = 8.0;
vector4 targetOffset = vector4(0.0, 0.0, 0.0, 0.0);
vector4 targetPosition = vector4(0.0, 0.0, 0.0, 0.0);
for (int u = -1; u <= 1; u++) {
for (int k = -1; k <= 1; k++) {
for (int j = -1; j <= 1; j++) {
for (int i = -1; i <= 1; i++) {
vector4 cellOffset = vector4(i, j, k, u);
vector4 pointPosition = cellOffset + hash_vector4_to_vector4(cellPosition + cellOffset) *
params.randomness;
float distanceToPoint = voronoi_distance(pointPosition, localPosition, params);
if (distanceToPoint < minDistance) {
targetOffset = cellOffset;
minDistance = distanceToPoint;
targetPosition = pointPosition;
}
}
}
}
}
VoronoiOutput octave;
octave.Distance = minDistance;
octave.Color = hash_vector4_to_color(cellPosition + targetOffset);
octave.Position = voronoi_position(targetPosition + cellPosition);
return octave;
}
VoronoiOutput voronoi_smooth_f1(VoronoiParams params, vector4 coord)
{
vector4 cellPosition = floor(coord);
vector4 localPosition = coord - cellPosition;
float smoothDistance = 8.0;
vector3 smoothColor = vector3(0.0, 0.0, 0.0);
vector4 smoothPosition = vector4(0.0, 0.0, 0.0, 0.0);
for (int u = -2; u <= 2; u++) {
for (int k = -2; k <= 2; k++) {
for (int j = -2; j <= 2; j++) {
for (int i = -2; i <= 2; i++) {
vector4 cellOffset = vector4(i, j, k, u);
vector4 pointPosition = cellOffset + hash_vector4_to_vector4(cellPosition + cellOffset) *
params.randomness;
float distanceToPoint = voronoi_distance(pointPosition, localPosition, params);
float h = smoothstep(
0.0, 1.0, 0.5 + 0.5 * (smoothDistance - distanceToPoint) / params.smoothness);
float correctionFactor = params.smoothness * h * (1.0 - h);
smoothDistance = mix(smoothDistance, distanceToPoint, h) - correctionFactor;
correctionFactor /= 1.0 + 3.0 * params.smoothness;
color cellColor = hash_vector4_to_color(cellPosition + cellOffset);
smoothColor = mix(smoothColor, cellColor, h) - correctionFactor;
smoothPosition = mix(smoothPosition, pointPosition, h) - correctionFactor;
}
}
}
}
VoronoiOutput octave;
octave.Distance = smoothDistance;
octave.Color = smoothColor;
octave.Position = voronoi_position(cellPosition + smoothPosition);
return octave;
}
VoronoiOutput voronoi_f2(VoronoiParams params, vector4 coord)
{
vector4 cellPosition = floor(coord);
vector4 localPosition = coord - cellPosition;
float distanceF1 = 8.0;
float distanceF2 = 8.0;
vector4 offsetF1 = vector4(0.0, 0.0, 0.0, 0.0);
vector4 positionF1 = vector4(0.0, 0.0, 0.0, 0.0);
vector4 offsetF2 = vector4(0.0, 0.0, 0.0, 0.0);
vector4 positionF2 = vector4(0.0, 0.0, 0.0, 0.0);
for (int u = -1; u <= 1; u++) {
for (int k = -1; k <= 1; k++) {
for (int j = -1; j <= 1; j++) {
for (int i = -1; i <= 1; i++) {
vector4 cellOffset = vector4(i, j, k, u);
vector4 pointPosition = cellOffset + hash_vector4_to_vector4(cellPosition + cellOffset) *
params.randomness;
float distanceToPoint = voronoi_distance(pointPosition, localPosition, params);
if (distanceToPoint < distanceF1) {
distanceF2 = distanceF1;
distanceF1 = distanceToPoint;
offsetF2 = offsetF1;
offsetF1 = cellOffset;
positionF2 = positionF1;
positionF1 = pointPosition;
}
else if (distanceToPoint < distanceF2) {
distanceF2 = distanceToPoint;
offsetF2 = cellOffset;
positionF2 = pointPosition;
}
}
}
}
}
VoronoiOutput octave;
octave.Distance = distanceF2;
octave.Color = hash_vector4_to_color(cellPosition + offsetF2);
octave.Position = voronoi_position(positionF2 + cellPosition);
return octave;
}
float voronoi_distance_to_edge(VoronoiParams params, vector4 coord)
{
vector4 cellPosition = floor(coord);
vector4 localPosition = coord - cellPosition;
vector4 vectorToClosest = vector4(0.0, 0.0, 0.0, 0.0);
float minDistance = 8.0;
for (int u = -1; u <= 1; u++) {
for (int k = -1; k <= 1; k++) {
for (int j = -1; j <= 1; j++) {
for (int i = -1; i <= 1; i++) {
vector4 cellOffset = vector4(i, j, k, u);
vector4 vectorToPoint = cellOffset +
hash_vector4_to_vector4(cellPosition + cellOffset) *
params.randomness -
localPosition;
float distanceToPoint = dot(vectorToPoint, vectorToPoint);
if (distanceToPoint < minDistance) {
minDistance = distanceToPoint;
vectorToClosest = vectorToPoint;
}
}
}
}
}
minDistance = 8.0;
for (int u = -1; u <= 1; u++) {
for (int k = -1; k <= 1; k++) {
for (int j = -1; j <= 1; j++) {
for (int i = -1; i <= 1; i++) {
vector4 cellOffset = vector4(i, j, k, u);
vector4 vectorToPoint = cellOffset +
hash_vector4_to_vector4(cellPosition + cellOffset) *
params.randomness -
localPosition;
vector4 perpendicularToEdge = vectorToPoint - vectorToClosest;
if (dot(perpendicularToEdge, perpendicularToEdge) > 0.0001) {
float distanceToEdge = dot((vectorToClosest + vectorToPoint) / 2.0,
normalize(perpendicularToEdge));
minDistance = min(minDistance, distanceToEdge);
}
}
}
}
}
return minDistance;
}
float voronoi_n_sphere_radius(VoronoiParams params, vector4 coord)
{
vector4 cellPosition = floor(coord);
vector4 localPosition = coord - cellPosition;
vector4 closestPoint = vector4(0.0, 0.0, 0.0, 0.0);
vector4 closestPointOffset = vector4(0.0, 0.0, 0.0, 0.0);
float minDistance = 8.0;
for (int u = -1; u <= 1; u++) {
for (int k = -1; k <= 1; k++) {
for (int j = -1; j <= 1; j++) {
for (int i = -1; i <= 1; i++) {
vector4 cellOffset = vector4(i, j, k, u);
vector4 pointPosition = cellOffset + hash_vector4_to_vector4(cellPosition + cellOffset) *
params.randomness;
float distanceToPoint = distance(pointPosition, localPosition);
if (distanceToPoint < minDistance) {
minDistance = distanceToPoint;
closestPoint = pointPosition;
closestPointOffset = cellOffset;
}
}
}
}
}
minDistance = 8.0;
vector4 closestPointToClosestPoint = vector4(0.0, 0.0, 0.0, 0.0);
for (int u = -1; u <= 1; u++) {
for (int k = -1; k <= 1; k++) {
for (int j = -1; j <= 1; j++) {
for (int i = -1; i <= 1; i++) {
if (i == 0 && j == 0 && k == 0 && u == 0) {
continue;
}
vector4 cellOffset = vector4(i, j, k, u) + closestPointOffset;
vector4 pointPosition = cellOffset + hash_vector4_to_vector4(cellPosition + cellOffset) *
params.randomness;
float distanceToPoint = distance(closestPoint, pointPosition);
if (distanceToPoint < minDistance) {
minDistance = distanceToPoint;
closestPointToClosestPoint = pointPosition;
}
}
}
}
}
return distance(closestPointToClosestPoint, closestPoint) / 2.0;
}

File diff suppressed because it is too large Load Diff

View File

@ -434,12 +434,14 @@ typedef enum ClosureType {
CLOSURE_BSDF_REFRACTION_ID,
CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID,
CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID,
CLOSURE_BSDF_HAIR_PRINCIPLED_ID,
CLOSURE_BSDF_HAIR_TRANSMISSION_ID,
/* Glass */
CLOSURE_BSDF_SHARP_GLASS_ID,
CLOSURE_BSDF_MICROFACET_BECKMANN_GLASS_ID,
CLOSURE_BSDF_MICROFACET_GGX_GLASS_ID,
CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID, /* virtual closure */
CLOSURE_BSDF_HAIR_PRINCIPLED_ID,
CLOSURE_BSDF_HAIR_TRANSMISSION_ID,
/* Special cases */
CLOSURE_BSDF_TRANSPARENT_ID,
@ -473,15 +475,15 @@ typedef enum ClosureType {
(type >= CLOSURE_BSDF_REFRACTION_ID && type <= CLOSURE_BSDF_HAIR_TRANSMISSION_ID)
#define CLOSURE_IS_BSDF_SINGULAR(type) \
(type == CLOSURE_BSDF_REFLECTION_ID || type == CLOSURE_BSDF_REFRACTION_ID || \
type == CLOSURE_BSDF_TRANSPARENT_ID)
type == CLOSURE_BSDF_TRANSPARENT_ID || type == CLOSURE_BSDF_SHARP_GLASS_ID)
#define CLOSURE_IS_BSDF_TRANSPARENT(type) (type == CLOSURE_BSDF_TRANSPARENT_ID)
#define CLOSURE_IS_BSDF_MULTISCATTER(type) \
(type == CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID || \
type == CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID)
#define CLOSURE_IS_BSDF_MICROFACET(type) \
((type >= CLOSURE_BSDF_MICROFACET_GGX_ID && type <= CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID) || \
(type >= CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID && \
type <= CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID))
((type >= CLOSURE_BSDF_REFLECTION_ID && type <= CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID) || \
(type >= CLOSURE_BSDF_REFRACTION_ID && type <= CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID) || \
(type >= CLOSURE_BSDF_SHARP_GLASS_ID && type <= CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID))
#define CLOSURE_IS_BSDF_OR_BSSRDF(type) (type <= CLOSURE_BSSRDF_RANDOM_WALK_FIXED_RADIUS_ID)
#define CLOSURE_IS_BSSRDF(type) \
(type >= CLOSURE_BSSRDF_BURLEY_ID && type <= CLOSURE_BSSRDF_RANDOM_WALK_FIXED_RADIUS_ID)
@ -491,8 +493,8 @@ typedef enum ClosureType {
#define CLOSURE_IS_VOLUME_ABSORPTION(type) (type == CLOSURE_VOLUME_ABSORPTION_ID)
#define CLOSURE_IS_HOLDOUT(type) (type == CLOSURE_HOLDOUT_ID)
#define CLOSURE_IS_PHASE(type) (type == CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID)
#define CLOSURE_IS_REFRACTIVE(type) \
(type >= CLOSURE_BSDF_REFRACTION_ID && type <= CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID)
#define CLOSURE_IS_REFRACTION(type) \
(type >= CLOSURE_BSDF_REFRACTION_ID && type <= CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID)
#define CLOSURE_IS_GLASS(type) \
(type >= CLOSURE_BSDF_SHARP_GLASS_ID && type <= CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID)
#define CLOSURE_IS_PRINCIPLED(type) (type == CLOSURE_BSDF_PRINCIPLED_ID)

File diff suppressed because it is too large Load Diff

View File

@ -1207,9 +1207,14 @@ NODE_DEFINE(VoronoiTextureNode)
feature_enum.insert("n_sphere_radius", NODE_VORONOI_N_SPHERE_RADIUS);
SOCKET_ENUM(feature, "Feature", feature_enum, NODE_VORONOI_F1);
SOCKET_BOOLEAN(normalize, "Normalize", false);
SOCKET_IN_POINT(vector, "Vector", zero_float3(), SocketType::LINK_TEXTURE_GENERATED);
SOCKET_IN_FLOAT(w, "W", 0.0f);
SOCKET_IN_FLOAT(scale, "Scale", 5.0f);
SOCKET_IN_FLOAT(detail, "Detail", 0.0f);
SOCKET_IN_FLOAT(roughness, "Roughness", 0.5f);
SOCKET_IN_FLOAT(lacunarity, "Lacunarity", 2.0f);
SOCKET_IN_FLOAT(smoothness, "Smoothness", 5.0f);
SOCKET_IN_FLOAT(exponent, "Exponent", 0.5f);
SOCKET_IN_FLOAT(randomness, "Randomness", 1.0f);
@ -1230,6 +1235,9 @@ void VoronoiTextureNode::compile(SVMCompiler &compiler)
ShaderInput *vector_in = input("Vector");
ShaderInput *w_in = input("W");
ShaderInput *scale_in = input("Scale");
ShaderInput *detail_in = input("Detail");
ShaderInput *roughness_in = input("Roughness");
ShaderInput *lacunarity_in = input("Lacunarity");
ShaderInput *smoothness_in = input("Smoothness");
ShaderInput *exponent_in = input("Exponent");
ShaderInput *randomness_in = input("Randomness");
@ -1243,6 +1251,9 @@ void VoronoiTextureNode::compile(SVMCompiler &compiler)
int vector_stack_offset = tex_mapping.compile_begin(compiler, vector_in);
int w_in_stack_offset = compiler.stack_assign_if_linked(w_in);
int scale_stack_offset = compiler.stack_assign_if_linked(scale_in);
int detail_stack_offset = compiler.stack_assign_if_linked(detail_in);
int roughness_stack_offset = compiler.stack_assign_if_linked(roughness_in);
int lacunarity_stack_offset = compiler.stack_assign_if_linked(lacunarity_in);
int smoothness_stack_offset = compiler.stack_assign_if_linked(smoothness_in);
int exponent_stack_offset = compiler.stack_assign_if_linked(exponent_in);
int randomness_stack_offset = compiler.stack_assign_if_linked(randomness_in);
@ -1255,19 +1266,21 @@ void VoronoiTextureNode::compile(SVMCompiler &compiler)
compiler.add_node(NODE_TEX_VORONOI, dimensions, feature, metric);
compiler.add_node(
compiler.encode_uchar4(
vector_stack_offset, w_in_stack_offset, scale_stack_offset, smoothness_stack_offset),
compiler.encode_uchar4(exponent_stack_offset,
randomness_stack_offset,
distance_stack_offset,
color_stack_offset),
compiler.encode_uchar4(position_stack_offset, w_out_stack_offset, radius_stack_offset),
__float_as_int(w));
vector_stack_offset, w_in_stack_offset, scale_stack_offset, detail_stack_offset),
compiler.encode_uchar4(roughness_stack_offset,
lacunarity_stack_offset,
smoothness_stack_offset,
exponent_stack_offset),
compiler.encode_uchar4(
randomness_stack_offset, normalize, distance_stack_offset, color_stack_offset),
compiler.encode_uchar4(position_stack_offset, w_out_stack_offset, radius_stack_offset));
compiler.add_node(__float_as_int(scale),
compiler.add_node(
__float_as_int(w), __float_as_int(scale), __float_as_int(detail), __float_as_int(roughness));
compiler.add_node(__float_as_int(lacunarity),
__float_as_int(smoothness),
__float_as_int(exponent),
__float_as_int(randomness));
tex_mapping.compile_end(compiler, vector_in, vector_stack_offset);
}
@ -1278,6 +1291,7 @@ void VoronoiTextureNode::compile(OSLCompiler &compiler)
compiler.parameter(this, "dimensions");
compiler.parameter(this, "feature");
compiler.parameter(this, "metric");
compiler.parameter(this, "normalize");
compiler.add(this, "node_voronoi_texture");
}

View File

@ -254,8 +254,12 @@ class VoronoiTextureNode : public TextureNode {
NODE_SOCKET_API(int, dimensions)
NODE_SOCKET_API(NodeVoronoiDistanceMetric, metric)
NODE_SOCKET_API(NodeVoronoiFeature, feature)
NODE_SOCKET_API(bool, normalize)
NODE_SOCKET_API(float, w)
NODE_SOCKET_API(float, scale)
NODE_SOCKET_API(float, detail)
NODE_SOCKET_API(float, roughness)
NODE_SOCKET_API(float, lacunarity)
NODE_SOCKET_API(float, exponent)
NODE_SOCKET_API(float, smoothness)
NODE_SOCKET_API(float, randomness)

View File

@ -224,6 +224,12 @@ ccl_device_inline float2 floor(const float2 a)
#endif /* !__KERNEL_METAL__ */
/* Consistent name for this would be pow, but HIP compiler crashes in name mangling. */
ccl_device_inline float2 power(float2 v, float e)
{
return make_float2(powf(v.x, e), powf(v.y, e));
}
ccl_device_inline float2 safe_divide_float2_float(const float2 a, const float b)
{
return (b != 0.0f) ? a / b : zero_float2();

View File

@ -469,7 +469,8 @@ ccl_device_inline bool isequal(const float3 a, const float3 b)
#endif
}
ccl_device_inline float3 pow(float3 v, float e)
/* Consistent name for this would be pow, but HIP compiler crashes in name mangling. */
ccl_device_inline float3 power(float3 v, float e)
{
return make_float3(powf(v.x, e), powf(v.y, e), powf(v.z, e));
}

View File

@ -593,7 +593,8 @@ ccl_device_inline float4 ensure_finite(float4 v)
return v;
}
ccl_device_inline float4 pow(float4 v, float e)
/* Consistent name for this would be pow, but HIP compiler crashes in name mangling. */
ccl_device_inline float4 power(float4 v, float e)
{
return make_float4(powf(v.x, e), powf(v.y, e), powf(v.z, e), powf(v.w, e));
}

View File

@ -931,6 +931,8 @@ def km_user_interface(_params):
("ui.reset_default_button", {"type": 'BACK_SPACE', "value": 'PRESS'}, {"properties": [("all", True)]}),
# UI lists (polls check if there's a UI list under the cursor).
("ui.list_start_filter", {"type": 'F', "value": 'PRESS', "ctrl": True}, None),
# UI views (polls check if there's a UI view under the cursor).
("ui.view_start_filter", {"type": 'F', "value": 'PRESS', "ctrl": True}, None),
])
return keymap
@ -4508,6 +4510,11 @@ def km_grease_pencil_edit(params):
items.extend([
*_template_items_select_actions(params, "grease_pencil.select_all"),
# Select linked
("grease_pencil.select_linked", {"type": 'L', "value": 'PRESS'}, None),
("grease_pencil.select_linked", {"type": 'L', "value": 'PRESS', "ctrl": True}, None),
("grease_pencil.select_more", {"type": 'NUMPAD_PLUS', "value": 'PRESS', "ctrl": True, "repeat": True}, None),
("grease_pencil.select_less", {"type": 'NUMPAD_MINUS', "value": 'PRESS', "ctrl": True, "repeat": True}, None),
])
return keymap

View File

@ -44,10 +44,9 @@ def geometry_modifier_poll(context):
def get_context_modifier(context):
# Context only has a 'modifier' attribute in the modifier extra operators dropdown.
if hasattr(context, 'modifier'):
modifier = context.modifier
else:
# Context only has a "modifier" attribute in the modifier extra operators drop-down.
modifier = getattr(context, "modifier", ...)
if modifier is ...:
ob = context.object
if ob is None:
return False

View File

@ -2030,6 +2030,13 @@ class VIEW3D_MT_select_edit_gpencil(Menu):
layout.separator()
layout.operator("grease_pencil.select_linked", text="Linked")
layout.separator()
layout.operator("grease_pencil.select_more")
layout.operator("grease_pencil.select_less")
class VIEW3D_MT_select_paint_mask(Menu):
bl_label = "Select"

View File

@ -9,7 +9,9 @@
#include "BLI_cpp_type.hh"
#include "BLI_generic_span.hh"
#include "BLI_generic_virtual_array.hh"
#include "BLI_math_axis_angle.hh"
#include "BLI_math_color.hh"
#include "BLI_math_quaternion.hh"
#include "BLI_math_vector.h"
#include "BLI_math_vector.hh"
@ -31,7 +33,8 @@ inline void convert_to_static_type(const CPPType &cpp_type, const Func &func)
bool,
int8_t,
ColorGeometry4f,
ColorGeometry4b>([&](auto type_tag) {
ColorGeometry4b,
math::Quaternion>([&](auto type_tag) {
using T = typename decltype(type_tag)::type;
if constexpr (std::is_same_v<T, void>) {
/* It's expected that the given cpp type is one of the supported ones. */
@ -400,7 +403,10 @@ class BooleanPropagationMixer {
* This mixer accumulates values in a type that is different from the one that is mixed.
* Some types cannot encode the floating point weights in their values (e.g. int and bool).
*/
template<typename T, typename AccumulationT, T (*ConvertToT)(const AccumulationT &value)>
template<typename T,
typename AccumulationT,
AccumulationT (*ValueToAccumulate)(const T &value),
T (*AccumulateToValue)(const AccumulationT &value)>
class SimpleMixerWithAccumulationType {
private:
struct Item {
@ -432,7 +438,7 @@ class SimpleMixerWithAccumulationType {
void set(const int64_t index, const T &value, const float weight = 1.0f)
{
const AccumulationT converted_value = static_cast<AccumulationT>(value);
const AccumulationT converted_value = ValueToAccumulate(value);
Item &item = accumulation_buffer_[index];
item.value = converted_value * weight;
item.weight = weight;
@ -440,7 +446,7 @@ class SimpleMixerWithAccumulationType {
void mix_in(const int64_t index, const T &value, const float weight = 1.0f)
{
const AccumulationT converted_value = static_cast<AccumulationT>(value);
const AccumulationT converted_value = ValueToAccumulate(value);
Item &item = accumulation_buffer_[index];
item.value += converted_value * weight;
item.weight += weight;
@ -457,7 +463,7 @@ class SimpleMixerWithAccumulationType {
const Item &item = accumulation_buffer_[i];
if (item.weight > 0.0f) {
const float weight_inv = 1.0f / item.weight;
const T converted_value = ConvertToT(item.value * weight_inv);
const T converted_value = AccumulateToValue(item.value * weight_inv);
buffer_[i] = converted_value;
}
else {
@ -532,40 +538,68 @@ template<> struct DefaultMixerStruct<ColorGeometry4b> {
using type = ColorGeometry4bMixer;
};
template<> struct DefaultMixerStruct<int> {
static double int_to_double(const int &value)
{
return double(value);
}
static int double_to_int(const double &value)
{
return int(std::round(value));
}
/* Store interpolated ints in a double temporarily, so that weights are handled correctly. It
* uses double instead of float so that it is accurate for all 32 bit integers. */
using type = SimpleMixerWithAccumulationType<int, double, double_to_int>;
using type = SimpleMixerWithAccumulationType<int, double, int_to_double, double_to_int>;
};
template<> struct DefaultMixerStruct<int2> {
static double2 int_to_double(const int2 &value)
{
return double2(value);
}
static int2 double_to_int(const double2 &value)
{
return int2(math::round(value));
}
/* Store interpolated ints in a double temporarily, so that weights are handled correctly. It
* uses double instead of float so that it is accurate for all 32 bit integers. */
using type = SimpleMixerWithAccumulationType<int2, double2, double_to_int>;
using type = SimpleMixerWithAccumulationType<int2, double2, int_to_double, double_to_int>;
};
template<> struct DefaultMixerStruct<bool> {
static float bool_to_float(const bool &value)
{
return value ? 1.0f : 0.0f;
}
static bool float_to_bool(const float &value)
{
return value >= 0.5f;
}
/* Store interpolated booleans in a float temporary.
* Otherwise information provided by weights is easily rounded away. */
using type = SimpleMixerWithAccumulationType<bool, float, float_to_bool>;
using type = SimpleMixerWithAccumulationType<bool, float, bool_to_float, float_to_bool>;
};
template<> struct DefaultMixerStruct<int8_t> {
static float int8_t_to_float(const int8_t &value)
{
return float(value);
}
static int8_t float_to_int8_t(const float &value)
{
return int8_t(std::round(value));
}
/* Store interpolated 8 bit integers in a float temporarily to increase accuracy. */
using type = SimpleMixerWithAccumulationType<int8_t, float, float_to_int8_t>;
using type = SimpleMixerWithAccumulationType<int8_t, float, int8_t_to_float, float_to_int8_t>;
};
template<> struct DefaultMixerStruct<math::Quaternion> {
static float3 quat_to_expmap(const math::Quaternion &value)
{
return value.expmap();
}
static math::Quaternion expmap_to_quat(const float3 &value)
{
return math::Quaternion::expmap(value);
}
using type =
SimpleMixerWithAccumulationType<math::Quaternion, float3, quat_to_expmap, expmap_to_quat>;
};
template<typename T> struct DefaultPropagationMixerStruct {

View File

@ -30,7 +30,7 @@ bool BKE_curves_attribute_required(const struct Curves *curves, const char *name
/* Depsgraph */
struct Curves *BKE_curves_copy_for_eval(struct Curves *curves_src);
struct Curves *BKE_curves_copy_for_eval(const struct Curves *curves_src);
void BKE_curves_data_update(struct Depsgraph *depsgraph,
struct Scene *scene,

View File

@ -80,7 +80,7 @@ bool BKE_pointcloud_attribute_required(const struct PointCloud *pointcloud, cons
/* Dependency Graph */
struct PointCloud *BKE_pointcloud_copy_for_eval(struct PointCloud *pointcloud_src);
struct PointCloud *BKE_pointcloud_copy_for_eval(const struct PointCloud *pointcloud_src);
void BKE_pointcloud_data_update(struct Depsgraph *depsgraph,
struct Scene *scene,

View File

@ -48,7 +48,7 @@ struct wmWindow;
struct wmWindowManager;
/* spacetype has everything stored to get an editor working, it gets initialized via
* #ED_spacetypes_init() in `editors/space_api/spacetypes.c` */
* #ED_spacetypes_init() in `editors/space_api/spacetypes.cc` */
/* an editor in Blender is a combined ScrArea + SpaceType + SpaceData */
#define BKE_ST_MAXNAME 64

View File

@ -132,7 +132,7 @@ void BKE_volume_grid_transform_matrix_set(const struct Volume *volume,
* file path. Grids are shared with the source data-block, not copied. */
struct Volume *BKE_volume_new_for_eval(const struct Volume *volume_src);
struct Volume *BKE_volume_copy_for_eval(struct Volume *volume_src);
struct Volume *BKE_volume_copy_for_eval(const struct Volume *volume_src);
struct VolumeGrid *BKE_volume_grid_add(struct Volume *volume,
const char *name,

View File

@ -107,11 +107,13 @@ static int attribute_data_type_complexity(const eCustomDataType data_type)
return 6;
case CD_PROP_BYTE_COLOR:
return 7;
case CD_PROP_COLOR:
case CD_PROP_QUATERNION:
return 8;
case CD_PROP_COLOR:
return 9;
#if 0 /* These attribute types are not supported yet. */
case CD_PROP_STRING:
return 9;
return 10;
#endif
default:
/* Only accept "generic" custom data types used by the attribute system. */

View File

@ -3,11 +3,39 @@
* SPDX-License-Identifier: GPL-2.0-or-later */
#include "BLI_array_utils.hh"
#include "BLI_math_quaternion.hh"
#include "BKE_attribute_math.hh"
namespace blender::bke::attribute_math {
template<>
math::Quaternion mix2(const float factor, const math::Quaternion &a, const math::Quaternion &b)
{
return math::interpolate(a, b, factor);
}
template<>
math::Quaternion mix3(const float3 &weights,
const math::Quaternion &v0,
const math::Quaternion &v1,
const math::Quaternion &v2)
{
const float3 expmap_mixed = mix3(weights, v0.expmap(), v1.expmap(), v2.expmap());
return math::Quaternion::expmap(expmap_mixed);
}
template<>
math::Quaternion mix4(const float4 &weights,
const math::Quaternion &v0,
const math::Quaternion &v1,
const math::Quaternion &v2,
const math::Quaternion &v3)
{
const float3 expmap_mixed = mix4(weights, v0.expmap(), v1.expmap(), v2.expmap(), v3.expmap());
return math::Quaternion::expmap(expmap_mixed);
}
ColorGeometry4fMixer::ColorGeometry4fMixer(MutableSpan<ColorGeometry4f> buffer,
ColorGeometry4f default_color)
: ColorGeometry4fMixer(buffer, buffer.index_range(), default_color)

View File

@ -222,7 +222,7 @@ bool BKE_curves_attribute_required(const Curves * /*curves*/, const char *name)
return STREQ(name, ATTR_POSITION);
}
Curves *BKE_curves_copy_for_eval(Curves *curves_src)
Curves *BKE_curves_copy_for_eval(const Curves *curves_src)
{
return reinterpret_cast<Curves *>(
BKE_id_copy_ex(nullptr, &curves_src->id, nullptr, LIB_ID_COPY_LOCALIZE));

View File

@ -24,6 +24,7 @@
#include "BLI_index_range.hh"
#include "BLI_math.h"
#include "BLI_math_color_blend.h"
#include "BLI_math_quaternion_types.hh"
#include "BLI_math_vector.hh"
#include "BLI_mempool.h"
#include "BLI_path_util.h"
@ -1542,6 +1543,20 @@ static void layerInterp_propbool(const void **sources,
*(bool *)dest = result;
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name Callbacks for (#math::Quaternion, #CD_PROP_QUATERNION)
* \{ */
static void layerDefault_propquaternion(void *data, const int count)
{
using namespace blender;
MutableSpan(static_cast<math::Quaternion *>(data), count).fill(math::Quaternion::identity());
}
/** \} */
static const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = {
/* 0: CD_MVERT */ /* DEPRECATED */
{sizeof(MVert), "MVert", 1, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr},
@ -1933,6 +1948,16 @@ static const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = {
nullptr},
/* 51: CD_HAIRLENGTH */
{sizeof(float), "float", 1, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr},
/* 52: CD_PROP_QUATERNION */
{sizeof(float[4]),
"vec4f",
1,
N_("Quaternion"),
nullptr,
nullptr,
nullptr,
nullptr,
layerDefault_propquaternion},
};
static const char *LAYERTYPENAMES[CD_NUMTYPES] = {
@ -1990,6 +2015,7 @@ static const char *LAYERTYPENAMES[CD_NUMTYPES] = {
"CDPropFloat2",
"CDPropBoolean",
"CDHairLength",
"CDPropQuaternion",
};
const CustomData_MeshMasks CD_MASK_BAREMESH = {
@ -5354,6 +5380,8 @@ const blender::CPPType *custom_data_type_to_cpp_type(const eCustomDataType type)
return &CPPType::get<int8_t>();
case CD_PROP_BYTE_COLOR:
return &CPPType::get<ColorGeometry4b>();
case CD_PROP_QUATERNION:
return &CPPType::get<math::Quaternion>();
case CD_PROP_STRING:
return &CPPType::get<MStringProperty>();
default:
@ -5390,6 +5418,9 @@ eCustomDataType cpp_type_to_custom_data_type(const blender::CPPType &type)
if (type.is<ColorGeometry4b>()) {
return CD_PROP_BYTE_COLOR;
}
if (type.is<math::Quaternion>()) {
return CD_PROP_QUATERNION;
}
if (type.is<MStringProperty>()) {
return CD_PROP_STRING;
}

View File

@ -661,6 +661,26 @@ static int customdata_compare(
}
break;
}
case CD_PROP_QUATERNION: {
const float(*l1_data)[4] = (float(*)[4])l1->data;
const float(*l2_data)[4] = (float(*)[4])l2->data;
for (int i = 0; i < total_length; i++) {
if (compare_threshold_relative(l1_data[i][0], l2_data[i][0], thresh)) {
return MESHCMP_ATTRIBUTE_VALUE_MISMATCH;
}
if (compare_threshold_relative(l1_data[i][1], l2_data[i][1], thresh)) {
return MESHCMP_ATTRIBUTE_VALUE_MISMATCH;
}
if (compare_threshold_relative(l1_data[i][2], l2_data[i][2], thresh)) {
return MESHCMP_ATTRIBUTE_VALUE_MISMATCH;
}
if (compare_threshold_relative(l1_data[i][3], l2_data[i][3], thresh)) {
return MESHCMP_ATTRIBUTE_VALUE_MISMATCH;
}
}
break;
}
case CD_PROP_INT32: {
const int *l1_data = (int *)l1->data;
const int *l2_data = (int *)l2->data;

View File

@ -320,7 +320,7 @@ bool BKE_pointcloud_attribute_required(const PointCloud * /*pointcloud*/, const
/* Dependency Graph */
PointCloud *BKE_pointcloud_copy_for_eval(PointCloud *pointcloud_src)
PointCloud *BKE_pointcloud_copy_for_eval(const PointCloud *pointcloud_src)
{
return reinterpret_cast<PointCloud *>(
BKE_id_copy_ex(nullptr, &pointcloud_src->id, nullptr, LIB_ID_COPY_LOCALIZE));

View File

@ -2684,7 +2684,8 @@ void BKE_scene_update_sound(Depsgraph *depsgraph, Main *bmain)
BKE_sound_set_scene_volume(scene, scene->audio.volume);
}
if (recalc & ID_RECALC_AUDIO_MUTE) {
const bool is_mute = (scene->audio.flag & AUDIO_MUTE);
const bool is_mute = (DEG_get_mode(depsgraph) == DAG_EVAL_VIEWPORT) &&
(scene->audio.flag & AUDIO_MUTE);
BKE_sound_mute_scene(scene, is_mute);
}
if (recalc & ID_RECALC_AUDIO_LISTENER) {

View File

@ -18,6 +18,7 @@
#include "BLI_endian_switch.h"
#include "BLI_fileops.hh"
#include "BLI_math_matrix_types.hh"
#include "BLI_math_quaternion_types.hh"
#include "BLI_path_util.h"
#include "RNA_access.h"
@ -778,6 +779,10 @@ static std::shared_ptr<io::serialize::Value> serialize_primitive_value(
const ColorGeometry4f value = *static_cast<const ColorGeometry4f *>(value_ptr);
return serialize_float_array({&value.r, 4});
}
case CD_PROP_QUATERNION: {
const math::Quaternion value = *static_cast<const math::Quaternion *>(value_ptr);
return serialize_float_array({&value.x, 4});
}
default:
break;
}
@ -966,6 +971,9 @@ template<typename T>
case CD_PROP_COLOR: {
return deserialize_float_array(io_value, {static_cast<float *>(r_value), 4});
}
case CD_PROP_QUATERNION: {
return deserialize_float_array(io_value, {static_cast<float *>(r_value), 4});
}
default:
break;
}

View File

@ -1530,7 +1530,7 @@ Volume *BKE_volume_new_for_eval(const Volume *volume_src)
return volume_dst;
}
Volume *BKE_volume_copy_for_eval(Volume *volume_src)
Volume *BKE_volume_copy_for_eval(const Volume *volume_src)
{
return reinterpret_cast<Volume *>(
BKE_id_copy_ex(nullptr, &volume_src->id, nullptr, LIB_ID_COPY_LOCALIZE));

View File

@ -11,6 +11,7 @@
#include "BLI_index_mask.hh"
#include "BLI_math_base.hh"
#include "BLI_math_color.hh"
#include "BLI_math_quaternion.hh"
#include "BLI_math_vector.hh"
namespace blender::length_parameterize {

View File

@ -306,87 +306,85 @@ float musgrave_hetero_terrain(
/** \name Voronoi Noise
* \{ */
void voronoi_f1(float w, float randomness, float *r_distance, float3 *r_color, float *r_w);
void voronoi_smooth_f1(
float w, float smoothness, float randomness, float *r_distance, float3 *r_color, float *r_w);
void voronoi_f2(float w, float randomness, float *r_distance, float3 *r_color, float *r_w);
void voronoi_distance_to_edge(float w, float randomness, float *r_distance);
void voronoi_n_sphere_radius(float w, float randomness, float *r_radius);
struct VoronoiParams {
float scale;
float detail;
float roughness;
float lacunarity;
float smoothness;
float exponent;
float randomness;
float max_distance;
bool normalize;
int feature;
int metric;
};
void voronoi_f1(const float2 coord,
float exponent,
float randomness,
int metric,
float *r_distance,
float3 *r_color,
float2 *r_position);
void voronoi_smooth_f1(const float2 coord,
float smoothness,
float exponent,
float randomness,
int metric,
float *r_distance,
float3 *r_color,
float2 *r_position);
void voronoi_f2(const float2 coord,
float exponent,
float randomness,
int metric,
float *r_distance,
float3 *r_color,
float2 *r_position);
void voronoi_distance_to_edge(const float2 coord, float randomness, float *r_distance);
void voronoi_n_sphere_radius(const float2 coord, float randomness, float *r_radius);
struct VoronoiOutput {
float distance = 0.0f;
float3 color{0.0f, 0.0f, 0.0f};
float4 position{0.0f, 0.0f, 0.0f, 0.0f};
};
void voronoi_f1(const float3 coord,
float exponent,
float randomness,
int metric,
float *r_distance,
float3 *r_color,
float3 *r_position);
void voronoi_smooth_f1(const float3 coord,
float smoothness,
float exponent,
float randomness,
int metric,
float *r_distance,
float3 *r_color,
float3 *r_position);
void voronoi_f2(const float3 coord,
float exponent,
float randomness,
int metric,
float *r_distance,
float3 *r_color,
float3 *r_position);
void voronoi_distance_to_edge(const float3 coord, float randomness, float *r_distance);
void voronoi_n_sphere_radius(const float3 coord, float randomness, float *r_radius);
/* ***** Distances ***** */
void voronoi_f1(const float4 coord,
float exponent,
float randomness,
int metric,
float *r_distance,
float3 *r_color,
float4 *r_position);
void voronoi_smooth_f1(const float4 coord,
float smoothness,
float exponent,
float randomness,
int metric,
float *r_distance,
float3 *r_color,
float4 *r_position);
void voronoi_f2(const float4 coord,
float exponent,
float randomness,
int metric,
float *r_distance,
float3 *r_color,
float4 *r_position);
void voronoi_distance_to_edge(const float4 coord, float randomness, float *r_distance);
void voronoi_n_sphere_radius(const float4 coord, float randomness, float *r_radius);
float voronoi_distance(const float a, const float b);
float voronoi_distance(const float2 a, const float2 b, const VoronoiParams &params);
float voronoi_distance(const float3 a, const float3 b, const VoronoiParams &params);
float voronoi_distance(const float4 a, const float4 b, const VoronoiParams &params);
/* **** 1D Voronoi **** */
float4 voronoi_position(const float coord);
VoronoiOutput voronoi_f1(const VoronoiParams &params, const float coord);
VoronoiOutput voronoi_smooth_f1(const VoronoiParams &params,
const float coord,
const bool calc_color);
VoronoiOutput voronoi_f2(const VoronoiParams &params, const float coord);
float voronoi_distance_to_edge(const VoronoiParams &params, const float coord);
float voronoi_n_sphere_radius(const VoronoiParams &params, const float coord);
/* **** 2D Voronoi **** */
float4 voronoi_position(const float2 coord);
VoronoiOutput voronoi_f1(const VoronoiParams &params, const float2 coord);
VoronoiOutput voronoi_smooth_f1(const VoronoiParams &params,
const float2 coord,
const bool calc_color);
VoronoiOutput voronoi_f2(const VoronoiParams &params, const float2 coord);
float voronoi_distance_to_edge(const VoronoiParams &params, const float2 coord);
float voronoi_n_sphere_radius(const VoronoiParams &params, const float2 coord);
/* **** 3D Voronoi **** */
float4 voronoi_position(const float3 coord);
VoronoiOutput voronoi_f1(const VoronoiParams &params, const float3 coord);
VoronoiOutput voronoi_smooth_f1(const VoronoiParams &params,
const float3 coord,
const bool calc_color);
VoronoiOutput voronoi_f2(const VoronoiParams &params, const float3 coord);
float voronoi_distance_to_edge(const VoronoiParams &params, const float3 coord);
float voronoi_n_sphere_radius(const VoronoiParams &params, const float3 coord);
/* **** 4D Voronoi **** */
float4 voronoi_position(const float4 coord);
VoronoiOutput voronoi_f1(const VoronoiParams &params, const float4 coord);
VoronoiOutput voronoi_smooth_f1(const VoronoiParams &params,
const float4 coord,
const bool calc_color);
VoronoiOutput voronoi_f2(const VoronoiParams &params, const float4 coord);
float voronoi_distance_to_edge(const VoronoiParams &params, const float4 coord);
float voronoi_n_sphere_radius(const VoronoiParams &params, const float4 coord);
/* Fractal Voronoi Noise */
template<typename T>
VoronoiOutput fractal_voronoi_x_fx(const VoronoiParams &params,
const T coord,
const bool calc_color);
template<typename T>
float fractal_voronoi_distance_to_edge(const VoronoiParams &params, const T coord);
/** \} */

View File

@ -32,7 +32,7 @@ template<typename T> class OffsetIndices {
OffsetIndices() = default;
OffsetIndices(const Span<T> offsets) : offsets_(offsets)
{
BLI_assert(std::is_sorted(offsets_.begin(), offsets_.end()));
BLI_assert(offsets_.size() < 2 || std::is_sorted(offsets_.begin(), offsets_.end()));
}
/** Return the total number of elements in the referenced arrays. */

View File

@ -265,6 +265,10 @@ int BLI_path_slash_ensure(char *path, size_t path_maxncpy) ATTR_NONNULL(1);
* Removes the last slash and everything after it to the end of path, if there is one.
*/
void BLI_path_slash_rstrip(char *path) ATTR_NONNULL(1);
/**
* \return the next non-slash character or the null byte (when `path` only contains slashes).
*/
const char *BLI_path_slash_skip(const char *path) ATTR_NONNULL(1) ATTR_WARN_UNUSED_RESULT;
/**
* Changes to the path separators to the native ones for this OS.
*/

View File

@ -6,6 +6,7 @@
#include "BLI_cpp_type_make.hh"
#include "BLI_cpp_types_make.hh"
#include "BLI_math_matrix_types.hh"
#include "BLI_math_quaternion_types.hh"
#include "BLI_math_vector_types.hh"
namespace blender {
@ -65,6 +66,8 @@ BLI_CPP_TYPE_MAKE(uint64_t, CPPTypeFlags::BasicType)
BLI_CPP_TYPE_MAKE(blender::ColorGeometry4f, CPPTypeFlags::BasicType)
BLI_CPP_TYPE_MAKE(blender::ColorGeometry4b, CPPTypeFlags::BasicType)
BLI_CPP_TYPE_MAKE(blender::math::Quaternion, CPPTypeFlags::BasicType)
BLI_CPP_TYPE_MAKE(std::string, CPPTypeFlags::BasicType)
BLI_VECTOR_CPP_TYPE_MAKE(std::string)
@ -94,6 +97,8 @@ void register_cpp_types()
BLI_CPP_TYPE_REGISTER(blender::ColorGeometry4f);
BLI_CPP_TYPE_REGISTER(blender::ColorGeometry4b);
BLI_CPP_TYPE_REGISTER(math::Quaternion);
BLI_CPP_TYPE_REGISTER(std::string);
BLI_VECTOR_CPP_TYPE_REGISTER(std::string);

File diff suppressed because it is too large Load Diff

View File

@ -1118,9 +1118,7 @@ bool BLI_path_abs(char path[FILE_MAX], const char *basepath)
BLI_assert(strlen(tmp) == root_dir_len);
/* Step over the slashes at the beginning of the path. */
while (BLI_path_slash_is_native_compat(*p)) {
p++;
}
p = (char *)BLI_path_slash_skip(p);
BLI_strncpy(tmp + root_dir_len, p, sizeof(tmp) - root_dir_len);
}
else {
@ -1958,6 +1956,15 @@ void BLI_path_slash_rstrip(char *path)
}
}
const char *BLI_path_slash_skip(const char *path)
{
/* This accounts for a null byte too. */
while (BLI_path_slash_is_native_compat(*path)) {
path++;
}
return path;
}
void BLI_path_slash_native(char *path)
{
#ifdef WIN32

View File

@ -42,7 +42,7 @@ set(SRC
intern/undofile.cc
intern/versioning_250.c
intern/versioning_260.c
intern/versioning_270.c
intern/versioning_270.cc
intern/versioning_280.cc
intern/versioning_290.cc
intern/versioning_300.cc

View File

@ -329,7 +329,9 @@ static void do_version_scene_collection_convert(
BLI_ghash_insert(collection_map, collection, sc);
}
LISTBASE_FOREACH (SceneCollection *, nsc, &sc->scene_collections) {
for (SceneCollection *nsc = static_cast<SceneCollection *>(sc->scene_collections.first);
nsc != nullptr;)
{
SceneCollection *nsc_next = nsc->next;
Collection *ncollection = BKE_collection_add(bmain, collection, nsc->name);
ncollection->id.lib = id->lib;

View File

@ -32,16 +32,16 @@ class DenoiseFilter {
#ifdef WITH_OPENIMAGEDENOISE
oidn::DeviceRef device_;
oidn::FilterRef filter_;
#endif
bool initialized_ = false;
#endif
public:
#ifdef WITH_OPENIMAGEDENOISE
~DenoiseFilter()
{
BLI_assert(!initialized_);
}
#ifdef WITH_OPENIMAGEDENOISE
void init_and_lock_denoiser(MemoryBuffer *output)
{
/* Since it's memory intensive, it's better to run only one instance of OIDN at a time.

View File

@ -298,3 +298,6 @@ if(WITH_OPENCOLORIO)
endif()
blender_add_lib(bf_realtime_compositor "${SRC}" "${INC}" "${INC_SYS}" "${LIB}")
# Needed so we can use dna_type_offsets.h
add_dependencies(bf_realtime_compositor bf_dna)

View File

@ -246,7 +246,7 @@ void output_renderpass_color(int id, vec4 color)
imageStore(rp_color_img, ivec3(texel, id), color);
}
#endif
};
}
void output_renderpass_value(int id, float value)
{
@ -256,7 +256,7 @@ void output_renderpass_value(int id, float value)
imageStore(rp_value_img, ivec3(texel, id), vec4(value));
}
#endif
};
}
void clear_aovs()
{

View File

@ -83,7 +83,7 @@ bool drw_custom_data_match_attribute(const CustomData *custom_data,
int *r_layer_index,
eCustomDataType *r_type)
{
const eCustomDataType possible_attribute_types[9] = {
const eCustomDataType possible_attribute_types[10] = {
CD_PROP_BOOL,
CD_PROP_INT8,
CD_PROP_INT32_2D,
@ -92,6 +92,7 @@ bool drw_custom_data_match_attribute(const CustomData *custom_data,
CD_PROP_FLOAT2,
CD_PROP_FLOAT3,
CD_PROP_COLOR,
CD_PROP_QUATERNION,
CD_PROP_BYTE_COLOR,
};

View File

@ -392,6 +392,7 @@ static DRW_MeshCDMask mesh_cd_calc_used_gpu_layers(const Object *object,
}
case CD_PROP_BYTE_COLOR:
case CD_PROP_COLOR:
case CD_PROP_QUATERNION:
case CD_PROP_FLOAT3:
case CD_PROP_BOOL:
case CD_PROP_INT8:

View File

@ -107,6 +107,7 @@ static uint gpu_component_size_for_attribute_type(eCustomDataType type)
return 3;
case CD_PROP_COLOR:
case CD_PROP_BYTE_COLOR:
case CD_PROP_QUATERNION:
return 4;
default:
return 0;
@ -315,6 +316,7 @@ static void extract_attr(const MeshRenderData *mr,
case CD_PROP_FLOAT3:
extract_attr_generic<float3>(mr, vbo, request);
break;
case CD_PROP_QUATERNION:
case CD_PROP_COLOR:
extract_attr_generic<float4>(mr, vbo, request);
break;

View File

@ -76,6 +76,102 @@ static void GREASE_PENCIL_OT_select_all(wmOperatorType *ot)
WM_operator_properties_select_all(ot);
}
static int select_more_exec(bContext *C, wmOperator * /*op*/)
{
Scene *scene = CTX_data_scene(C);
Object *object = CTX_data_active_object(C);
GreasePencil &grease_pencil = *static_cast<GreasePencil *>(object->data);
grease_pencil.foreach_editable_drawing(
scene->r.cfra, [](int /*drawing_index*/, GreasePencilDrawing &drawing) {
// TODO: Support different selection domains.
blender::ed::curves::select_adjacent(drawing.geometry.wrap(), false);
});
/* Use #ID_RECALC_GEOMETRY instead of #ID_RECALC_SELECT because it is handled as a generic
* attribute for now. */
DEG_id_tag_update(&grease_pencil.id, ID_RECALC_GEOMETRY);
WM_event_add_notifier(C, NC_GEOM | ND_DATA, &grease_pencil);
return OPERATOR_FINISHED;
}
static void GREASE_PENCIL_OT_select_more(wmOperatorType *ot)
{
ot->name = "Select More";
ot->idname = "GREASE_PENCIL_OT_select_more";
ot->description = "Grow the selection by one point";
ot->exec = select_more_exec;
ot->poll = editable_grease_pencil_poll;
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
static int select_less_exec(bContext *C, wmOperator * /*op*/)
{
Scene *scene = CTX_data_scene(C);
Object *object = CTX_data_active_object(C);
GreasePencil &grease_pencil = *static_cast<GreasePencil *>(object->data);
grease_pencil.foreach_editable_drawing(
scene->r.cfra, [](int /*drawing_index*/, GreasePencilDrawing &drawing) {
// TODO: Support different selection domains.
blender::ed::curves::select_adjacent(drawing.geometry.wrap(), true);
});
/* Use #ID_RECALC_GEOMETRY instead of #ID_RECALC_SELECT because it is handled as a generic
* attribute for now. */
DEG_id_tag_update(&grease_pencil.id, ID_RECALC_GEOMETRY);
WM_event_add_notifier(C, NC_GEOM | ND_DATA, &grease_pencil);
return OPERATOR_FINISHED;
}
static void GREASE_PENCIL_OT_select_less(wmOperatorType *ot)
{
ot->name = "Select Less";
ot->idname = "GREASE_PENCIL_OT_select_less";
ot->description = "Shrink the selection by one point";
ot->exec = select_less_exec;
ot->poll = editable_grease_pencil_poll;
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
static int select_linked_exec(bContext *C, wmOperator * /*op*/)
{
Scene *scene = CTX_data_scene(C);
Object *object = CTX_data_active_object(C);
GreasePencil &grease_pencil = *static_cast<GreasePencil *>(object->data);
grease_pencil.foreach_editable_drawing(
scene->r.cfra, [](int /*drawing_index*/, GreasePencilDrawing &drawing) {
// TODO: Support different selection domains.
blender::ed::curves::select_linked(drawing.geometry.wrap());
});
/* Use #ID_RECALC_GEOMETRY instead of #ID_RECALC_SELECT because it is handled as a generic
* attribute for now. */
DEG_id_tag_update(&grease_pencil.id, ID_RECALC_GEOMETRY);
WM_event_add_notifier(C, NC_GEOM | ND_DATA, &grease_pencil);
return OPERATOR_FINISHED;
}
static void GREASE_PENCIL_OT_select_linked(wmOperatorType *ot)
{
ot->name = "Select Linked";
ot->idname = "GREASE_PENCIL_OT_select_linked";
ot->description = "Select all points in curves with any point selection";
ot->exec = select_linked_exec;
ot->poll = editable_grease_pencil_poll;
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
static void keymap_grease_pencil_editing(wmKeyConfig *keyconf)
{
wmKeyMap *keymap = WM_keymap_ensure(keyconf, "Grease Pencil Edit Mode", 0, 0);
@ -88,6 +184,9 @@ void ED_operatortypes_grease_pencil(void)
{
using namespace blender::ed::greasepencil;
WM_operatortype_append(GREASE_PENCIL_OT_select_all);
WM_operatortype_append(GREASE_PENCIL_OT_select_more);
WM_operatortype_append(GREASE_PENCIL_OT_select_less);
WM_operatortype_append(GREASE_PENCIL_OT_select_linked);
}
void ED_keymap_grease_pencil(wmKeyConfig *keyconf)

View File

@ -10,16 +10,16 @@
#include "BLI_compiler_attrs.h"
#include "BKE_scene.h"
#ifdef __cplusplus
extern "C" {
#endif
enum eSceneCopyMethod;
struct Scene *ED_scene_add(struct Main *bmain,
struct bContext *C,
struct wmWindow *win,
enum eSceneCopyMethod method) ATTR_NONNULL();
eSceneCopyMethod method) ATTR_NONNULL();
/**
* Add a new scene in the sequence editor.
*
@ -27,8 +27,8 @@ struct Scene *ED_scene_add(struct Main *bmain,
*/
struct Scene *ED_scene_sequencer_add(struct Main *bmain,
struct bContext *C,
enum eSceneCopyMethod method,
const bool assign_strip);
eSceneCopyMethod method,
bool assign_strip);
/**
* \note Only call outside of area/region loops.
* \return true if successful.

View File

@ -493,9 +493,9 @@ bScreen *ED_screen_animation_playing(const struct wmWindowManager *wm);
bScreen *ED_screen_animation_no_scrub(const struct wmWindowManager *wm);
/* screen keymaps */
/* called in spacetypes.c */
/* called in spacetypes.cc */
void ED_operatortypes_screen(void);
/* called in spacetypes.c */
/* called in spacetypes.cc */
void ED_keymap_screen(struct wmKeyConfig *keyconf);
/**
* Workspace key-maps.

View File

@ -84,6 +84,13 @@ class AbstractView {
/** Listen to a notifier, returning true if a redraw is needed. */
virtual bool listen(const wmNotifier &) const;
/**
* Enable filtering. Typically used to enable a filter text button. Triggered on Ctrl+F by
* default.
* \return True when filtering was enabled successfully.
*/
virtual bool begin_filtering(const bContext &C) const;
/**
* Makes \a item valid for display in this view. Behavior is undefined for items not registered
* with this.
@ -136,6 +143,9 @@ class AbstractViewItem {
bool is_active_ = false;
bool is_renaming_ = false;
/** Cache filtered state here to avoid having to re-query. */
mutable std::optional<bool> is_filtered_visible_;
public:
virtual ~AbstractViewItem() = default;
@ -174,6 +184,10 @@ class AbstractViewItem {
*/
virtual std::unique_ptr<AbstractViewItemDropTarget> create_drop_target();
/** Return the result of #is_filtered_visible(), but ensure the result is cached so it's only
* queried once per redraw. */
bool is_filtered_visible_cached() const;
/** Get the view this item is registered for using #AbstractView::register_item(). */
AbstractView &get_view() const;
@ -217,6 +231,12 @@ class AbstractViewItem {
*/
virtual void update_from_old(const AbstractViewItem &old);
/**
* \note Do not call this directly to avoid constantly rechecking the filter state. Instead use
* #is_filtered_visible_cached() for querying.
*/
virtual bool is_filtered_visible() const;
/**
* Add a text button for renaming the item to \a block. This must be used for the built-in
* renaming to work. This button is meant to appear temporarily. It is removed when renaming is

View File

@ -98,6 +98,8 @@ class AbstractGridView : public AbstractView {
protected:
Vector<std::unique_ptr<AbstractGridViewItem>> items_;
/** Store this to avoid recomputing. */
mutable std::optional<int> item_count_filtered_;
/** <identifier, item> map to lookup items by identifier, used for efficient lookups in
* #update_from_old(). */
Map<StringRef, AbstractGridViewItem *> item_map_;
@ -109,6 +111,7 @@ class AbstractGridView : public AbstractView {
using ItemIterFn = FunctionRef<void(AbstractGridViewItem &)>;
void foreach_item(ItemIterFn iter_fn) const;
void foreach_filtered_item(ItemIterFn iter_fn) const;
/**
* Convenience wrapper constructing the item by forwarding given arguments to the constructor of
@ -126,6 +129,7 @@ class AbstractGridView : public AbstractView {
template<class ItemT, typename... Args> inline ItemT &add_item(Args &&...args);
const GridViewStyle &get_style() const;
int get_item_count() const;
int get_item_count_filtered() const;
protected:
virtual void build_items() = 0;

View File

@ -3269,6 +3269,13 @@ void UI_interface_tag_script_reload(void);
/* Support click-drag motion which presses the button and closes a popover (like a menu). */
#define USE_UI_POPOVER_ONCE
/**
* Call the #ui::AbstractView::begin_filtering() function of the view to enable filtering.
* Typically used to enable a filter text button. Triggered on Ctrl+F by default.
* \return True when filtering was enabled successfully.
*/
bool UI_view_begin_filtering(const struct bContext *C, const uiViewHandle *view_handle);
bool UI_view_item_is_interactive(const uiViewItemHandle *item_handle);
bool UI_view_item_is_active(const uiViewItemHandle *item_handle);
bool UI_view_item_matches(const uiViewItemHandle *a_handle, const uiViewItemHandle *b_handle);

View File

@ -66,6 +66,7 @@ class TreeViewItemContainer {
enum class IterOptions {
None = 0,
SkipCollapsed = 1 << 0,
SkipFiltered = 1 << 1,
/* Keep ENUM_OPERATORS() below updated! */
};

View File

@ -43,6 +43,7 @@
#include "RNA_access.h"
#include "RNA_define.h"
#include "RNA_enum_types.h"
#include "RNA_path.h"
#include "RNA_prototypes.h"
#include "RNA_types.h"
@ -2341,6 +2342,48 @@ static void UI_OT_list_start_filter(wmOperatorType *ot)
/** \} */
/* -------------------------------------------------------------------- */
/** \name UI View Start Filter Operator
* \{ */
static bool ui_view_focused_poll(bContext *C)
{
const ARegion *region = CTX_wm_region(C);
if (!region) {
return false;
}
const wmWindow *win = CTX_wm_window(C);
const uiViewHandle *view = UI_region_view_find_at(region, win->eventstate->xy, 0);
return view != nullptr;
}
static int ui_view_start_filter_invoke(bContext *C, wmOperator * /*op*/, const wmEvent *event)
{
const ARegion *region = CTX_wm_region(C);
const uiViewHandle *hovered_view = UI_region_view_find_at(region, event->xy, 0);
if (!UI_view_begin_filtering(C, hovered_view)) {
return OPERATOR_CANCELLED | OPERATOR_PASS_THROUGH;
}
return OPERATOR_FINISHED;
}
static void UI_OT_view_start_filter(wmOperatorType *ot)
{
ot->name = "View Filter";
ot->idname = "UI_OT_view_start_filter";
ot->description = "Start entering filter text for the data-set in focus";
ot->invoke = ui_view_start_filter_invoke;
ot->poll = ui_view_focused_poll;
ot->flag = OPTYPE_INTERNAL;
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name UI View Drop Operator
* \{ */
@ -2528,6 +2571,7 @@ void ED_operatortypes_ui(void)
WM_operatortype_append(UI_OT_list_start_filter);
WM_operatortype_append(UI_OT_view_start_filter);
WM_operatortype_append(UI_OT_view_drop);
WM_operatortype_append(UI_OT_view_item_rename);

View File

@ -10,6 +10,8 @@
#include "UI_abstract_view.hh"
using namespace blender;
namespace blender::ui {
void AbstractView::register_item(AbstractViewItem &item)
@ -76,6 +78,11 @@ bool AbstractView::listen(const wmNotifier & /*notifier*/) const
return false;
}
bool AbstractView::begin_filtering(const bContext & /*C*/) const
{
return false;
}
/** \} */
/* ---------------------------------------------------------------------- */
@ -119,16 +126,26 @@ std::optional<rcti> AbstractView::get_bounds() const
/** \} */
} // namespace blender::ui
/* ---------------------------------------------------------------------- */
/** \name General API functions
* \{ */
namespace blender::ui {
std::unique_ptr<DropTargetInterface> view_drop_target(uiViewHandle *view_handle)
{
AbstractView &view = reinterpret_cast<AbstractView &>(*view_handle);
return view.create_drop_target();
}
/** \} */
} // namespace blender::ui
bool UI_view_begin_filtering(const bContext *C, const uiViewHandle *view_handle)
{
const ui::AbstractView &view = reinterpret_cast<const ui::AbstractView &>(*view_handle);
return view.begin_filtering(*C);
}
/** \} */

View File

@ -166,6 +166,27 @@ void AbstractViewItem::build_context_menu(bContext & /*C*/, uiLayout & /*column*
/** \} */
/* ---------------------------------------------------------------------- */
/** \name Filtering
* \{ */
bool AbstractViewItem::is_filtered_visible() const
{
return true;
}
bool AbstractViewItem::is_filtered_visible_cached() const
{
if (is_filtered_visible_.has_value()) {
return *is_filtered_visible_;
}
is_filtered_visible_ = is_filtered_visible();
return *is_filtered_visible_;
}
/** \} */
/* ---------------------------------------------------------------------- */
/** \name Drag 'n Drop
* \{ */

View File

@ -44,6 +44,15 @@ void AbstractGridView::foreach_item(ItemIterFn iter_fn) const
}
}
void AbstractGridView::foreach_filtered_item(ItemIterFn iter_fn) const
{
for (const auto &item_ptr : items_) {
if (item_ptr->is_filtered_visible_cached()) {
iter_fn(*item_ptr);
}
}
}
AbstractGridViewItem *AbstractGridView::find_matching_item(
const AbstractGridViewItem &item_to_match, const AbstractGridView &view_to_search_in) const
{
@ -86,6 +95,20 @@ int AbstractGridView::get_item_count() const
return items_.size();
}
int AbstractGridView::get_item_count_filtered() const
{
if (item_count_filtered_) {
return *item_count_filtered_;
}
int i = 0;
foreach_filtered_item([&i](const auto &) { i++; });
BLI_assert(i <= get_item_count());
item_count_filtered_ = i;
return i;
}
GridViewStyle::GridViewStyle(int width, int height) : tile_width(width), tile_height(height) {}
/* ---------------------------------------------------------------------- */
@ -265,7 +288,7 @@ void BuildOnlyVisibleButtonsHelper::fill_layout_before_visible(uiBlock &block) c
void BuildOnlyVisibleButtonsHelper::fill_layout_after_visible(uiBlock &block) const
{
const int last_item_idx = grid_view_.get_item_count() - 1;
const int last_item_idx = grid_view_.get_item_count_filtered() - 1;
const int last_visible_idx = visible_items_range_.last();
if (last_item_idx > last_visible_idx) {
@ -350,7 +373,7 @@ void GridViewLayoutBuilder::build_from_view(const AbstractGridView &grid_view,
int item_idx = 0;
uiLayout *row = nullptr;
grid_view.foreach_item([&](AbstractGridViewItem &item) {
grid_view.foreach_filtered_item([&](AbstractGridViewItem &item) {
/* Skip if item isn't visible. */
if (!build_visible_helper.is_item_visible(item_idx)) {
item_idx++;

View File

@ -52,7 +52,15 @@ AbstractTreeViewItem &TreeViewItemContainer::add_tree_item(
void TreeViewItemContainer::foreach_item_recursive(ItemIterFn iter_fn, IterOptions options) const
{
for (const auto &child : children_) {
iter_fn(*child);
bool skip = false;
if (bool(options & IterOptions::SkipFiltered) && !child->is_filtered_visible_cached()) {
skip = true;
}
if (!skip) {
iter_fn(*child);
}
if (bool(options & IterOptions::SkipCollapsed) && child->is_collapsed()) {
continue;
}
@ -428,7 +436,8 @@ void TreeViewLayoutBuilder::build_from_tree(const AbstractTreeView &tree_view)
uiLayoutColumn(box, false);
tree_view.foreach_item([this](AbstractTreeViewItem &item) { build_row(item); },
AbstractTreeView::IterOptions::SkipCollapsed);
AbstractTreeView::IterOptions::SkipCollapsed |
AbstractTreeView::IterOptions::SkipFiltered);
UI_block_layout_set_current(&block(), &parent_layout);
}
@ -502,7 +511,7 @@ void TreeViewBuilder::ensure_min_rows_items(AbstractTreeView &tree_view)
int tot_visible_items = 0;
tree_view.foreach_item(
[&tot_visible_items](AbstractTreeViewItem & /*item*/) { tot_visible_items++; },
AbstractTreeView::IterOptions::SkipCollapsed);
AbstractTreeView::IterOptions::SkipCollapsed | AbstractTreeView::IterOptions::SkipFiltered);
if (tot_visible_items >= tree_view.min_rows_) {
return;

View File

@ -45,7 +45,7 @@ set(SRC
io_collada.hh
io_gpencil.hh
io_obj.hh
io_ops.h
io_ops.hh
io_ply_ops.hh
io_stl_ops.hh
io_usd.hh

View File

@ -6,7 +6,7 @@
* \ingroup collada
*/
#include "io_ops.h" /* own include */
#include "io_ops.hh" /* own include */
#include "WM_api.h"
@ -28,7 +28,7 @@
#include "io_ply_ops.hh"
#include "io_stl_ops.hh"
void ED_operatortypes_io(void)
void ED_operatortypes_io()
{
#ifdef WITH_COLLADA
/* Collada operators: */

View File

@ -8,12 +8,4 @@
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
void ED_operatortypes_io(void);
#ifdef __cplusplus
}
#endif
void ED_operatortypes_io();

View File

@ -8,6 +8,7 @@
#include "BLI_color.hh"
#include "BLI_generic_pointer.hh"
#include "BLI_math_quaternion.hh"
#include "BKE_attribute.h"
#include "BKE_context.h"
@ -106,6 +107,8 @@ static StringRefNull rna_property_name_for_type(const eCustomDataType type)
return "value_int";
case CD_PROP_INT32_2D:
return "value_int_vector_2d";
case CD_PROP_QUATERNION:
return "value_quat";
default:
BLI_assert_unreachable();
return "";
@ -198,6 +201,12 @@ static int mesh_set_attribute_exec(bContext *C, wmOperator *op)
case CD_PROP_COLOR:
RNA_float_get_array(op->ptr, prop_name.c_str(), static_cast<float *>(buffer));
break;
case CD_PROP_QUATERNION: {
float4 value;
RNA_float_get_array(op->ptr, prop_name.c_str(), value);
*static_cast<math::Quaternion *>(buffer) = math::normalize(math::Quaternion(value));
break;
}
case CD_PROP_BYTE_COLOR:
ColorGeometry4f value;
RNA_float_get_array(op->ptr, prop_name.c_str(), value);
@ -330,6 +339,11 @@ static int mesh_set_attribute_invoke(bContext *C, wmOperator *op, const wmEvent
case CD_PROP_INT32_2D:
RNA_property_int_set_array(op->ptr, prop, *active_value.get<int2>());
break;
case CD_PROP_QUATERNION: {
const math::Quaternion value = math::normalize(*active_value.get<math::Quaternion>());
RNA_property_float_set_array(op->ptr, prop, float4(value));
break;
}
default:
BLI_assert_unreachable();
}
@ -408,6 +422,16 @@ void MESH_OT_attribute_set(wmOperatorType *ot)
RNA_def_float_color(
ot->srna, "value_color", 4, color_default, -FLT_MAX, FLT_MAX, "Value", "", 0.0f, 1.0f);
RNA_def_boolean(ot->srna, "value_bool", false, "Value", "");
RNA_def_float_array(ot->srna,
"value_quat",
4,
rna_default_quaternion,
-FLT_MAX,
FLT_MAX,
"Value",
"",
FLT_MAX,
FLT_MAX);
}
/** \} */

View File

@ -123,8 +123,10 @@ void PaintOperation::on_stroke_done(const bContext &C)
/* Set position, radius and opacity attribute. */
bke::MutableAttributeAccessor attributes = curves.attributes_for_write();
MutableSpan<float3> positions = curves.positions_for_write();
SpanAttributeWriter<float> radii = attributes.lookup_for_write_span<float>("radius");
SpanAttributeWriter<float> opacities = attributes.lookup_for_write_span<float>("opacity");
SpanAttributeWriter<float> radii = attributes.lookup_or_add_for_write_span<float>(
"radius", ATTR_DOMAIN_POINT);
SpanAttributeWriter<float> opacities = attributes.lookup_or_add_for_write_span<float>(
"opacity", ATTR_DOMAIN_POINT);
for (const int i : IndexRange(stroke_points.size())) {
const bke::greasepencil::StrokePoint &point = stroke_points[i];
const int point_i = new_points_range[i];
@ -135,7 +137,9 @@ void PaintOperation::on_stroke_done(const bContext &C)
/* Set material index attribute. */
int material_index = 0;
SpanAttributeWriter<int> materials = attributes.lookup_for_write_span<int>("material_index");
SpanAttributeWriter<int> materials = attributes.lookup_or_add_for_write_span<int>(
"material_index", ATTR_DOMAIN_CURVE);
materials.span.slice(new_curves_range).fill(material_index);
/* Set curve_type attribute. */

View File

@ -5,6 +5,7 @@
set(INC
../include
../io
../../asset_system
../../blenkernel
../../blenlib
../../gpu
@ -19,7 +20,7 @@ set(INC_SYS
)
set(SRC
spacetypes.c
spacetypes.cc
)
set(LIB

View File

@ -6,7 +6,7 @@
* \ingroup spapi
*/
#include <stdlib.h>
#include <cstdlib>
#include "MEM_guardedalloc.h"
@ -58,9 +58,9 @@
#include "ED_util.h"
#include "ED_uvedit.h"
#include "io_ops.h"
#include "io_ops.hh"
void ED_spacetypes_init(void)
void ED_spacetypes_init()
{
/* UI unit is a variable, may be used in some space type initialization. */
U.widget_unit = 20;
@ -149,7 +149,7 @@ void ED_spacetypes_init(void)
}
}
void ED_spacemacros_init(void)
void ED_spacemacros_init()
{
/* Macros must go last since they reference other operators.
* They need to be registered after python operators too. */
@ -221,22 +221,21 @@ void ED_spacetypes_keymap(wmKeyConfig *keyconf)
/* ********************** Custom Draw Call API ***************** */
typedef struct RegionDrawCB {
struct RegionDrawCB {
struct RegionDrawCB *next, *prev;
void (*draw)(const bContext *, ARegion *, void *);
void *customdata;
int type;
} RegionDrawCB;
};
void *ED_region_draw_cb_activate(ARegionType *art,
void (*draw)(const bContext *, ARegion *, void *),
void *customdata,
int type)
{
RegionDrawCB *rdc = MEM_callocN(sizeof(RegionDrawCB), "RegionDrawCB");
RegionDrawCB *rdc = MEM_cnew<RegionDrawCB>(__func__);
BLI_addtail(&art->drawcalls, rdc);
rdc->draw = draw;
@ -277,7 +276,7 @@ void ED_region_draw_cb_draw(const bContext *C, ARegion *region, int type)
void ED_region_surface_draw_cb_draw(ARegionType *art, int type)
{
ed_region_draw_cb_draw(NULL, NULL, art, type);
ed_region_draw_cb_draw(nullptr, nullptr, art, type);
}
void ED_region_draw_cb_remove_by_type(ARegionType *art, void *draw_fn, void (*free)(void *))
@ -295,19 +294,19 @@ void ED_region_draw_cb_remove_by_type(ARegionType *art, void *draw_fn, void (*fr
/* ********************* space template *********************** */
/* forward declare */
void ED_spacetype_xxx(void);
void ED_spacetype_xxx();
/* allocate and init some vars */
static SpaceLink *xxx_create(const ScrArea *UNUSED(area), const Scene *UNUSED(scene))
static SpaceLink *xxx_create(const ScrArea * /*area*/, const Scene * /*scene*/)
{
return NULL;
return nullptr;
}
/* Doesn't free the space-link itself. */
static void xxx_free(SpaceLink *UNUSED(sl)) {}
static void xxx_free(SpaceLink * /*sl*/) {}
/* spacetype; init callback for usage, should be re-doable. */
static void xxx_init(wmWindowManager *UNUSED(wm), ScrArea *UNUSED(area))
static void xxx_init(wmWindowManager * /*wm*/, ScrArea * /*area*/)
{
/* link area to SpaceXXX struct */
@ -317,24 +316,23 @@ static void xxx_init(wmWindowManager *UNUSED(wm), ScrArea *UNUSED(area))
/* add types to regions */
}
static SpaceLink *xxx_duplicate(SpaceLink *UNUSED(sl))
static SpaceLink *xxx_duplicate(SpaceLink * /*sl*/)
{
return NULL;
return nullptr;
}
static void xxx_operatortypes(void)
static void xxx_operatortypes()
{
/* register operator types for this space */
}
static void xxx_keymap(wmKeyConfig *UNUSED(keyconf))
static void xxx_keymap(wmKeyConfig * /*keyconf*/)
{
/* add default items to keymap */
}
/* only called once, from screen/spacetypes.c */
void ED_spacetype_xxx(void)
/* only called once, from screen/spacetypes.cc */
void ED_spacetype_xxx()
{
static SpaceType st;

View File

@ -405,8 +405,8 @@ std::string AssetCatalogDropTarget::drop_tooltip_asset_catalog(const wmDrag &dra
const AssetCatalog *src_catalog = get_drag_catalog(drag, get_asset_library());
return fmt::format(TIP_("Move catalog {} into {}"),
(std::string_view)src_catalog->path.name(),
(std::string_view)catalog_item_.get_name());
std::string_view(src_catalog->path.name()),
std::string_view(catalog_item_.get_name()));
}
std::string AssetCatalogDropTarget::drop_tooltip_asset_list(const wmDrag &drag) const
@ -620,7 +620,7 @@ std::string AssetCatalogTreeViewAllItem::DropTarget::drop_tooltip(const wmDrag &
drag, *get_view<AssetCatalogTreeView>().asset_library_);
return fmt::format(TIP_("Move catalog {} to the top level of the tree"),
(std::string_view)drag_catalog->path.name());
std::string_view(drag_catalog->path.name()));
}
bool AssetCatalogTreeViewAllItem::DropTarget::on_drop(bContext * /*C*/, const wmDrag &drag) const

View File

@ -247,6 +247,13 @@ static int node_clipboard_paste_exec(bContext *C, wmOperator *op)
{
bNode *new_node = bke::node_copy_with_mapping(
&tree, node, LIB_ID_COPY_DEFAULT, true, socket_map);
/* Reset socket shape in case a node is copied to a different tree type. */
LISTBASE_FOREACH (bNodeSocket *, socket, &new_node->inputs) {
socket->display_shape = SOCK_DISPLAY_SHAPE_CIRCLE;
}
LISTBASE_FOREACH (bNodeSocket *, socket, &new_node->outputs) {
socket->display_shape = SOCK_DISPLAY_SHAPE_CIRCLE;
}
node_map.add_new(&node, new_node);
}
else {

View File

@ -59,9 +59,11 @@ set(SRC
tree/tree_element_id.cc
tree/tree_element_id_curve.cc
tree/tree_element_id_library.cc
tree/tree_element_id_linestyle.cc
tree/tree_element_id_mesh.cc
tree/tree_element_id_metaball.cc
tree/tree_element_id_scene.cc
tree/tree_element_id_texture.cc
tree/tree_element_label.cc
tree/tree_element_nla.cc
tree/tree_element_overrides.cc
@ -82,9 +84,11 @@ set(SRC
tree/tree_element_id.hh
tree/tree_element_id_curve.hh
tree/tree_element_id_library.hh
tree/tree_element_id_linestyle.hh
tree/tree_element_id_mesh.hh
tree/tree_element_id_metaball.hh
tree/tree_element_id_scene.hh
tree/tree_element_id_texture.hh
tree/tree_element_label.hh
tree/tree_element_nla.hh
tree/tree_element_overrides.hh

View File

@ -554,6 +554,8 @@ static void outliner_add_id_contents(SpaceOutliner *space_outliner,
case ID_ME:
case ID_CU_LEGACY:
case ID_MB:
case ID_TE:
case ID_LS:
BLI_assert_msg(0, "ID type expected to be expanded through new tree-element design");
break;
case ID_OB: {
@ -567,14 +569,6 @@ static void outliner_add_id_contents(SpaceOutliner *space_outliner,
}
break;
}
case ID_TE: {
Tex *tex = (Tex *)id;
if (outliner_animdata_test(tex->adt)) {
outliner_add_element(space_outliner, &te->subtree, tex, te, TSE_ANIM_DATA, 0);
}
outliner_add_element(space_outliner, &te->subtree, tex->ima, te, TSE_SOME_ID, 0);
break;
}
case ID_CA: {
Camera *ca = (Camera *)id;
if (outliner_animdata_test(ca->adt)) {
@ -679,20 +673,6 @@ static void outliner_add_id_contents(SpaceOutliner *space_outliner,
}
break;
}
case ID_LS: {
FreestyleLineStyle *linestyle = (FreestyleLineStyle *)id;
if (outliner_animdata_test(linestyle->adt)) {
outliner_add_element(space_outliner, &te->subtree, linestyle, te, TSE_ANIM_DATA, 0);
}
for (int a = 0; a < MAX_MTEX; a++) {
if (linestyle->mtex[a]) {
outliner_add_element(space_outliner, &te->subtree, linestyle->mtex[a]->tex, te, 0, a);
}
}
break;
}
case ID_GD_LEGACY: {
bGPdata *gpd = (bGPdata *)id;

View File

@ -22,9 +22,11 @@
#include "common.hh"
#include "tree_element_id_curve.hh"
#include "tree_element_id_library.hh"
#include "tree_element_id_linestyle.hh"
#include "tree_element_id_mesh.hh"
#include "tree_element_id_metaball.hh"
#include "tree_element_id_scene.hh"
#include "tree_element_id_texture.hh"
#include "tree_element_id.hh"
@ -48,9 +50,12 @@ std::unique_ptr<TreeElementID> TreeElementID::createFromID(TreeElement &legacy_t
return std::make_unique<TreeElementIDCurve>(legacy_te, (Curve &)id);
case ID_MB:
return std::make_unique<TreeElementIDMetaBall>(legacy_te, (MetaBall &)id);
case ID_TE:
return std::make_unique<TreeElementIDTexture>(legacy_te, (Tex &)id);
case ID_LS:
return std::make_unique<TreeElementIDLineStyle>(legacy_te, (FreestyleLineStyle &)id);
case ID_OB:
case ID_MA:
case ID_TE:
case ID_LT:
case ID_LA:
case ID_CA:
@ -64,7 +69,6 @@ std::unique_ptr<TreeElementID> TreeElementID::createFromID(TreeElement &legacy_t
case ID_PA:
case ID_MC:
case ID_MSK:
case ID_LS:
case ID_LP:
case ID_GD_LEGACY:
case ID_WS:

View File

@ -0,0 +1,53 @@
/* SPDX-FileCopyrightText: 2023 Blender Foundation
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup spoutliner
*/
#include "DNA_ID.h"
#include "DNA_linestyle_types.h"
#include "DNA_listBase.h"
#include "DNA_outliner_types.h"
#include "DNA_texture_types.h"
#include "../outliner_intern.hh"
#include "tree_element_id_linestyle.hh"
namespace blender::ed::outliner {
TreeElementIDLineStyle::TreeElementIDLineStyle(TreeElement &legacy_te,
FreestyleLineStyle &linestyle)
: TreeElementID(legacy_te, linestyle.id), linestyle_(linestyle)
{
}
void TreeElementIDLineStyle::expand(SpaceOutliner &space_outliner) const
{
expand_animation_data(space_outliner, linestyle_.adt);
expandTextures(space_outliner);
}
bool TreeElementIDLineStyle::isExpandValid() const
{
return true;
}
void TreeElementIDLineStyle::expandTextures(SpaceOutliner &space_outliner) const
{
for (int a = 0; a < MAX_MTEX; a++) {
if (linestyle_.mtex[a]) {
outliner_add_element(&space_outliner,
&legacy_te_.subtree,
(linestyle_.mtex[a])->tex,
&legacy_te_,
TSE_SOME_ID,
a);
}
}
}
} // namespace blender::ed::outliner

View File

@ -0,0 +1,30 @@
/* SPDX-FileCopyrightText: 2023 Blender Foundation
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup spoutliner
*/
#pragma once
#include "tree_element_id.hh"
struct FreestyleLineStyle;
namespace blender::ed::outliner {
class TreeElementIDLineStyle final : public TreeElementID {
FreestyleLineStyle &linestyle_;
public:
TreeElementIDLineStyle(TreeElement &legacy_te, FreestyleLineStyle &linestyle);
void expand(SpaceOutliner &) const override;
bool isExpandValid() const override;
private:
void expandTextures(SpaceOutliner &) const;
};
} // namespace blender::ed::outliner

View File

@ -0,0 +1,42 @@
/* SPDX-FileCopyrightText: 2023 Blender Foundation
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup spoutliner
*/
#include "DNA_listBase.h"
#include "DNA_outliner_types.h"
#include "DNA_texture_types.h"
#include "../outliner_intern.hh"
#include "tree_element_id_texture.hh"
namespace blender::ed::outliner {
TreeElementIDTexture::TreeElementIDTexture(TreeElement &legacy_te, Tex &texture)
: TreeElementID(legacy_te, texture.id), texture_(texture)
{
}
bool TreeElementIDTexture::isExpandValid() const
{
return true;
}
void TreeElementIDTexture::expand(SpaceOutliner &space_outliner) const
{
expand_animation_data(space_outliner, texture_.adt);
expandImage(space_outliner);
}
void TreeElementIDTexture::expandImage(SpaceOutliner &space_outliner) const
{
outliner_add_element(
&space_outliner, &legacy_te_.subtree, texture_.ima, &legacy_te_, TSE_SOME_ID, 0);
}
} // namespace blender::ed::outliner

View File

@ -0,0 +1,28 @@
/* SPDX-FileCopyrightText: 2023 Blender Foundation
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup spoutliner
*/
#pragma once
#include "tree_element_id.hh"
namespace blender::ed::outliner {
class TreeElementIDTexture final : public TreeElementID {
Tex &texture_;
public:
TreeElementIDTexture(TreeElement &legacy_te, Tex &texture);
void expand(SpaceOutliner &) const override;
bool isExpandValid() const override;
private:
void expandImage(SpaceOutliner &) const;
};
} // namespace blender::ed::outliner

View File

@ -37,6 +37,7 @@ typedef struct GizmoGroup_retime {
wmGizmo *add_handle_gizmo;
wmGizmo *move_handle_gizmo;
wmGizmo *remove_handle_gizmo;
wmGizmo *speed_set_gizmo;
} GizmoGroup_retime;
static bool gizmogroup_retime_poll(const bContext *C, wmGizmoGroupType *gzgt)
@ -81,6 +82,8 @@ static void gizmogroup_retime_setup(const bContext * /* C */, wmGizmoGroup *gzgr
ggd->remove_handle_gizmo = WM_gizmo_new_ptr(gzt_remove_handle, gzgroup, nullptr);
const wmGizmoType *gzt_move_handle = WM_gizmotype_find("GIZMO_GT_retime_handle_move", true);
ggd->move_handle_gizmo = WM_gizmo_new_ptr(gzt_move_handle, gzgroup, nullptr);
const wmGizmoType *gzt_speed_set = WM_gizmotype_find("GIZMO_GT_retime_speed_set", true);
ggd->speed_set_gizmo = WM_gizmo_new_ptr(gzt_speed_set, gzgroup, nullptr);
gzgroup->customdata = ggd;
/* Assign operators. */
@ -90,6 +93,8 @@ static void gizmogroup_retime_setup(const bContext * /* C */, wmGizmoGroup *gzgr
WM_gizmo_operator_set(ggd->add_handle_gizmo, 0, ot, nullptr);
ot = WM_operatortype_find("SEQUENCER_OT_retiming_handle_remove", true);
WM_gizmo_operator_set(ggd->remove_handle_gizmo, 0, ot, nullptr);
ot = WM_operatortype_find("SEQUENCER_OT_retiming_segment_speed_set", true);
WM_gizmo_operator_set(ggd->speed_set_gizmo, 0, ot, nullptr);
}
void SEQUENCER_GGT_gizmo_retime(wmGizmoGroupType *gzgt)

View File

@ -403,61 +403,6 @@ static void retime_handle_draw(const bContext *C,
immEnd();
}
static void retime_speed_text_draw(const bContext *C,
const Sequence *seq,
const SeqRetimingHandle *handle)
{
SeqRetimingHandle *last_handle = SEQ_retiming_last_handle_get(seq);
if (handle == last_handle) {
return;
}
const Scene *scene = CTX_data_scene(C);
const int start_frame = SEQ_time_left_handle_frame_get(scene, seq);
const int end_frame = SEQ_time_right_handle_frame_get(scene, seq);
int next_handle_index = SEQ_retiming_handle_index_get(seq, handle) + 1;
const SeqRetimingHandle *next_handle = &SEQ_retiming_handles_get(seq)[next_handle_index];
if (handle_x_get(scene, seq, next_handle) < start_frame ||
handle_x_get(scene, seq, handle) > end_frame)
{
return; /* Label out of strip bounds. */
}
char label_str[40];
size_t label_len;
if (SEQ_retiming_handle_is_transition_type(handle)) {
const float prev_speed = SEQ_retiming_handle_speed_get(seq, handle - 1);
const float next_speed = SEQ_retiming_handle_speed_get(seq, next_handle + 1);
label_len = SNPRINTF_RLEN(label_str,
"%d%% - %d%%",
round_fl_to_int(prev_speed * 100.0f),
round_fl_to_int(next_speed * 100.0f));
}
else {
const float speed = SEQ_retiming_handle_speed_get(seq, next_handle);
label_len = SNPRINTF_RLEN(label_str, "%d%%", round_fl_to_int(speed * 100.0f));
}
const float width = pixels_to_view_width(C, BLF_width(BLF_default(), label_str, label_len));
const float xmin = max_ff(SEQ_time_left_handle_frame_get(scene, seq),
handle_x_get(scene, seq, handle));
const float xmax = min_ff(SEQ_time_right_handle_frame_get(scene, seq),
handle_x_get(scene, seq, next_handle));
const float text_x = (xmin + xmax - width) / 2;
const float text_y = strip_y_rescale(seq, 0) + pixels_to_view_height(C, 5);
if (width > xmax - xmin) {
return; /* Not enough space to draw label. */
}
const uchar col[4] = {255, 255, 255, 255};
UI_view2d_text_cache_add(UI_view2d_fromcontext(C), text_x, text_y, label_str, label_len, col);
}
static void gizmo_retime_handle_draw(const bContext *C, wmGizmo *gz)
{
RetimeHandleMoveGizmo *gizmo = (RetimeHandleMoveGizmo *)gz;
@ -488,8 +433,6 @@ static void gizmo_retime_handle_draw(const bContext *C, wmGizmo *gz)
MutableSpan handles = SEQ_retiming_handles_get(seq);
for (const SeqRetimingHandle &handle : handles) {
retime_speed_text_draw(C, seq, &handle);
if (&handle == handles.begin()) {
continue; /* Ignore first handle. */
}
@ -646,3 +589,183 @@ void GIZMO_GT_retime_remove(wmGizmoType *gzt)
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name Retiming Speed Set Gizmo
* \{ */
static size_t label_str_get(const Sequence *seq,
const SeqRetimingHandle *handle,
size_t str_len,
char *r_label_str)
{
const SeqRetimingHandle *next_handle = handle + 1;
if (SEQ_retiming_handle_is_transition_type(handle)) {
const float prev_speed = SEQ_retiming_handle_speed_get(seq, handle - 1);
const float next_speed = SEQ_retiming_handle_speed_get(seq, next_handle + 1);
return BLI_snprintf_rlen(r_label_str,
str_len,
"%d%% - %d%%",
round_fl_to_int(prev_speed * 100.0f),
round_fl_to_int(next_speed * 100.0f));
}
const float speed = SEQ_retiming_handle_speed_get(seq, next_handle);
return BLI_snprintf_rlen(r_label_str, str_len, "%d%%", round_fl_to_int(speed * 100.0f));
}
static bool label_rect_get(const bContext *C,
const Sequence *seq,
const SeqRetimingHandle *handle,
char *label_str,
size_t label_len,
rctf *rect)
{
const Scene *scene = CTX_data_scene(C);
const SeqRetimingHandle *next_handle = handle + 1;
const float width = pixels_to_view_width(C, BLF_width(BLF_default(), label_str, label_len));
const float height = pixels_to_view_height(C, BLF_height(BLF_default(), label_str, label_len));
const float xmin = max_ff(SEQ_time_left_handle_frame_get(scene, seq),
handle_x_get(scene, seq, handle));
const float xmax = min_ff(SEQ_time_right_handle_frame_get(scene, seq),
handle_x_get(scene, seq, next_handle));
rect->xmin = (xmin + xmax - width) / 2;
rect->xmax = rect->xmin + width;
rect->ymin = strip_y_rescale(seq, 0) + pixels_to_view_height(C, 5);
rect->ymax = rect->ymin + height;
return width < xmax - xmin;
}
static void label_rect_apply_mouseover_offset(const View2D *v2d, rctf *rect)
{
float scale_x, scale_y;
UI_view2d_scale_get_inverse(v2d, &scale_x, &scale_y);
rect->xmin -= RETIME_HANDLE_MOUSEOVER_THRESHOLD * scale_x;
rect->xmax += RETIME_HANDLE_MOUSEOVER_THRESHOLD * scale_x;
rect->ymax += RETIME_HANDLE_MOUSEOVER_THRESHOLD * scale_y;
}
static void retime_speed_text_draw(const bContext *C,
const Sequence *seq,
const SeqRetimingHandle *handle)
{
SeqRetimingHandle *last_handle = SEQ_retiming_last_handle_get(seq);
if (handle == last_handle) {
return;
}
const Scene *scene = CTX_data_scene(C);
const int start_frame = SEQ_time_left_handle_frame_get(scene, seq);
const int end_frame = SEQ_time_right_handle_frame_get(scene, seq);
const SeqRetimingHandle *next_handle = handle + 1;
if (handle_x_get(scene, seq, next_handle) < start_frame ||
handle_x_get(scene, seq, handle) > end_frame)
{
return; /* Label out of strip bounds. */
}
char label_str[40];
rctf label_rect;
size_t label_len = label_str_get(seq, handle, sizeof(label_str), label_str);
if (!label_rect_get(C, seq, handle, label_str, label_len, &label_rect)) {
return; /* Not enough space to draw label. */
}
const uchar col[4] = {255, 255, 255, 255};
UI_view2d_text_cache_add(
UI_view2d_fromcontext(C), label_rect.xmin, label_rect.ymin, label_str, label_len, col);
}
static void gizmo_retime_speed_set_draw(const bContext *C, wmGizmo * /* gz */)
{
const View2D *v2d = UI_view2d_fromcontext(C);
wmOrtho2_region_pixelspace(CTX_wm_region(C));
GPU_blend(GPU_BLEND_ALPHA);
GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
Sequence *seq = active_seq_from_context(C);
SEQ_retiming_data_ensure(seq);
MutableSpan handles = SEQ_retiming_handles_get(seq);
for (const SeqRetimingHandle &handle : handles) {
retime_speed_text_draw(C, seq, &handle);
}
immUnbindProgram();
GPU_blend(GPU_BLEND_NONE);
UI_view2d_text_cache_draw(CTX_wm_region(C));
UI_view2d_view_ortho(v2d); /* 'UI_view2d_text_cache_draw()' messes up current view. */
}
static int gizmo_retime_speed_set_test_select(bContext *C, wmGizmo *gz, const int mval[2])
{
Scene *scene = CTX_data_scene(C);
wmGizmoOpElem *op_elem = WM_gizmo_operator_get(gz, 0);
const View2D *v2d = UI_view2d_fromcontext(C);
Sequence *seq = active_seq_from_context(C);
SEQ_retiming_data_ensure(seq);
for (const SeqRetimingHandle &handle : SEQ_retiming_handles_get(seq)) {
if (SEQ_retiming_handle_is_transition_type(&handle)) {
continue;
}
char label_str[40];
rctf label_rect;
size_t label_len = label_str_get(seq, &handle, sizeof(label_str), label_str);
if (!label_rect_get(C, seq, &handle, label_str, label_len, &label_rect)) {
continue;
}
label_rect_apply_mouseover_offset(v2d, &label_rect);
float mouse_view[2];
UI_view2d_region_to_view(v2d, mval[0], mval[1], &mouse_view[0], &mouse_view[1]);
if (!BLI_rctf_isect_pt(&label_rect, mouse_view[0], mouse_view[1])) {
continue;
}
/* Store next handle in RNA property, since label rect uses first handle as reference. */
const int handle_index = SEQ_retiming_handle_index_get(seq, &handle) + 1;
RNA_int_set(&op_elem->ptr, "handle_index", handle_index);
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
return 0;
}
return -1;
}
static int gizmo_retime_speed_set_cursor_get(wmGizmo *gz)
{
if (RNA_boolean_get(gz->ptr, "show_drag")) {
return WM_CURSOR_TEXT_EDIT;
}
return WM_CURSOR_DEFAULT;
}
void GIZMO_GT_speed_set_remove(wmGizmoType *gzt)
{
/* Identifiers. */
gzt->idname = "GIZMO_GT_retime_speed_set";
/* Api callbacks. */
gzt->draw = gizmo_retime_speed_set_draw;
gzt->test_select = gizmo_retime_speed_set_test_select;
gzt->cursor_get = gizmo_retime_speed_set_cursor_get;
gzt->struct_size = sizeof(wmGizmo);
/* Currently only used for cursor display. */
RNA_def_boolean(gzt->srna, "show_drag", true, "Show Drag", "");
}
/** \} */

View File

@ -312,6 +312,7 @@ void SEQUENCER_OT_retiming_reset(struct wmOperatorType *ot);
void SEQUENCER_OT_retiming_handle_move(struct wmOperatorType *ot);
void SEQUENCER_OT_retiming_handle_add(struct wmOperatorType *ot);
void SEQUENCER_OT_retiming_handle_remove(struct wmOperatorType *ot);
void SEQUENCER_OT_retiming_segment_speed_set(struct wmOperatorType *ot);
/* sequencer_gizmo_retime.c */
void SEQUENCER_GGT_gizmo_retime(struct wmGizmoGroupType *gzgt);
@ -320,6 +321,7 @@ void SEQUENCER_GGT_gizmo_retime(struct wmGizmoGroupType *gzgt);
void GIZMO_GT_retime_handle_add(struct wmGizmoType *gzt);
void GIZMO_GT_retime_handle(struct wmGizmoType *gzt);
void GIZMO_GT_retime_remove(struct wmGizmoType *gzt);
void GIZMO_GT_speed_set_remove(struct wmGizmoType *gzt);
#ifdef __cplusplus
}

View File

@ -74,6 +74,7 @@ void sequencer_operatortypes(void)
WM_operatortype_append(SEQUENCER_OT_retiming_handle_move);
WM_operatortype_append(SEQUENCER_OT_retiming_handle_add);
WM_operatortype_append(SEQUENCER_OT_retiming_handle_remove);
WM_operatortype_append(SEQUENCER_OT_retiming_segment_speed_set);
/* sequencer_select.c */
WM_operatortype_append(SEQUENCER_OT_select_all);

View File

@ -461,3 +461,95 @@ void SEQUENCER_OT_retiming_handle_remove(wmOperatorType *ot)
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name Retiming Set Segment Speed
* \{ */
static int sequencer_retiming_segment_speed_set_exec(bContext *C, wmOperator *op)
{
Scene *scene = CTX_data_scene(C);
const Editing *ed = SEQ_editing_get(scene);
Sequence *seq = ed->act_seq;
MutableSpan handles = SEQ_retiming_handles_get(seq);
SeqRetimingHandle *handle = &handles[RNA_int_get(op->ptr, "handle_index")];
SEQ_retiming_handle_speed_set(scene, seq, handle, RNA_float_get(op->ptr, "speed"));
SEQ_relations_invalidate_cache_raw(scene, seq);
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
return OPERATOR_FINISHED;
}
static int sequencer_retiming_segment_speed_set_invoke(bContext *C,
wmOperator *op,
const wmEvent *event)
{
const Scene *scene = CTX_data_scene(C);
const Editing *ed = SEQ_editing_get(scene);
const Sequence *seq = ed->act_seq;
if (seq == nullptr) {
return OPERATOR_CANCELLED;
}
MutableSpan handles = SEQ_retiming_handles_get(seq);
SeqRetimingHandle *handle = nullptr;
if (RNA_struct_property_is_set(op->ptr, "handle_index")) {
const int handle_index = RNA_int_get(op->ptr, "handle_index");
BLI_assert(handle_index < handles.size());
handle = &handles[handle_index];
}
else {
handle = closest_retiming_handle_get(C, seq, event->mval[0]);
}
if (handle == nullptr) {
BKE_report(op->reports, RPT_ERROR, "No handle available");
return OPERATOR_CANCELLED;
}
RNA_float_set(op->ptr, "speed", SEQ_retiming_handle_speed_get(seq, handle) * 100.0f);
RNA_int_set(op->ptr, "handle_index", SEQ_retiming_handle_index_get(seq, handle));
return WM_operator_props_popup(C, op, event);
}
void SEQUENCER_OT_retiming_segment_speed_set(wmOperatorType *ot)
{
/* identifiers */
ot->name = "Set Speed";
ot->description = "Set speed of retimed segment";
ot->idname = "SEQUENCER_OT_retiming_segment_speed_set";
/* api callbacks */
ot->invoke = sequencer_retiming_segment_speed_set_invoke;
ot->exec = sequencer_retiming_segment_speed_set_exec;
ot->poll = retiming_poll;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
/* properties */
PropertyRNA *prop = RNA_def_int(ot->srna,
"handle_index",
0,
0,
INT_MAX,
"Handle Index",
"Index of handle to be removed",
0,
INT_MAX);
RNA_def_property_flag(prop, PROP_HIDDEN);
prop = RNA_def_float(ot->srna,
"speed",
100.0f,
0.001f,
FLT_MAX,
"Speed",
"New speed of retimed segment",
0.1f,
FLT_MAX);
}
/** \} */

View File

@ -430,6 +430,7 @@ static void sequencer_gizmos(void)
WM_gizmotype_append(GIZMO_GT_retime_handle_add);
WM_gizmotype_append(GIZMO_GT_retime_handle);
WM_gizmotype_append(GIZMO_GT_retime_remove);
WM_gizmotype_append(GIZMO_GT_speed_set_remove);
WM_gizmogrouptype_append(SEQUENCER_GGT_gizmo2d);
WM_gizmogrouptype_append(SEQUENCER_GGT_gizmo2d_translate);

View File

@ -346,6 +346,7 @@ static float get_default_column_width(const ColumnValues &values)
return 3.0f * float_width;
case SPREADSHEET_VALUE_TYPE_COLOR:
case SPREADSHEET_VALUE_TYPE_BYTE_COLOR:
case SPREADSHEET_VALUE_TYPE_QUATERNION:
return 4.0f * float_width;
case SPREADSHEET_VALUE_TYPE_INSTANCES:
return 8.0f;

View File

@ -9,6 +9,7 @@
#include "BLI_color.hh"
#include "BLI_cpp_type.hh"
#include "BLI_hash.hh"
#include "BLI_math_quaternion_types.hh"
#include "BLI_math_vector_types.hh"
#include "BLI_string.h"
#include "BLI_string_ref.hh"
@ -56,6 +57,9 @@ eSpreadsheetColumnValueType cpp_type_to_column_type(const CPPType &type)
if (type.is<ColorGeometry4b>()) {
return SPREADSHEET_VALUE_TYPE_BYTE_COLOR;
}
if (type.is<math::Quaternion>()) {
return SPREADSHEET_VALUE_TYPE_QUATERNION;
}
return SPREADSHEET_VALUE_TYPE_UNKNOWN;
}

View File

@ -5,6 +5,7 @@
#include <iomanip>
#include <sstream>
#include "BLI_math_quaternion_types.hh"
#include "BLI_math_vector_types.hh"
#include "BKE_geometry_set.hh"
@ -204,6 +205,10 @@ class SpreadsheetLayoutDrawer : public SpreadsheetDrawer {
const ColorGeometry4b value = data.get<ColorGeometry4b>(real_index);
this->draw_byte_color(params, value);
}
else if (data.type().is<math::Quaternion>()) {
const float4 value = float4(data.get<math::Quaternion>(real_index));
this->draw_float_vector(params, Span(&value.x, 4));
}
else if (data.type().is<bke::InstanceReference>()) {
const bke::InstanceReference value = data.get<bke::InstanceReference>(real_index);
switch (value.type()) {

View File

@ -107,6 +107,7 @@ static std::string value_string(const SpreadsheetRowFilter &row_filter,
}
case SPREADSHEET_VALUE_TYPE_STRING:
return row_filter.value_string;
case SPREADSHEET_VALUE_TYPE_QUATERNION:
case SPREADSHEET_VALUE_TYPE_UNKNOWN:
return "";
}
@ -250,7 +251,8 @@ static void spreadsheet_filter_panel_draw(const bContext *C, Panel *panel)
uiItemR(layout, filter_ptr, "value_string", 0, IFACE_("Value"), ICON_NONE);
break;
case SPREADSHEET_VALUE_TYPE_UNKNOWN:
uiItemL(layout, IFACE_("Unknown column type"), ICON_ERROR);
case SPREADSHEET_VALUE_TYPE_QUATERNION:
uiItemL(layout, IFACE_("Unsupported column type"), ICON_ERROR);
break;
}
}

View File

@ -590,6 +590,9 @@ static void handle_armature_parent_orientation(Object *ob, float r_mat[3][3])
if (active_pchan && active_pchan->parent) {
/* For child, show parent local regardless if "local location" is set for parent bone. */
transform_orientations_create_from_axis(r_mat, UNPACK3(active_pchan->parent->pose_mat));
float ob_orientations_mat[3][3];
transform_orientations_create_from_axis(ob_orientations_mat, UNPACK3(ob->object_to_world));
mul_m3_m3_pre(r_mat, ob_orientations_mat);
return;
}

View File

@ -6,6 +6,7 @@
#include "BLI_cpp_type_make.hh"
#include "BLI_cpp_types_make.hh"
#include "BLI_math_matrix_types.hh"
#include "BLI_math_quaternion_types.hh"
#include "BLI_math_vector_types.hh"
#include "FN_field_cpp_type_make.hh"
@ -16,6 +17,7 @@ FN_FIELD_CPP_TYPE_MAKE(blender::float2);
FN_FIELD_CPP_TYPE_MAKE(blender::float3);
FN_FIELD_CPP_TYPE_MAKE(blender::ColorGeometry4f);
FN_FIELD_CPP_TYPE_MAKE(blender::ColorGeometry4b);
FN_FIELD_CPP_TYPE_MAKE(blender::math::Quaternion);
FN_FIELD_CPP_TYPE_MAKE(bool);
FN_FIELD_CPP_TYPE_MAKE(int8_t);
FN_FIELD_CPP_TYPE_MAKE(int32_t);
@ -31,6 +33,7 @@ void FN_register_cpp_types()
FN_FIELD_CPP_TYPE_REGISTER(blender::float3);
FN_FIELD_CPP_TYPE_REGISTER(blender::ColorGeometry4f);
FN_FIELD_CPP_TYPE_REGISTER(blender::ColorGeometry4b);
FN_FIELD_CPP_TYPE_REGISTER(blender::math::Quaternion);
FN_FIELD_CPP_TYPE_REGISTER(bool);
FN_FIELD_CPP_TYPE_REGISTER(int8_t);
FN_FIELD_CPP_TYPE_REGISTER(int32_t);

View File

@ -1457,6 +1457,8 @@ static void customdata_weld(
int src_i, dest_i;
int j;
int vs_flag = 0;
/* interpolates a layer at a time */
dest_i = 0;
for (src_i = 0; src_i < source->totlayer; src_i++) {
@ -1477,7 +1479,21 @@ static void customdata_weld(
/* if we found a matching layer, add the data */
if (dest->layers[dest_i].type == type) {
void *src_data = source->layers[src_i].data;
if (CustomData_layer_has_interp(dest, dest_i)) {
if (type == CD_MVERT_SKIN) {
/* The `typeInfo->interp` of #CD_MVERT_SKIN does not include the flags, so #MVERT_SKIN_ROOT
* and #MVERT_SKIN_LOOSE are lost after the interpolation.
*
* This behavior is not incorrect. Ideally, islands should be checked to avoid repeated
* roots.
*
* However, for now, to prevent the loss of flags, they are simply re-added if any of the
* merged vertices have them. */
for (j = 0; j < count; j++) {
MVertSkin *vs = &((MVertSkin *)src_data)[src_indices[j]];
vs_flag |= vs->flag;
}
}
else if (CustomData_layer_has_interp(dest, dest_i)) {
/* Already calculated.
* TODO: Optimize by exposing `typeInfo->interp`. */
}
@ -1507,7 +1523,11 @@ static void customdata_weld(
for (dest_i = 0; dest_i < dest->totlayer; dest_i++) {
CustomDataLayer *layer_dst = &dest->layers[dest_i];
const eCustomDataType type = eCustomDataType(layer_dst->type);
if (CustomData_layer_has_interp(dest, dest_i)) {
if (type == CD_MVERT_SKIN) {
MVertSkin *vs = &((MVertSkin *)layer_dst->data)[dest_index];
vs->flag = vs_flag;
}
else if (CustomData_layer_has_interp(dest, dest_i)) {
/* Already calculated. */
}
else if (CustomData_layer_has_math(dest, dest_i)) {

View File

@ -482,6 +482,7 @@ set(GLSL_SRC
shaders/material/gpu_shader_material_eevee_specular.glsl
shaders/material/gpu_shader_material_emission.glsl
shaders/material/gpu_shader_material_fractal_noise.glsl
shaders/material/gpu_shader_material_fractal_voronoi.glsl
shaders/material/gpu_shader_material_fresnel.glsl
shaders/material/gpu_shader_material_gamma.glsl
shaders/material/gpu_shader_material_geometry.glsl
@ -546,6 +547,7 @@ set(GLSL_SRC
shaders/material/gpu_shader_material_volume_absorption.glsl
shaders/material/gpu_shader_material_volume_principled.glsl
shaders/material/gpu_shader_material_volume_scatter.glsl
shaders/material/gpu_shader_material_voronoi.glsl
shaders/material/gpu_shader_material_wireframe.glsl
shaders/material/gpu_shader_material_world_normals.glsl
@ -793,8 +795,6 @@ if(WITH_GPU_BUILDTIME_SHADER_BUILDER)
intern/gpu_shader_builder_stubs.cc
${shader_create_info_list_file}
)
setup_platform_linker_flags(shader_builder)
target_link_libraries(shader_builder PUBLIC buildinfoobj)
else()
if(WIN32)
@ -809,8 +809,9 @@ if(WITH_GPU_BUILDTIME_SHADER_BUILDER)
${shader_create_info_list_file}
${MANIFEST}
)
endif()
setup_platform_linker_flags(shader_builder)
target_link_libraries(shader_builder PUBLIC
bf_gpu
bf_intern_clog
@ -848,6 +849,7 @@ if(WITH_GTESTS)
tests/gpu_testing.cc
tests/buffer_texture_test.cc
tests/compute_test.cc
tests/framebuffer_test.cc
tests/immediate_test.cc
tests/index_buffer_test.cc

View File

@ -271,5 +271,36 @@ void DRW_cdlayer_attr_aliases_add(struct GPUVertFormat * /*format*/,
{
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name Stubs of IMB_imbuf.h
* \{ */
struct ImBuf *IMB_ibImageFromMemory(const unsigned char * /*mem*/,
size_t /*size*/,
int /*flags*/,
char /*colorspace*/[IM_MAX_SPACE],
const char * /*descr*/)
{
BLI_assert_unreachable();
return nullptr;
}
struct ImBuf *IMB_allocFromBuffer(const uint8_t * /*rect*/,
const float * /*rectf*/,
unsigned int /*w*/,
unsigned int /*h*/,
unsigned int /*channels*/)
{
BLI_assert_unreachable();
return nullptr;
}
bool IMB_saveiff(struct ImBuf * /*ibuf*/, const char * /*filepath*/, int /*flags*/)
{
BLI_assert_unreachable();
return false;
}
/** \} */
}

View File

@ -755,7 +755,8 @@ inline size_t to_bytesize(eGPUTextureFormat tex_format, eGPUDataFormat data_form
* Standard component len calculation does not apply, as the texture formats contain multiple
* channels, but associated data format contains several compacted components. */
if ((tex_format == GPU_R11F_G11F_B10F && data_format == GPU_DATA_10_11_11_REV) ||
(tex_format == GPU_RGB10_A2 && data_format == GPU_DATA_2_10_10_10_REV))
((tex_format == GPU_RGB10_A2 || tex_format == GPU_RGB10_A2UI) &&
data_format == GPU_DATA_2_10_10_10_REV))
{
return 4;
}

View File

@ -3113,6 +3113,14 @@ std::string MSLGeneratorInterface::generate_msl_fragment_input_population()
<< this->vertex_output_varyings[0].name << ";" << std::endl;
}
/* Assign default gl_FragDepth.
* If gl_FragDepth is used, it should default to the original depth value. Resolves #107159 where
* overlay_wireframe_frag may not write to gl_FragDepth. */
if (this->uses_gl_FragDepth) {
out << "\t" << shader_stage_inst_name << ".gl_FragDepth = " << shader_stage_inst_name
<< ".gl_FragCoord.z;" << std::endl;
}
/* NOTE: We will only assign to the intersection of the vertex output and fragment input.
* Fragment input represents varying variables which are declared (but are not necessarily
* used). The Vertex out defines the set which is passed into the fragment shader, which

View File

@ -484,6 +484,7 @@ inline std::string tex_data_format_to_msl_type_str(eGPUDataFormat type)
case GPU_DATA_UINT_24_8:
return "uint"; /* Problematic type - but will match alignment. */
case GPU_DATA_10_11_11_REV:
case GPU_DATA_2_10_10_10_REV:
return "float"; /* Problematic type - each component will be read as a float. */
default:
BLI_assert(false);
@ -509,6 +510,7 @@ inline std::string tex_data_format_to_msl_texture_template_type(eGPUDataFormat t
case GPU_DATA_UINT_24_8:
return "uint"; /* Problematic type. */
case GPU_DATA_10_11_11_REV:
case GPU_DATA_2_10_10_10_REV:
return "float"; /* Problematic type. */
default:
BLI_assert(false);

Some files were not shown because too many files have changed in this diff Show More