Mesh: Replace auto smooth with node group #108014

Merged
Hans Goudey merged 149 commits from HooglyBoogly/blender:refactor-mesh-corner-normals-lazy into main 2023-10-20 16:54:20 +02:00
544 changed files with 13398 additions and 11345 deletions
Showing only changes of commit 93d81777a8 - 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

@ -1,5 +1,10 @@
# SPDX-License-Identifier: GPL-2.0-or-later
if(CMAKE_COMPILER_IS_GNUCC)
# NOTE: Resolved up-stream, quiet noisy compiler warnings for now.
add_cxx_flag("-Wno-uninitialized")
endif()
set(INC
include
)

View File

@ -2,6 +2,8 @@
#include "config_mac.h"
#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
#include "config_freebsd.h"
#elif defined(__NetBSD__)
#include "config_netbsd.h"
#elif defined(__OpenBSD__)
#include "config_openbsd.h"
#elif defined(__MINGW32__)

192
extern/glog/src/config_netbsd.h vendored Normal file
View File

@ -0,0 +1,192 @@
/* define if glog doesn't use RTTI */
/* #undef DISABLE_RTTI */
/* Namespace for Google classes */
#define GOOGLE_NAMESPACE google
/* Define if you have the `dladdr' function */
/* #undef HAVE_DLADDR */
/* Define if you have the `snprintf' function */
#define HAVE_SNPRINTF
/* Define to 1 if you have the <dlfcn.h> header file. */
#define HAVE_DLFCN_H
/* Define to 1 if you have the <execinfo.h> header file. */
/* #undef HAVE_EXECINFO_H */
/* Define if you have the `fcntl' function */
#define HAVE_FCNTL
/* Define to 1 if you have the <glob.h> header file. */
#define HAVE_GLOB_H
/* Define to 1 if you have the <inttypes.h> header file. */
#define HAVE_INTTYPES_H 1
/* Define to 1 if you have the `pthread' library (-lpthread). */
#define HAVE_LIBPTHREAD
/* Define to 1 if you have the <libunwind.h> header file. */
/* #undef HAVE_LIBUNWIND_H */
/* define if you have google gflags library */
#define HAVE_LIB_GFLAGS
/* define if you have google gmock library */
/* #undef HAVE_LIB_GMOCK */
/* define if you have google gtest library */
/* #undef HAVE_LIB_GTEST */
/* define if you have libunwind */
/* #undef HAVE_LIB_UNWIND */
/* Define to 1 if you have the <memory.h> header file. */
#define HAVE_MEMORY_H
/* define to disable multithreading support. */
/* #undef NO_THREADS */
/* define if the compiler implements namespaces */
#define HAVE_NAMESPACES
/* Define if you have the 'pread' function */
#define HAVE_PREAD
/* Define if you have POSIX threads libraries and header files. */
#define HAVE_PTHREAD
/* Define to 1 if you have the <pwd.h> header file. */
#define HAVE_PWD_H
/* Define if you have the 'pwrite' function */
#define HAVE_PWRITE
/* define if the compiler implements pthread_rwlock_* */
#define HAVE_RWLOCK 1
/* Define if you have the 'sigaction' function */
#define HAVE_SIGACTION
/* Define if you have the `sigaltstack' function */
#define HAVE_SIGALTSTACK 1
/* Define to 1 if you have the <stdint.h> header file. */
#define HAVE_STDINT_H 1
/* Define to 1 if you have the <stdlib.h> header file. */
#define HAVE_STDLIB_H
/* Define to 1 if you have the <strings.h> header file. */
#define HAVE_STRINGS_H
/* Define to 1 if you have the <string.h> header file. */
#define HAVE_STRING_H
/* Define to 1 if you have the <syscall.h> header file. */
/* #undef HAVE_SYSCALL_H */
/* Define to 1 if you have the <syslog.h> header file. */
#define HAVE_SYSLOG_H
/* Define to 1 if you have the <sys/stat.h> header file. */
#define HAVE_SYS_STAT_H
/* Define to 1 if you have the <sys/syscall.h> header file. */
#define HAVE_SYS_SYSCALL_H
/* Define to 1 if you have the <sys/time.h> header file. */
#define HAVE_SYS_TIME_H
/* Define to 1 if you have the <sys/types.h> header file. */
#define HAVE_SYS_TYPES_H 1
/* Define to 1 if you have the <sys/ucontext.h> header file. */
#define HAVE_SYS_UCONTEXT_H
/* Define to 1 if you have the <sys/utsname.h> header file. */
#define HAVE_SYS_UTSNAME_H
/* Define to 1 if you have the <ucontext.h> header file. */
#define HAVE_UCONTEXT_H
/* Define to 1 if you have the <unistd.h> header file. */
#define HAVE_UNISTD_H 1
/* Define to 1 if you have the <unwind.h> header file. */
#define HAVE_UNWIND_H 1
/* define if the compiler supports using expression for operator */
#define HAVE_USING_OPERATOR
/* define if your compiler has __attribute__ */
#define HAVE___ATTRIBUTE__
/* define if your compiler has __builtin_expect */
#define HAVE___BUILTIN_EXPECT 1
/* define if your compiler has __sync_val_compare_and_swap */
#define HAVE___SYNC_VAL_COMPARE_AND_SWAP
/* Define to the sub-directory in which libtool stores uninstalled libraries.
*/
/* #undef LT_OBJDIR */
/* Name of package */
/* #undef PACKAGE */
/* Define to the address where bug reports for this package should be sent. */
/* #undef PACKAGE_BUGREPORT */
/* Define to the full name of this package. */
/* #undef PACKAGE_NAME */
/* Define to the full name and version of this package. */
/* #undef PACKAGE_STRING */
/* Define to the one symbol short name of this package. */
/* #undef PACKAGE_TARNAME */
/* Define to the home page for this package. */
/* #undef PACKAGE_URL */
/* Define to the version of this package. */
/* #undef PACKAGE_VERSION */
/* How to access the PC from a struct ucontext */
/* #undef PC_FROM_UCONTEXT */
/* Define to necessary symbol if this constant uses a non-standard name on
your system. */
/* #undef PTHREAD_CREATE_JOINABLE */
/* The size of `void *', as computed by sizeof. */
#define SIZEOF_VOID_P 8
/* Define to 1 if you have the ANSI C header files. */
#define STDC_HEADERS 1
/* the namespace where STL code like vector<> is defined */
#define STL_NAMESPACE std
/* location of source code */
#define TEST_SRC_DIR "."
/* Version number of package */
/* #undef VERSION */
/* Stops putting the code inside the Google namespace */
#define _END_GOOGLE_NAMESPACE_ }
/* Puts following code inside the Google namespace */
#define _START_GOOGLE_NAMESPACE_ namespace google {
#define GOOGLE_GLOG_DLL_DECL
/* isn't getting defined by configure script when clang compilers are used
and cuases compilation errors in stactrace/unwind modules */
#ifdef __clang__
# define NO_FRAME_POINTER
#endif

View File

@ -149,7 +149,11 @@ void BlenderSync::sync_light(BL::Object &b_parent,
light->set_is_shadow_catcher(b_ob_info.real_object.is_shadow_catcher());
/* Light group and linking. */
light->set_lightgroup(ustring(b_ob_info.real_object.lightgroup()));
string lightgroup = b_ob_info.real_object.lightgroup();
if (lightgroup.empty()) {
lightgroup = b_parent.lightgroup();
}
light->set_lightgroup(ustring(lightgroup));
light->set_light_set_membership(
BlenderLightLink::get_light_set_membership(PointerRNA_NULL, b_ob_info.real_object));
light->set_shadow_set_membership(

View File

@ -989,6 +989,48 @@ static const bool *find_sharp_face_attribute(BL::Mesh b_mesh)
return nullptr;
}
static const float *find_edge_crease_attribute(BL::Mesh b_mesh)
{
for (BL::Attribute &b_attribute : b_mesh.attributes) {
if (b_attribute.domain() != BL::Attribute::domain_EDGE) {
continue;
}
if (b_attribute.data_type() != BL::Attribute::data_type_FLOAT) {
continue;
}
if (b_attribute.name() != "crease_edge") {
continue;
}
BL::FloatAttribute b_float_attribute{b_attribute};
if (b_float_attribute.data.length() == 0) {
return nullptr;
}
return static_cast<const float *>(b_float_attribute.data[0].ptr.data);
}
return nullptr;
}
static const float *find_vert_crease_attribute(BL::Mesh b_mesh)
{
for (BL::Attribute &b_attribute : b_mesh.attributes) {
if (b_attribute.domain() != BL::Attribute::domain_POINT) {
continue;
}
if (b_attribute.data_type() != BL::Attribute::data_type_FLOAT) {
continue;
}
if (b_attribute.name() != "crease_vert") {
continue;
}
BL::FloatAttribute b_float_attribute{b_attribute};
if (b_float_attribute.data.length() == 0) {
return nullptr;
}
return static_cast<const float *>(b_float_attribute.data[0].ptr.data);
}
return nullptr;
}
static void create_mesh(Scene *scene,
Mesh *mesh,
BL::Mesh &b_mesh,
@ -1227,11 +1269,12 @@ static void create_subd_mesh(Scene *scene,
create_mesh(scene, mesh, b_mesh, used_shaders, need_motion, motion_scale, true, subdivide_uvs);
const int verts_num = b_mesh.vertices.length();
const int edges_num = b_mesh.edges.length();
if (edges_num != 0 && b_mesh.edge_creases.length() > 0) {
const float *creases = static_cast<const float *>(b_mesh.edge_creases[0].data[0].ptr.data);
const float *creases = find_edge_crease_attribute(b_mesh);
if (edges_num != 0 && creases != nullptr) {
size_t num_creases = 0;
for (int i = 0; i < edges_num; i++) {
if (creases[i] != 0.0f) {
@ -1251,11 +1294,10 @@ static void create_subd_mesh(Scene *scene,
}
}
for (BL::MeshVertexCreaseLayer &layer : b_mesh.vertex_creases) {
const float *creases = static_cast<const float *>(layer.data[0].ptr.data);
for (int i = 0; i < layer.data.length(); ++i) {
if (creases[i] != 0.0f) {
mesh->add_vertex_crease(i, creases[i]);
if (const float *vert_creases = find_vert_crease_attribute(b_mesh)) {
for (int i = 0; i < verts_num; i++) {
if (vert_creases[i] != 0.0f) {
mesh->add_vertex_crease(i, vert_creases[i]);
}
}
}

View File

@ -350,7 +350,11 @@ Object *BlenderSync::sync_object(BL::Depsgraph &b_depsgraph,
}
/* Light group and linking. */
object->set_lightgroup(ustring(b_ob.lightgroup()));
string lightgroup = b_ob.lightgroup();
if (lightgroup.empty()) {
lightgroup = b_parent.lightgroup();
}
object->set_lightgroup(ustring(lightgroup));
object->set_light_set_membership(BlenderLightLink::get_light_set_membership(b_parent, b_ob));
object->set_receiver_light_set(BlenderLightLink::get_receiver_light_set(b_parent, b_ob));

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_use_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

@ -104,7 +104,7 @@ ccl_device int bsdf_ashikhmin_velvet_sample(ccl_private const ShaderClosure *sc,
float cosHI = fabsf(dot(wi, H));
float cosNH = dot(N, H);
if (!(fabsf(cosNI) > 1e-5f && fabsf(cosNH) < 1.0f - 1e-5f && cosHI > 1e-5f)) {
if (!(cosNI > 1e-5f && fabsf(cosNH) < 1.0f - 1e-5f && cosHI > 1e-5f)) {
*pdf = 0.0f;
*eval = zero_spectrum();
return LABEL_NONE;

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)) :
(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

@ -79,6 +79,7 @@ struct CCLShadowContext
#endif
IntegratorShadowState isect_s;
float throughput;
float max_t;
bool opaque_hit;
numhit_t max_hits;
numhit_t num_hits;
@ -314,7 +315,7 @@ ccl_device_forceinline void kernel_embree_filter_occluded_shadow_all_func_impl(
/* Current implementation in Cycles assumes only single-ray intersection queries. */
assert(args->N == 1);
RTCRay *ray = (RTCRay *)args->ray;
const RTCRay *ray = (RTCRay *)args->ray;
RTCHit *hit = (RTCHit *)args->hit;
#if EMBREE_MAJOR_VERSION >= 4
CCLShadowContext *ctx = (CCLShadowContext *)(args->context);
@ -367,18 +368,32 @@ ccl_device_forceinline void kernel_embree_filter_occluded_shadow_all_func_impl(
}
}
/* Test if we need to record this transparent intersection. */
numhit_t isect_index = ctx->num_recorded_hits;
/* Always increase the number of recorded hits, even beyond the maximum,
* so that we can detect this and trace another ray if needed.
* More details about the related logic can be found in implementation of
* "shadow_intersections_has_remaining" and "integrate_transparent_shadow"
* functions. */
++ctx->num_recorded_hits;
/* This tells Embree to continue tracing. */
*args->valid = 0;
const numhit_t max_record_hits = min(ctx->max_hits, numhit_t(INTEGRATOR_SHADOW_ISECT_SIZE));
if (ctx->num_recorded_hits < max_record_hits) {
/* If maximum number of hits was reached, replace the intersection with the
* highest distance. We want to find the N closest intersections. */
const numhit_t num_recorded_hits = min(ctx->num_recorded_hits, max_record_hits);
numhit_t isect_index = num_recorded_hits;
if (num_recorded_hits + 1 >= max_record_hits) {
/* If the maximum number of hits was reached, replace the furthest intersection
* with a closer one so we get the N closest intersections. */
if (isect_index >= max_record_hits) {
/* When recording only N closest hits, max_t will always only decrease.
* So let's test if we are already not meeting criteria and can skip max_t recalculation. */
if (current_isect.t >= ctx->max_t) {
return;
}
float max_t = INTEGRATOR_STATE_ARRAY(ctx->isect_s, shadow_isect, 0, t);
numhit_t max_recorded_hit = numhit_t(0);
for (numhit_t i = numhit_t(1); i < num_recorded_hits; ++i) {
for (numhit_t i = numhit_t(1); i < max_record_hits; ++i) {
const float isect_t = INTEGRATOR_STATE_ARRAY(ctx->isect_s, shadow_isect, i, t);
if (isect_t > max_t) {
max_recorded_hit = i;
@ -386,25 +401,20 @@ ccl_device_forceinline void kernel_embree_filter_occluded_shadow_all_func_impl(
}
}
if (num_recorded_hits >= max_record_hits) {
isect_index = max_recorded_hit;
}
/* Limit the ray distance and stop counting hits beyond this. */
ray->tfar = max(current_isect.t, max_t);
/* Limit the ray distance and avoid processing hits beyond this. */
ctx->max_t = max_t;
/* If it's further away than max_t, we don't record this transparent intersection. */
if (current_isect.t >= max_t) {
return;
}
}
integrator_state_write_shadow_isect(ctx->isect_s, &current_isect, isect_index);
}
/* Always increase the number of recorded hits, even beyond the maximum,
* so that we can detect this and trace another ray if needed. */
++ctx->num_recorded_hits;
/* This tells Embree to continue tracing. */
*args->valid = 0;
}
ccl_device_forceinline void kernel_embree_filter_occluded_local_func_impl(
const RTCFilterFunctionNArguments *args)
{

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,33 +20,58 @@ CCL_NAMESPACE_BEGIN
* them separately. */
ccl_device_inline void bsdf_eval_init(ccl_private BsdfEval *eval,
const ClosureType closure_type,
ccl_private 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_accum(ccl_private BsdfEval *eval,
const ClosureType closure_type,
Spectrum value)
ccl_device_inline void bsdf_eval_init(ccl_private BsdfEval *eval, Spectrum value)
{
if (CLOSURE_IS_BSDF_DIFFUSE(closure_type)) {
eval->diffuse += value;
}
else if (CLOSURE_IS_BSDF_GLOSSY(closure_type)) {
eval->glossy += value;
eval->diffuse = zero_spectrum();
eval->glossy = zero_spectrum();
eval->sum = value;
}
ccl_device_inline void bsdf_eval_accum(ccl_private BsdfEval *eval,
ccl_private const ShaderClosure *sc,
const float3 wo,
Spectrum value)
{
if (CLOSURE_IS_BSDF_DIFFUSE(sc->type)) {
eval->diffuse += value;
}
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;
}

View File

@ -155,12 +155,15 @@ ccl_device_inline void shader_setup_from_sample(KernelGlobals kg,
sd->Ng = Ng;
sd->wi = I;
sd->shader = shader;
if (prim != PRIM_NONE)
sd->type = PRIMITIVE_TRIANGLE;
else if (lamp != LAMP_NONE)
if (lamp != LAMP_NONE) {
sd->type = PRIMITIVE_LAMP;
else
}
else if (prim != PRIM_NONE) {
sd->type = PRIMITIVE_TRIANGLE;
}
else {
sd->type = PRIMITIVE_NONE;
}
/* primitive */
sd->object = object;

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

@ -316,7 +316,7 @@ ccl_device void light_tree_node_importance(KernelGlobals kg,
return;
}
point_to_centroid = -bcone.axis;
cos_theta_u = fast_cosf(bcone.theta_o);
cos_theta_u = fast_cosf(bcone.theta_o + bcone.theta_e);
distance = 1.0f;
}
else {

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(use_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, use_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, "use_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, use_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

@ -162,7 +162,7 @@ extern void GHOST_GetAllDisplayDimensions(GHOST_SystemHandle systemhandle,
* \param height: The height the window.
* \param state: The state of the window when opened.
* \param is_dialog: Stay on top of parent window, no icon in taskbar, can't be minimized.
* \param glSettings: Misc OpenGL options.
* \param gpuSettings: Misc GPU options.
* \return A handle to the new window ( == NULL if creation failed).
*/
extern GHOST_WindowHandle GHOST_CreateWindow(GHOST_SystemHandle systemhandle,
@ -174,17 +174,17 @@ extern GHOST_WindowHandle GHOST_CreateWindow(GHOST_SystemHandle systemhandle,
uint32_t height,
GHOST_TWindowState state,
bool is_dialog,
GHOST_GLSettings glSettings);
GHOST_GPUSettings gpuSettings);
/**
* Create a new off-screen context.
* Never explicitly delete the context, use #disposeContext() instead.
* \param systemhandle: The handle to the system.
* \param glSettings: Misc OpenGL options.
* \param gpuSettings: Misc GPU options.
* \return A handle to the new context ( == NULL if creation failed).
*/
extern GHOST_ContextHandle GHOST_CreateOpenGLContext(GHOST_SystemHandle systemhandle,
GHOST_GLSettings glSettings);
extern GHOST_ContextHandle GHOST_CreateGPUContext(GHOST_SystemHandle systemhandle,
GHOST_GPUSettings gpuSettings);
/**
* Dispose of a context.
@ -192,7 +192,7 @@ extern GHOST_ContextHandle GHOST_CreateOpenGLContext(GHOST_SystemHandle systemha
* \param contexthandle: Handle to the context to be disposed.
* \return Indication of success.
*/
extern GHOST_TSuccess GHOST_DisposeOpenGLContext(GHOST_SystemHandle systemhandle,
extern GHOST_TSuccess GHOST_DisposeGPUContext(GHOST_SystemHandle systemhandle,
GHOST_ContextHandle contexthandle);
/**
@ -730,24 +730,24 @@ extern GHOST_TSuccess GHOST_InvalidateWindow(GHOST_WindowHandle windowhandle);
* \param contexthandle: The handle to the context.
* \return A success indicator.
*/
extern GHOST_TSuccess GHOST_ActivateOpenGLContext(GHOST_ContextHandle contexthandle);
extern GHOST_TSuccess GHOST_ActivateGPUContext(GHOST_ContextHandle contexthandle);
/**
* Release the drawing context bound to this thread.
* \param contexthandle: The handle to the context.
* \return A success indicator.
*/
extern GHOST_TSuccess GHOST_ReleaseOpenGLContext(GHOST_ContextHandle contexthandle);
extern GHOST_TSuccess GHOST_ReleaseGPUContext(GHOST_ContextHandle contexthandle);
/**
* Get the OpenGL frame-buffer handle that serves as a default frame-buffer.
* Get the GPU frame-buffer handle that serves as a default frame-buffer.
*/
extern unsigned int GHOST_GetContextDefaultOpenGLFramebuffer(GHOST_ContextHandle contexthandle);
extern unsigned int GHOST_GetContextDefaultGPUFramebuffer(GHOST_ContextHandle contexthandle);
/**
* Get the OpenGL frame-buffer handle that serves as a default frame-buffer.
* Get the GPU frame-buffer handle that serves as a default frame-buffer.
*/
extern unsigned int GHOST_GetDefaultOpenGLFramebuffer(GHOST_WindowHandle windowhandle);
extern unsigned int GHOST_GetDefaultGPUFramebuffer(GHOST_WindowHandle windowhandle);
/**
* Use multi-touch gestures if supported.
@ -1072,7 +1072,7 @@ int GHOST_XrSessionIsRunning(const GHOST_XrContextHandle xr_context);
/**
* Check if \a xr_context has a session that requires an upside-down frame-buffer (compared to
* OpenGL). If true, the render result should be flipped vertically for correct output.
* GPU). If true, the render result should be flipped vertically for correct output.
* \note Only to be called after session start, may otherwise result in a false negative.
*/
int GHOST_XrSessionNeedsUpsideDownDrawing(const GHOST_XrContextHandle xr_context);

View File

@ -230,7 +230,7 @@ class GHOST_ISystem {
* \param width: The width the window.
* \param height: The height the window.
* \param state: The state of the window when opened.
* \param glSettings: Misc OpenGL settings.
* \param gpuSettings: Misc GPU settings.
* \param exclusive: Use to show the window on top and ignore others (used full-screen).
* \param is_dialog: Stay on top of parent window, no icon in taskbar, can't be minimized.
* \param parentWindow: Parent (embedder) window
@ -242,7 +242,7 @@ class GHOST_ISystem {
uint32_t width,
uint32_t height,
GHOST_TWindowState state,
GHOST_GLSettings glSettings,
GHOST_GPUSettings gpuSettings,
const bool exclusive = false,
const bool is_dialog = false,
const GHOST_IWindow *parentWindow = NULL) = 0;
@ -259,7 +259,7 @@ class GHOST_ISystem {
* Never explicitly delete the context, use #disposeContext() instead.
* \return The new context (or 0 if creation failed).
*/
virtual GHOST_IContext *createOffscreenContext(GHOST_GLSettings glSettings) = 0;
virtual GHOST_IContext *createOffscreenContext(GHOST_GPUSettings gpuSettings) = 0;
/**
* Dispose of a context.

View File

@ -64,9 +64,9 @@ typedef struct {
} GHOST_CursorBitmapRef;
typedef enum {
GHOST_glStereoVisual = (1 << 0),
GHOST_glDebugContext = (1 << 1),
} GHOST_GLFlags;
GHOST_gpuStereoVisual = (1 << 0),
GHOST_gpuDebugContext = (1 << 1),
} GHOST_GPUFlags;
typedef enum GHOST_DialogOptions {
GHOST_DialogWarning = (1 << 0),
@ -170,14 +170,15 @@ typedef enum {
GHOST_kModifierKeyNum
} GHOST_TModifierKey;
/**
* \note these values are stored in #wmWindow::windowstate,
* don't change, only add new values.
*/
typedef enum {
GHOST_kWindowStateNormal = 0,
GHOST_kWindowStateMaximized,
GHOST_kWindowStateMinimized,
GHOST_kWindowStateFullScreen,
GHOST_kWindowStateEmbedded,
// GHOST_kWindowStateModified,
// GHOST_kWindowStateUnModified,
GHOST_kWindowStateMaximized = 1,
GHOST_kWindowStateMinimized = 2,
GHOST_kWindowStateFullScreen = 3,
} GHOST_TWindowState;
typedef enum {
@ -680,7 +681,7 @@ typedef struct {
typedef struct {
int flags;
GHOST_TDrawingContextType context_type;
} GHOST_GLSettings;
} GHOST_GPUSettings;
typedef enum {
/** Axis that cursor grab will wrap. */

View File

@ -135,15 +135,15 @@ void GHOST_GetAllDisplayDimensions(GHOST_SystemHandle systemhandle,
system->getAllDisplayDimensions(*width, *height);
}
GHOST_ContextHandle GHOST_CreateOpenGLContext(GHOST_SystemHandle systemhandle,
GHOST_GLSettings glSettings)
GHOST_ContextHandle GHOST_CreateGPUContext(GHOST_SystemHandle systemhandle,
GHOST_GPUSettings gpuSettings)
{
GHOST_ISystem *system = (GHOST_ISystem *)systemhandle;
return (GHOST_ContextHandle)system->createOffscreenContext(glSettings);
return (GHOST_ContextHandle)system->createOffscreenContext(gpuSettings);
}
GHOST_TSuccess GHOST_DisposeOpenGLContext(GHOST_SystemHandle systemhandle,
GHOST_TSuccess GHOST_DisposeGPUContext(GHOST_SystemHandle systemhandle,
GHOST_ContextHandle contexthandle)
{
GHOST_ISystem *system = (GHOST_ISystem *)systemhandle;
@ -161,7 +161,7 @@ GHOST_WindowHandle GHOST_CreateWindow(GHOST_SystemHandle systemhandle,
uint32_t height,
GHOST_TWindowState state,
bool is_dialog,
GHOST_GLSettings glSettings)
GHOST_GPUSettings gpuSettings)
{
GHOST_ISystem *system = (GHOST_ISystem *)systemhandle;
@ -171,7 +171,7 @@ GHOST_WindowHandle GHOST_CreateWindow(GHOST_SystemHandle systemhandle,
width,
height,
state,
glSettings,
gpuSettings,
false,
is_dialog,
(GHOST_IWindow *)parent_windowhandle);
@ -716,7 +716,7 @@ GHOST_TSuccess GHOST_ActivateWindowDrawingContext(GHOST_WindowHandle windowhandl
return window->activateDrawingContext();
}
GHOST_TSuccess GHOST_ActivateOpenGLContext(GHOST_ContextHandle contexthandle)
GHOST_TSuccess GHOST_ActivateGPUContext(GHOST_ContextHandle contexthandle)
{
GHOST_IContext *context = (GHOST_IContext *)contexthandle;
if (context) {
@ -726,21 +726,21 @@ GHOST_TSuccess GHOST_ActivateOpenGLContext(GHOST_ContextHandle contexthandle)
return GHOST_kFailure;
}
GHOST_TSuccess GHOST_ReleaseOpenGLContext(GHOST_ContextHandle contexthandle)
GHOST_TSuccess GHOST_ReleaseGPUContext(GHOST_ContextHandle contexthandle)
{
GHOST_IContext *context = (GHOST_IContext *)contexthandle;
return context->releaseDrawingContext();
}
uint GHOST_GetContextDefaultOpenGLFramebuffer(GHOST_ContextHandle contexthandle)
uint GHOST_GetContextDefaultGPUFramebuffer(GHOST_ContextHandle contexthandle)
{
GHOST_IContext *context = (GHOST_IContext *)contexthandle;
return context->getDefaultFramebuffer();
}
uint GHOST_GetDefaultOpenGLFramebuffer(GHOST_WindowHandle windowhandle)
uint GHOST_GetDefaultGPUFramebuffer(GHOST_WindowHandle windowhandle)
{
GHOST_IWindow *window = (GHOST_IWindow *)windowhandle;

View File

@ -215,6 +215,7 @@ class GHOST_DeviceVK {
device_features.geometryShader = VK_TRUE;
device_features.dualSrcBlend = VK_TRUE;
device_features.logicOp = VK_TRUE;
device_features.imageCubeArray = VK_TRUE;
#endif
VkDeviceCreateInfo device_create_info = {};
@ -309,7 +310,7 @@ static GHOST_TSuccess ensure_vulkan_device(VkInstance vk_instance,
#if STRICT_REQUIREMENTS
if (!device_vk.features.geometryShader || !device_vk.features.dualSrcBlend ||
!device_vk.features.logicOp)
!device_vk.features.logicOp || !device_vk.features.imageCubeArray)
{
continue;
}

View File

@ -397,12 +397,12 @@ GHOST_TSuccess GHOST_System::createFullScreenWindow(GHOST_Window **window,
const GHOST_DisplaySetting &settings,
const bool stereoVisual)
{
GHOST_GLSettings glSettings = {0};
GHOST_GPUSettings gpuSettings = {0};
if (stereoVisual) {
glSettings.flags |= GHOST_glStereoVisual;
gpuSettings.flags |= GHOST_gpuStereoVisual;
}
glSettings.context_type = GHOST_kDrawingContextTypeOpenGL;
gpuSettings.context_type = GHOST_kDrawingContextTypeOpenGL;
/* NOTE: don't use #getCurrentDisplaySetting() because on X11 we may
* be zoomed in and the desktop may be bigger than the viewport. */
GHOST_ASSERT(m_displayManager,
@ -414,7 +414,7 @@ GHOST_TSuccess GHOST_System::createFullScreenWindow(GHOST_Window **window,
settings.xPixels,
settings.yPixels,
GHOST_kWindowStateNormal,
glSettings,
gpuSettings,
true /* exclusive */);
return (*window == nullptr) ? GHOST_kFailure : GHOST_kSuccess;
}

View File

@ -101,7 +101,7 @@ class GHOST_System : public GHOST_ISystem {
* Never explicitly delete the context, use #disposeContext() instead.
* \return The new context (or 0 if creation failed).
*/
virtual GHOST_IContext *createOffscreenContext(GHOST_GLSettings glSettings) = 0;
virtual GHOST_IContext *createOffscreenContext(GHOST_GPUSettings gpuSettings) = 0;
/**
* Returns whether a window is valid.

View File

@ -77,7 +77,7 @@ class GHOST_SystemCocoa : public GHOST_System {
* \param width: The width the window.
* \param height: The height the window.
* \param state: The state of the window when opened.
* \param glSettings: Misc OpenGL settings.
* \param gpuSettings: Misc GPU settings.
* \param exclusive: Use to show the window on top and ignore others (used full-screen).
* \param parentWindow: Parent (embedder) window.
* \return The new window (or 0 if creation failed).
@ -88,7 +88,7 @@ class GHOST_SystemCocoa : public GHOST_System {
uint32_t width,
uint32_t height,
GHOST_TWindowState state,
GHOST_GLSettings glSettings,
GHOST_GPUSettings gpuSettings,
const bool exclusive = false,
const bool is_dialog = false,
const GHOST_IWindow *parentWindow = NULL);
@ -98,7 +98,7 @@ class GHOST_SystemCocoa : public GHOST_System {
* Never explicitly delete the context, use #disposeContext() instead.
* \return The new context (or 0 if creation failed).
*/
GHOST_IContext *createOffscreenContext(GHOST_GLSettings glSettings);
GHOST_IContext *createOffscreenContext(GHOST_GPUSettings gpuSettings);
/**
* Dispose of a context.

View File

@ -696,7 +696,7 @@ GHOST_IWindow *GHOST_SystemCocoa::createWindow(const char *title,
uint32_t width,
uint32_t height,
GHOST_TWindowState state,
GHOST_GLSettings glSettings,
GHOST_GPUSettings gpuSettings,
const bool exclusive,
const bool is_dialog,
const GHOST_IWindow *parentWindow)
@ -725,9 +725,9 @@ GHOST_IWindow *GHOST_SystemCocoa::createWindow(const char *title,
width,
height,
state,
glSettings.context_type,
glSettings.flags & GHOST_glStereoVisual,
glSettings.flags & GHOST_glDebugContext,
gpuSettings.context_type,
gpuSettings.flags & GHOST_gpuStereoVisual,
gpuSettings.flags & GHOST_gpuDebugContext,
is_dialog,
(GHOST_WindowCocoa *)parentWindow);
@ -755,11 +755,11 @@ GHOST_IWindow *GHOST_SystemCocoa::createWindow(const char *title,
* Never explicitly delete the context, use #disposeContext() instead.
* \return The new context (or 0 if creation failed).
*/
GHOST_IContext *GHOST_SystemCocoa::createOffscreenContext(GHOST_GLSettings glSettings)
GHOST_IContext *GHOST_SystemCocoa::createOffscreenContext(GHOST_GPUSettings gpuSettings)
{
#ifdef WITH_VULKAN_BACKEND
if (glSettings.context_type == GHOST_kDrawingContextTypeVulkan) {
const bool debug_context = (glSettings.flags & GHOST_glDebugContext) != 0;
if (gpuSettings.context_type == GHOST_kDrawingContextTypeVulkan) {
const bool debug_context = (gpuSettings.flags & GHOST_gpuDebugContext) != 0;
GHOST_Context *context = new GHOST_ContextVK(false, NULL, 1, 2, debug_context);
if (!context->initializeDrawingContext()) {
delete context;
@ -769,7 +769,7 @@ GHOST_IContext *GHOST_SystemCocoa::createOffscreenContext(GHOST_GLSettings glSet
}
#endif
GHOST_Context *context = new GHOST_ContextCGL(false, NULL, NULL, NULL, glSettings.context_type);
GHOST_Context *context = new GHOST_ContextCGL(false, NULL, NULL, NULL, gpuSettings.context_type);
if (context->initializeDrawingContext())
return context;
else

View File

@ -79,7 +79,7 @@ class GHOST_SystemHeadless : public GHOST_System {
void getAllDisplayDimensions(uint32_t & /*width*/, uint32_t & /*height*/) const override
{ /* nop */
}
GHOST_IContext *createOffscreenContext(GHOST_GLSettings /*glSettings*/) override
GHOST_IContext *createOffscreenContext(GHOST_GPUSettings /*gpuSettings*/) override
{
#ifdef __linux__
GHOST_Context *context;
@ -150,7 +150,7 @@ class GHOST_SystemHeadless : public GHOST_System {
uint32_t width,
uint32_t height,
GHOST_TWindowState state,
GHOST_GLSettings glSettings,
GHOST_GPUSettings gpuSettings,
const bool /*exclusive*/,
const bool /*is_dialog*/,
const GHOST_IWindow *parentWindow) override
@ -162,8 +162,8 @@ class GHOST_SystemHeadless : public GHOST_System {
height,
state,
parentWindow,
glSettings.context_type,
((glSettings.flags & GHOST_glStereoVisual) != 0));
gpuSettings.context_type,
((gpuSettings.flags & GHOST_gpuStereoVisual) != 0));
}
GHOST_IWindow *getWindowUnderCursor(int32_t /*x*/, int32_t /*y*/) override

View File

@ -42,7 +42,7 @@ GHOST_IWindow *GHOST_SystemSDL::createWindow(const char *title,
uint32_t width,
uint32_t height,
GHOST_TWindowState state,
GHOST_GLSettings glSettings,
GHOST_GPUSettings gpuSettings,
const bool exclusive,
const bool /* is_dialog */,
const GHOST_IWindow *parentWindow)
@ -56,8 +56,8 @@ GHOST_IWindow *GHOST_SystemSDL::createWindow(const char *title,
width,
height,
state,
glSettings.context_type,
((glSettings.flags & GHOST_glStereoVisual) != 0),
gpuSettings.context_type,
((gpuSettings.flags & GHOST_gpuStereoVisual) != 0),
exclusive,
parentWindow);
@ -125,7 +125,7 @@ uint8_t GHOST_SystemSDL::getNumDisplays() const
return SDL_GetNumVideoDisplays();
}
GHOST_IContext *GHOST_SystemSDL::createOffscreenContext(GHOST_GLSettings /*glSettings*/)
GHOST_IContext *GHOST_SystemSDL::createOffscreenContext(GHOST_GPUSettings /*gpuSettings*/)
{
GHOST_Context *context = new GHOST_ContextSDL(false,
nullptr,

View File

@ -60,7 +60,7 @@ class GHOST_SystemSDL : public GHOST_System {
void getMainDisplayDimensions(uint32_t &width, uint32_t &height) const override;
GHOST_IContext *createOffscreenContext(GHOST_GLSettings glSettings) override;
GHOST_IContext *createOffscreenContext(GHOST_GPUSettings gpuSettings) override;
GHOST_TSuccess disposeContext(GHOST_IContext *context) override;
@ -73,7 +73,7 @@ class GHOST_SystemSDL : public GHOST_System {
uint32_t width,
uint32_t height,
GHOST_TWindowState state,
GHOST_GLSettings glSettings,
GHOST_GPUSettings gpuSettings,
const bool exclusive = false,
const bool is_dialog = false,
const GHOST_IWindow *parentWindow = nullptr) override;

View File

@ -6279,7 +6279,7 @@ static GHOST_Context *createOffscreenContext_impl(GHOST_SystemWayland *system,
return nullptr;
}
GHOST_IContext *GHOST_SystemWayland::createOffscreenContext(GHOST_GLSettings glSettings)
GHOST_IContext *GHOST_SystemWayland::createOffscreenContext(GHOST_GPUSettings gpuSettings)
{
#ifdef USE_EVENT_BACKGROUND_THREAD
std::lock_guard lock_server_guard{*server_mutex};
@ -6289,9 +6289,9 @@ GHOST_IContext *GHOST_SystemWayland::createOffscreenContext(GHOST_GLSettings glS
wl_surface *wl_surface = wl_compositor_create_surface(wl_compositor());
#ifdef WITH_VULKAN_BACKEND
const bool debug_context = (glSettings.flags & GHOST_glDebugContext) != 0;
const bool debug_context = (gpuSettings.flags & GHOST_gpuDebugContext) != 0;
if (glSettings.context_type == GHOST_kDrawingContextTypeVulkan) {
if (gpuSettings.context_type == GHOST_kDrawingContextTypeVulkan) {
GHOST_Context *context = new GHOST_ContextVK(false,
GHOST_kVulkanPlatformWayland,
0,
@ -6310,7 +6310,7 @@ GHOST_IContext *GHOST_SystemWayland::createOffscreenContext(GHOST_GLSettings glS
return context;
}
#else
(void)glSettings;
(void)gpuSettings;
#endif
wl_egl_window *egl_window = wl_surface ? wl_egl_window_create(wl_surface, 1, 1) : nullptr;
@ -6359,7 +6359,7 @@ GHOST_IWindow *GHOST_SystemWayland::createWindow(const char *title,
const uint32_t width,
const uint32_t height,
const GHOST_TWindowState state,
const GHOST_GLSettings glSettings,
const GHOST_GPUSettings gpuSettings,
const bool exclusive,
const bool is_dialog,
const GHOST_IWindow *parentWindow)
@ -6374,9 +6374,9 @@ GHOST_IWindow *GHOST_SystemWayland::createWindow(const char *title,
height,
state,
parentWindow,
glSettings.context_type,
gpuSettings.context_type,
is_dialog,
((glSettings.flags & GHOST_glStereoVisual) != 0),
((gpuSettings.flags & GHOST_gpuStereoVisual) != 0),
exclusive);
if (window) {

View File

@ -157,7 +157,7 @@ class GHOST_SystemWayland : public GHOST_System {
void getAllDisplayDimensions(uint32_t &width, uint32_t &height) const override;
GHOST_IContext *createOffscreenContext(GHOST_GLSettings glSettings) override;
GHOST_IContext *createOffscreenContext(GHOST_GPUSettings gpuSettings) override;
GHOST_TSuccess disposeContext(GHOST_IContext *context) override;
@ -167,7 +167,7 @@ class GHOST_SystemWayland : public GHOST_System {
uint32_t width,
uint32_t height,
GHOST_TWindowState state,
GHOST_GLSettings glSettings,
GHOST_GPUSettings gpuSettings,
const bool exclusive,
const bool is_dialog,
const GHOST_IWindow *parentWindow) override;

View File

@ -224,7 +224,7 @@ GHOST_IWindow *GHOST_SystemWin32::createWindow(const char *title,
uint32_t width,
uint32_t height,
GHOST_TWindowState state,
GHOST_GLSettings glSettings,
GHOST_GPUSettings gpuSettings,
const bool /*exclusive*/,
const bool is_dialog,
const GHOST_IWindow *parentWindow)
@ -237,11 +237,11 @@ GHOST_IWindow *GHOST_SystemWin32::createWindow(const char *title,
width,
height,
state,
glSettings.context_type,
((glSettings.flags & GHOST_glStereoVisual) != 0),
gpuSettings.context_type,
((gpuSettings.flags & GHOST_gpuStereoVisual) != 0),
false,
(GHOST_WindowWin32 *)parentWindow,
((glSettings.flags & GHOST_glDebugContext) != 0),
((gpuSettings.flags & GHOST_gpuDebugContext) != 0),
is_dialog);
if (window->getValid()) {
@ -263,15 +263,15 @@ GHOST_IWindow *GHOST_SystemWin32::createWindow(const char *title,
* Never explicitly delete the window, use #disposeContext() instead.
* \return The new context (or 0 if creation failed).
*/
GHOST_IContext *GHOST_SystemWin32::createOffscreenContext(GHOST_GLSettings glSettings)
GHOST_IContext *GHOST_SystemWin32::createOffscreenContext(GHOST_GPUSettings gpuSettings)
{
const bool debug_context = (glSettings.flags & GHOST_glDebugContext) != 0;
const bool debug_context = (gpuSettings.flags & GHOST_gpuDebugContext) != 0;
GHOST_Context *context = nullptr;
#ifdef WITH_VULKAN_BACKEND
/* Vulkan does not need a window. */
if (glSettings.context_type == GHOST_kDrawingContextTypeVulkan) {
if (gpuSettings.context_type == GHOST_kDrawingContextTypeVulkan) {
context = new GHOST_ContextVK(false, (HWND)0, 1, 2, debug_context);
if (!context->initializeDrawingContext()) {

View File

@ -103,7 +103,7 @@ class GHOST_SystemWin32 : public GHOST_System {
* \param width: The width the window.
* \param height: The height the window.
* \param state: The state of the window when opened.
* \param glSettings: Misc OpenGL settings.
* \param gpuSettings: Misc GPU settings.
* \param exclusive: Use to show the window on top and ignore others (used full-screen).
* \param parentWindow: Parent window.
* \return The new window (or 0 if creation failed).
@ -114,7 +114,7 @@ class GHOST_SystemWin32 : public GHOST_System {
uint32_t width,
uint32_t height,
GHOST_TWindowState state,
GHOST_GLSettings glSettings,
GHOST_GPUSettings gpuSettings,
const bool exclusive = false,
const bool is_dialog = false,
const GHOST_IWindow *parentWindow = 0);
@ -124,7 +124,7 @@ class GHOST_SystemWin32 : public GHOST_System {
* Never explicitly delete the window, use #disposeContext() instead.
* \return The new context (or 0 if creation failed).
*/
GHOST_IContext *createOffscreenContext(GHOST_GLSettings glSettings);
GHOST_IContext *createOffscreenContext(GHOST_GPUSettings gpuSettings);
/**
* Dispose of a context.

View File

@ -304,7 +304,7 @@ GHOST_IWindow *GHOST_SystemX11::createWindow(const char *title,
uint32_t width,
uint32_t height,
GHOST_TWindowState state,
GHOST_GLSettings glSettings,
GHOST_GPUSettings gpuSettings,
const bool exclusive,
const bool is_dialog,
const GHOST_IWindow *parentWindow)
@ -324,11 +324,11 @@ GHOST_IWindow *GHOST_SystemX11::createWindow(const char *title,
height,
state,
(GHOST_WindowX11 *)parentWindow,
glSettings.context_type,
gpuSettings.context_type,
is_dialog,
((glSettings.flags & GHOST_glStereoVisual) != 0),
((gpuSettings.flags & GHOST_gpuStereoVisual) != 0),
exclusive,
(glSettings.flags & GHOST_glDebugContext) != 0);
(gpuSettings.flags & GHOST_gpuDebugContext) != 0);
if (window) {
/* Both are now handle in GHOST_WindowX11.cc
@ -399,7 +399,7 @@ static GHOST_Context *create_glx_context(Display *display,
return nullptr;
}
GHOST_IContext *GHOST_SystemX11::createOffscreenContext(GHOST_GLSettings glSettings)
GHOST_IContext *GHOST_SystemX11::createOffscreenContext(GHOST_GPUSettings gpuSettings)
{
/* During development:
* try 4.x compatibility profile
@ -411,11 +411,11 @@ GHOST_IContext *GHOST_SystemX11::createOffscreenContext(GHOST_GLSettings glSetti
* try 3.3 core profile
* no fall-backs. */
const bool debug_context = (glSettings.flags & GHOST_glDebugContext) != 0;
const bool debug_context = (gpuSettings.flags & GHOST_gpuDebugContext) != 0;
GHOST_Context *context = nullptr;
#ifdef WITH_VULKAN_BACKEND
if (glSettings.context_type == GHOST_kDrawingContextTypeVulkan) {
if (gpuSettings.context_type == GHOST_kDrawingContextTypeVulkan) {
context = new GHOST_ContextVK(
false, GHOST_kVulkanPlatformX11, 0, m_display, NULL, NULL, 1, 2, debug_context);

View File

@ -124,7 +124,7 @@ class GHOST_SystemX11 : public GHOST_System {
uint32_t width,
uint32_t height,
GHOST_TWindowState state,
GHOST_GLSettings glSettings,
GHOST_GPUSettings gpuSettings,
const bool exclusive = false,
const bool is_dialog = false,
const GHOST_IWindow *parentWindow = nullptr) override;
@ -134,7 +134,7 @@ class GHOST_SystemX11 : public GHOST_System {
* Never explicitly delete the context, use #disposeContext() instead.
* \return The new context (or 0 if creation failed).
*/
GHOST_IContext *createOffscreenContext(GHOST_GLSettings glSettings) override;
GHOST_IContext *createOffscreenContext(GHOST_GPUSettings gpuSettings) override;
/**
* Dispose of a context.

View File

@ -332,9 +332,6 @@ static bool gwl_window_state_set_for_libdecor(libdecor_frame *frame,
libdecor_frame_set_fullscreen(frame, nullptr);
break;
}
case GHOST_kWindowStateEmbedded: {
return false;
}
}
return true;
}
@ -377,9 +374,6 @@ static bool gwl_window_state_set_for_xdg(xdg_toplevel *toplevel,
xdg_toplevel_set_fullscreen(toplevel, nullptr);
break;
}
case GHOST_kWindowStateEmbedded: {
return false;
}
}
return true;
}

View File

@ -412,7 +412,7 @@ bool processEvent(GHOST_EventHandle hEvent, GHOST_TUserDataPtr userData)
int main(int argc, char **argv)
{
GHOST_GLSettings glSettings = {0};
GHOST_GPUSettings gpuSettings = {0};
char *title1 = "gears - main window";
char *title2 = "gears - secondary window";
GHOST_EventConsumerHandle consumer = GHOST_CreateEventConsumer(processEvent, NULL);
@ -433,7 +433,7 @@ int main(int argc, char **argv)
GHOST_kWindowStateNormal,
false,
GHOST_kDrawingContextTypeOpenGL,
glSettings);
gpuSettings);
if (!sMainWindow) {
printf("could not create main window\n");
exit(-1);
@ -450,7 +450,7 @@ int main(int argc, char **argv)
GHOST_kWindowStateNormal,
false,
GHOST_kDrawingContextTypeOpenGL,
glSettings);
gpuSettings);
if (!sSecondaryWindow) {
printf("could not create secondary window\n");
exit(-1);

View File

@ -406,13 +406,13 @@ Application::Application(GHOST_ISystem *system)
m_exitRequested(false),
stereo(false)
{
GHOST_GLSettings glSettings = {0};
glSettings.context_type = GHOST_kDrawingContextTypeOpenGL;
GHOST_GPUSettings gpuSettings = {0};
gpuSettings.context_type = GHOST_kDrawingContextTypeOpenGL;
fApp = this;
// Create the main window
m_mainWindow = system->createWindow(
"gears - main window", 10, 64, 320, 200, GHOST_kWindowStateNormal, glSettings);
"gears - main window", 10, 64, 320, 200, GHOST_kWindowStateNormal, gpuSettings);
if (!m_mainWindow) {
std::cout << "could not create main window\n";
@ -421,7 +421,7 @@ Application::Application(GHOST_ISystem *system)
// Create a secondary window
m_secondaryWindow = system->createWindow(
"gears - secondary window", 340, 64, 320, 200, GHOST_kWindowStateNormal, glSettings);
"gears - secondary window", 340, 64, 320, 200, GHOST_kWindowStateNormal, gpuSettings);
if (!m_secondaryWindow) {
std::cout << "could not create secondary window\n";
exit(-1);

View File

@ -306,7 +306,7 @@ MainWindow *mainwindow_new(MultiTestApp *app)
{
GHOST_SystemHandle sys = multitestapp_get_system(app);
GHOST_WindowHandle win;
GHOST_GLSettings glSettings = {0};
GHOST_GPUSettings gpuSettings = {0};
win = GHOST_CreateWindow(sys,
NULL,
@ -318,7 +318,7 @@ MainWindow *mainwindow_new(MultiTestApp *app)
GHOST_kWindowStateNormal,
false,
GHOST_kDrawingContextTypeOpenGL,
glSettings);
gpuSettings);
if (win) {
MainWindow *mw = MEM_callocN(sizeof(*mw), "mainwindow_new");
@ -557,7 +557,7 @@ static void loggerwindow_handle(void *priv, GHOST_EventHandle evt)
LoggerWindow *loggerwindow_new(MultiTestApp *app)
{
GHOST_GLSettings glSettings = {0};
GHOST_GPUSettings gpuSettings = {0};
GHOST_SystemHandle sys = multitestapp_get_system(app);
uint32_t screensize[2];
GHOST_WindowHandle win;
@ -573,7 +573,7 @@ LoggerWindow *loggerwindow_new(MultiTestApp *app)
GHOST_kWindowStateNormal,
false,
GHOST_kDrawingContextTypeOpenGL,
glSettings);
gpuSettings);
if (win) {
LoggerWindow *lw = MEM_callocN(sizeof(*lw), "loggerwindow_new");
@ -761,7 +761,7 @@ static void extrawindow_handle(void *priv, GHOST_EventHandle evt)
ExtraWindow *extrawindow_new(MultiTestApp *app)
{
GHOST_GLSettings glSettings = {0};
GHOST_GPUSettings gpuSettings = {0};
GHOST_SystemHandle sys = multitestapp_get_system(app);
GHOST_WindowHandle win;
@ -775,7 +775,7 @@ ExtraWindow *extrawindow_new(MultiTestApp *app)
GHOST_kWindowStateNormal,
false,
GHOST_kDrawingContextTypeOpenGL,
glSettings);
gpuSettings);
if (win) {
ExtraWindow *ew = MEM_callocN(sizeof(*ew), "mainwindow_new");

View File

@ -25,7 +25,7 @@
# define HAVE_MALLOC_STATS
#elif defined(__FreeBSD__)
# include <malloc_np.h>
#elif defined(__OpenBSD__)
#elif defined(__NetBSD__) || defined(__OpenBSD__)
# undef USE_MALLOC_USABLE_SIZE
#elif defined(__APPLE__)
# include <malloc/malloc.h>

View File

@ -350,7 +350,7 @@ def main():
if name.rpartition(".")[2].isdigit():
continue
if not ob_eval.data.attributes.active_color:
if (not hasattr(ob_eval.data, 'attributes')) or not ob_eval.data.attributes.active_color:
print("Skipping:", name, "(no vertex colors)")
continue

View File

@ -571,8 +571,6 @@ class KeyframesCo:
keyframe_points.foreach_set("co", co_buffer)
keyframe_points.foreach_set("interpolation", ipo_buffer)
# TODO: in Blender 4.0 the next lines can be replaced with one call to `fcurve.update()`.
# See https://projects.blender.org/blender/blender/issues/107126 for more info.
keyframe_points.sort()
keyframe_points.deduplicate()
keyframe_points.handles_recalc()
# This also deduplicates keys where baked keys were inserted on the
# same frame as existing ones.
fcurve.update()

View File

@ -178,6 +178,8 @@ class Object(bpy_types.ID):
def children(self):
"""All the children of this object.
:type: tuple of `Object`
.. note:: Takes ``O(len(bpy.data.objects))`` time."""
import bpy
return tuple(child for child in bpy.data.objects
@ -187,6 +189,8 @@ class Object(bpy_types.ID):
def children_recursive(self):
"""A list of all children from this object.
:type: tuple of `Object`
.. note:: Takes ``O(len(bpy.data.objects))`` time."""
import bpy
parent_child_map = {}
@ -209,6 +213,8 @@ class Object(bpy_types.ID):
"""
The collections this object is in.
:type: tuple of `Collection`
.. note:: Takes ``O(len(bpy.data.collections) + len(bpy.data.scenes))`` time."""
import bpy
return (
@ -225,6 +231,8 @@ class Object(bpy_types.ID):
def users_scene(self):
"""The scenes this object is in.
:type: tuple of `Scene`
.. note:: Takes ``O(len(bpy.data.scenes) * len(bpy.data.objects))`` time."""
import bpy
return tuple(scene for scene in bpy.data.scenes
@ -523,6 +531,36 @@ def ord_ind(i1, i2):
return i2, i1
def _name_convention_attribute_get(attributes, name, domain, data_type):
try:
attribute = attributes[name]
except KeyError:
return None
if attribute.domain != domain:
return None
if attribute.data_type != data_type:
return None
return attribute
def _name_convention_attribute_ensure(attributes, name, domain, data_type):
try:
attribute = attributes[name]
except KeyError:
return attributes.new(name, data_type, domain)
if attribute.domain == domain and attribute.data_type == data_type:
return attribute
attributes.remove(attribute)
return attributes.new(name, data_type, domain)
def _name_convention_attribute_remove(attributes, name):
try:
attributes.remove(attributes[name])
except KeyError:
pass
class Mesh(bpy_types.ID):
__slots__ = ()
@ -597,6 +635,32 @@ class Mesh(bpy_types.ID):
def edge_keys(self):
return [ed.key for ed in self.edges]
@property
def vertex_creases(self):
"""
Vertex crease values for subdivision surface, corresponding to the "crease_vert" attribute.
"""
return _name_convention_attribute_get(self.attributes, "crease_vert", 'POINT', 'FLOAT')
def vertex_creases_ensure(self):
return _name_convention_attribute_ensure(self.attributes, "crease_vert", 'POINT', 'FLOAT')
def vertex_creases_remove(self):
_name_convention_attribute_remove(self.attributes, "crease_vert")
@property
def edge_creases(self):
"""
Edge crease values for subdivision surface, corresponding to the "crease_edge" attribute.
"""
return _name_convention_attribute_get(self.attributes, "crease_edge", 'EDGE', 'FLOAT')
def edge_creases_ensure(self):
return _name_convention_attribute_ensure(self.attributes, "crease_edge", 'EDGE', 'FLOAT')
def edge_creases_remove(self):
_name_convention_attribute_remove(self.attributes, "crease_edge")
class MeshEdge(StructRNA):
__slots__ = ()

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
@ -1836,6 +1838,10 @@ def km_graph_editor(params):
("graph.delete", {"type": 'DEL', "value": 'PRESS'}, {"properties": [("confirm", False)]}),
("graph.duplicate_move", {"type": 'D', "value": 'PRESS', "shift": True}, None),
("graph.keyframe_insert", {"type": 'I', "value": 'PRESS'}, None),
("graph.keyframe_jump", {"type": 'UP_ARROW', "value": 'PRESS', "repeat": True},
{"properties": [("next", True)]}),
("graph.keyframe_jump", {"type": 'DOWN_ARROW', "value": 'PRESS', "repeat": True},
{"properties": [("next", False)]}),
("graph.click_insert", {"type": params.action_mouse, "value": 'CLICK', "ctrl": True}, None),
("graph.click_insert", {"type": params.action_mouse, "value": 'CLICK', "shift": True, "ctrl": True},
{"properties": [("extend", True)]}),
@ -4504,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):
area = context.area
if (area is not None) and (area.type == 'PROPERTIES'):
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

@ -109,17 +109,6 @@ class MESH_UL_vgroups(UIList):
layout.label(text="", icon_value=icon)
class MESH_UL_fmaps(UIList):
def draw_item(self, _context, layout, _data, item, icon, _active_data, _active_propname, _index):
# assert(isinstance(item, bpy.types.FaceMap))
fmap = item
if self.layout_type in {'DEFAULT', 'COMPACT'}:
layout.prop(fmap, "name", text="", emboss=False, icon='FACE_MAPS')
elif self.layout_type == 'GRID':
layout.alignment = 'CENTER'
layout.label(text="", icon_value=icon)
class MESH_UL_shape_keys(UIList):
def draw_item(self, _context, layout, _data, item, icon, active_data, _active_propname, index):
# assert(isinstance(item, bpy.types.ShapeKey))
@ -280,50 +269,6 @@ class DATA_PT_vertex_groups(MeshButtonsPanel, Panel):
layout.prop(context.tool_settings, "vertex_group_weight", text="Weight")
class DATA_PT_face_maps(MeshButtonsPanel, Panel):
bl_label = "Face Maps"
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH', 'BLENDER_WORKBENCH_NEXT'}
@classmethod
def poll(cls, context):
obj = context.object
return (obj and obj.type == 'MESH')
def draw(self, context):
layout = self.layout
ob = context.object
facemap = ob.face_maps.active
rows = 2
if facemap:
rows = 4
row = layout.row()
row.template_list("MESH_UL_fmaps", "", ob, "face_maps", ob.face_maps, "active_index", rows=rows)
col = row.column(align=True)
col.operator("object.face_map_add", icon='ADD', text="")
col.operator("object.face_map_remove", icon='REMOVE', text="")
if facemap:
col.separator()
col.operator("object.face_map_move", icon='TRIA_UP', text="").direction = 'UP'
col.operator("object.face_map_move", icon='TRIA_DOWN', text="").direction = 'DOWN'
if ob.face_maps and (ob.mode == 'EDIT' and ob.type == 'MESH'):
row = layout.row()
sub = row.row(align=True)
sub.operator("object.face_map_assign", text="Assign")
sub.operator("object.face_map_remove_from", text="Remove")
sub = row.row(align=True)
sub.operator("object.face_map_select", text="Select")
sub.operator("object.face_map_deselect", text="Deselect")
class DATA_PT_shape_keys(MeshButtonsPanel, Panel):
bl_label = "Shape Keys"
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH', 'BLENDER_WORKBENCH_NEXT'}
@ -486,16 +431,6 @@ class DATA_PT_customdata(MeshButtonsPanel, Panel):
col.operator("mesh.customdata_mask_clear", icon='X')
col.operator("mesh.customdata_skin_clear", icon='X')
if me.has_crease_edge:
col.operator("mesh.customdata_crease_edge_clear", icon='X')
else:
col.operator("mesh.customdata_crease_edge_add", icon='ADD')
if me.has_crease_vertex:
col.operator("mesh.customdata_crease_vertex_clear", icon='X')
else:
col.operator("mesh.customdata_crease_vertex_add", icon='ADD')
class DATA_PT_custom_props_mesh(MeshButtonsPanel, PropertyPanel, Panel):
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH', 'BLENDER_WORKBENCH_NEXT'}
@ -707,7 +642,6 @@ classes = (
MESH_MT_color_attribute_context_menu,
MESH_MT_attribute_context_menu,
MESH_UL_vgroups,
MESH_UL_fmaps,
MESH_UL_shape_keys,
MESH_UL_uvmaps,
MESH_UL_attributes,
@ -716,7 +650,6 @@ classes = (
DATA_PT_shape_keys,
DATA_PT_uv_texture,
DATA_PT_vertex_colors,
DATA_PT_face_maps,
DATA_PT_mesh_attributes,
DATA_PT_normals,
DATA_PT_texture_space,

View File

@ -12,6 +12,7 @@ from bpy.types import (
ParticleSettings,
Texture,
)
from bpy.app.translations import contexts as i18n_contexts
from rna_prop_ui import PropertyPanel
from bl_ui.properties_paint_common import brush_texture_settings
@ -512,10 +513,10 @@ class TEXTURE_PT_image_mapping(TextureTypePanel, Panel):
sub.prop(tex, "repeat_x", text="Repeat X")
sub.prop(tex, "repeat_y", text="Y")
col = flow.column()
col = flow.column(heading="Mirror")
sub = col.column()
sub.active = (tex.repeat_x > 1)
sub.prop(tex, "use_mirror_x", text="Mirror X")
sub.prop(tex, "use_mirror_x", text="X")
sub = col.column()
sub.active = (tex.repeat_y > 1)
@ -527,8 +528,8 @@ class TEXTURE_PT_image_mapping(TextureTypePanel, Panel):
col = flow.column()
col.prop(tex, "checker_distance", text="Distance")
col = flow.column()
col.prop(tex, "use_checker_even", text="Tiles Even")
col = flow.column(heading="Tiles")
col.prop(tex, "use_checker_even", text="Even", text_ctxt=i18n_contexts.amount)
col.prop(tex, "use_checker_odd", text="Odd")
else:
del flow

View File

@ -1221,7 +1221,7 @@ class IMAGE_PT_tools_brush_display(Panel, BrushButtonsPanel, DisplayPanel):
bl_context = ".paint_common_2d"
bl_parent_id = "IMAGE_PT_paint_settings"
bl_category = "Tool"
bl_label = "Brush Tip"
bl_label = "Cursor"
bl_options = {'DEFAULT_CLOSED'}
bl_ui_units_x = 15

View File

@ -3111,7 +3111,7 @@ class VIEW3D_PT_tools_active(ToolSelectPanelHelper, Panel):
*_tools_annotate,
],
'EDIT_GPENCIL': [
*_tools_gpencil_select,
*_tools_select,
_defs_view3d_generic.cursor,
None,
*_tools_transform,

View File

@ -2030,6 +2030,22 @@ class VIEW3D_MT_select_edit_gpencil(Menu):
layout.separator()
layout.operator("grease_pencil.select_linked", text="Linked")
layout.separator()
op = layout.operator("grease_pencil.select_ends", text="First")
op.amount_start = 1
op.amount_end = 0
op = layout.operator("grease_pencil.select_ends", text="Last")
op.amount_start = 0
op.amount_end = 1
layout.separator()
layout.operator("grease_pencil.select_more")
layout.operator("grease_pencil.select_less")
class VIEW3D_MT_select_paint_mask(Menu):
bl_label = "Select"
@ -2103,7 +2119,7 @@ class VIEW3D_MT_select_edit_curves(Menu):
layout.separator()
layout.operator("curves.select_random", text="Random")
layout.operator("curves.select_end", text="Endpoints")
layout.operator("curves.select_ends", text="Endpoints")
layout.operator("curves.select_linked", text="Linked")
layout.separator()
@ -2121,7 +2137,7 @@ class VIEW3D_MT_select_sculpt_curves(Menu):
layout.operator("curves.select_all", text="None").action = 'DESELECT'
layout.operator("curves.select_all", text="Invert").action = 'INVERT'
layout.operator("sculpt_curves.select_random", text="Random")
layout.operator("curves.select_end", text="Endpoints")
layout.operator("curves.select_ends", text="Endpoints")
layout.operator("sculpt_curves.select_grow", text="Grow")

View File

@ -335,6 +335,7 @@ compositor_node_categories = [
NodeItem("CompositorNodeSunBeams"),
NodeItem("CompositorNodeDenoise"),
NodeItem("CompositorNodeAntiAliasing"),
NodeItem("CompositorNodeKuwahara"),
]),
CompositorNodeCategory("CMP_OP_VECTOR", "Vector", items=[
NodeItem("CompositorNodeNormal"),

View File

@ -124,6 +124,7 @@ class AssetLibrary {
*/
AssetRepresentation &add_external_asset(StringRef relative_asset_path,
StringRef name,
int id_type,
std::unique_ptr<AssetMetaData> metadata);
/** See #AssetLibrary::add_external_asset(). */
AssetRepresentation &add_local_id_asset(StringRef relative_asset_path, ID &id);

View File

@ -10,6 +10,8 @@
#include "BLI_compiler_attrs.h"
#include "DNA_ID_enums.h"
#ifdef __cplusplus
extern "C" {
#endif
@ -22,6 +24,8 @@ typedef struct AssetRepresentation AssetRepresentation;
const char *AS_asset_representation_name_get(const AssetRepresentation *asset)
ATTR_WARN_UNUSED_RESULT;
ID_Type AS_asset_representation_id_type_get(const AssetRepresentation *asset)
ATTR_WARN_UNUSED_RESULT;
AssetMetaData *AS_asset_representation_metadata_get(const AssetRepresentation *asset)
ATTR_WARN_UNUSED_RESULT;
struct ID *AS_asset_representation_local_id_get(const AssetRepresentation *asset)
@ -30,6 +34,9 @@ bool AS_asset_representation_is_local_id(const AssetRepresentation *asset) ATTR_
bool AS_asset_representation_is_never_link(const AssetRepresentation *asset)
ATTR_WARN_UNUSED_RESULT;
bool AS_asset_representation_may_override_import_method(const AssetRepresentation *asset);
bool AS_asset_representation_use_relative_path_get(const AssetRepresentation *asset);
/**
* C version of #AssetRepresentation::make_weak_reference. Returned pointer needs freeing with
* #MEM_delete() or #BKE_asset_weak_reference_free().

View File

@ -19,6 +19,7 @@
#include "BLI_string_ref.hh"
#include "DNA_ID_enums.h"
#include "DNA_asset_types.h"
#include "AS_asset_identifier.hh"
@ -42,6 +43,7 @@ class AssetRepresentation {
struct ExternalAsset {
std::string name;
int id_type = 0;
std::unique_ptr<AssetMetaData> metadata_ = nullptr;
};
union {
@ -55,6 +57,7 @@ class AssetRepresentation {
/** Constructs an asset representation for an external ID. The asset will not be editable. */
AssetRepresentation(AssetIdentifier &&identifier,
StringRef name,
int id_type,
std::unique_ptr<AssetMetaData> metadata,
const AssetLibrary &owner_asset_library);
/**
@ -85,6 +88,7 @@ class AssetRepresentation {
std::unique_ptr<AssetWeakReference> make_weak_reference() const;
StringRefNull get_name() const;
ID_Type get_id_type() const;
AssetMetaData &get_metadata() const;
/**
* Get the import method to use for this asset. A different one may be used if
@ -114,6 +118,9 @@ class AssetRepresentation {
/* C-Handle */
struct AssetRepresentation;
const blender::StringRefNull AS_asset_representation_library_relative_identifier_get(
const AssetRepresentation *asset_handle);
std::string AS_asset_representation_full_path_get(const ::AssetRepresentation *asset);
/**
* Get the absolute path to the .blend file containing the given asset. String will be empty if
@ -123,5 +130,3 @@ std::string AS_asset_representation_full_path_get(const ::AssetRepresentation *a
std::string AS_asset_representation_full_library_path_get(const ::AssetRepresentation *asset);
std::optional<eAssetImportMethod> AS_asset_representation_import_method_get(
const ::AssetRepresentation *asset_handle);
bool AS_asset_representation_may_override_import_method(const ::AssetRepresentation *asset_handle);
bool AS_asset_representation_use_relative_path_get(const ::AssetRepresentation *asset_handle);

View File

@ -230,11 +230,12 @@ void AssetLibrary::refresh()
AssetRepresentation &AssetLibrary::add_external_asset(StringRef relative_asset_path,
StringRef name,
const int id_type,
std::unique_ptr<AssetMetaData> metadata)
{
AssetIdentifier identifier = asset_identifier_from_library(relative_asset_path);
return asset_storage_->add_external_asset(
std::move(identifier), name, std::move(metadata), *this);
std::move(identifier), name, id_type, std::move(metadata), *this);
}
AssetRepresentation &AssetLibrary::add_local_id_asset(StringRef relative_asset_path, ID &id)

View File

@ -21,6 +21,7 @@ namespace blender::asset_system {
AssetRepresentation::AssetRepresentation(AssetIdentifier &&identifier,
StringRef name,
const int id_type,
std::unique_ptr<AssetMetaData> metadata,
const AssetLibrary &owner_asset_library)
: identifier_(identifier),
@ -29,6 +30,7 @@ AssetRepresentation::AssetRepresentation(AssetIdentifier &&identifier,
external_asset_()
{
external_asset_.name = name;
external_asset_.id_type = id_type;
external_asset_.metadata_ = std::move(metadata);
}
@ -87,6 +89,15 @@ StringRefNull AssetRepresentation::get_name() const
return external_asset_.name;
}
ID_Type AssetRepresentation::get_id_type() const
{
if (is_local_id_) {
return GS(local_asset_id_->name);
}
return ID_Type(external_asset_.id_type);
}
AssetMetaData &AssetRepresentation::get_metadata() const
{
return is_local_id_ ? *local_asset_id_->asset_data : *external_asset_.metadata_;
@ -135,6 +146,15 @@ const AssetLibrary &AssetRepresentation::owner_asset_library() const
using namespace blender;
const StringRefNull AS_asset_representation_library_relative_identifier_get(
const AssetRepresentation *asset_handle)
{
const asset_system::AssetRepresentation *asset =
reinterpret_cast<const asset_system::AssetRepresentation *>(asset_handle);
const asset_system::AssetIdentifier &identifier = asset->get_identifier();
return identifier.library_relative_identifier();
}
std::string AS_asset_representation_full_path_get(const AssetRepresentation *asset_handle)
{
const asset_system::AssetRepresentation *asset =
@ -183,6 +203,13 @@ const char *AS_asset_representation_name_get(const AssetRepresentation *asset_ha
return asset->get_name().c_str();
}
ID_Type AS_asset_representation_id_type_get(const AssetRepresentation *asset_handle)
{
const asset_system::AssetRepresentation *asset =
reinterpret_cast<const asset_system::AssetRepresentation *>(asset_handle);
return asset->get_id_type();
}
AssetMetaData *AS_asset_representation_metadata_get(const AssetRepresentation *asset_handle)
{
const asset_system::AssetRepresentation *asset =

View File

@ -27,11 +27,12 @@ AssetRepresentation &AssetStorage::add_local_id_asset(AssetIdentifier &&identifi
AssetRepresentation &AssetStorage::add_external_asset(AssetIdentifier &&identifier,
StringRef name,
const int id_type,
std::unique_ptr<AssetMetaData> metadata,
const AssetLibrary &owner_asset_library)
{
return *external_assets_.lookup_key_or_add(std::make_unique<AssetRepresentation>(
std::move(identifier), name, std::move(metadata), owner_asset_library));
std::move(identifier), name, id_type, std::move(metadata), owner_asset_library));
}
bool AssetStorage::remove_asset(AssetRepresentation &asset)

View File

@ -37,6 +37,7 @@ class AssetStorage {
/** See #AssetLibrary::add_external_asset(). */
AssetRepresentation &add_external_asset(AssetIdentifier &&identifier,
StringRef name,
int id_type,
std::unique_ptr<AssetMetaData> metadata,
const AssetLibrary &owner_asset_library);
/** See #AssetLibrary::add_external_asset(). */

View File

@ -32,7 +32,8 @@ class AssetRepresentationTest : public AssetLibraryTestBase {
AssetRepresentation &add_dummy_asset(AssetLibrary &library, StringRef relative_path)
{
std::unique_ptr<AssetMetaData> dummy_metadata = std::make_unique<AssetMetaData>();
return library.add_external_asset(relative_path, "Some asset name", std::move(dummy_metadata));
return library.add_external_asset(
relative_path, "Some asset name", 0, std::move(dummy_metadata));
}
};

View File

@ -38,6 +38,13 @@ typedef struct AssetTypeInfo {
struct AssetMetaData *BKE_asset_metadata_create(void);
void BKE_asset_metadata_free(struct AssetMetaData **asset_data);
/**
* Create a copy of the #AssetMetaData so that it can be assigned to another asset.
*
* The caller becomes the owner of the returned pointer.
*/
struct AssetMetaData *BKE_asset_metadata_copy(const struct AssetMetaData *source);
struct AssetTagEnsureResult {
struct AssetTag *tag;
/* Set to false if a tag of this name was already present. */

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

@ -27,13 +27,13 @@ extern "C" {
/* Blender file format version. */
#define BLENDER_FILE_VERSION BLENDER_VERSION
#define BLENDER_FILE_SUBVERSION 5
#define BLENDER_FILE_SUBVERSION 7
/* Minimum Blender version that supports reading file written with the current
* version. Older Blender versions will test this and show a warning if the file
* was written with too new a version. */
#define BLENDER_FILE_MIN_VERSION 400
#define BLENDER_FILE_MIN_SUBVERSION 2
#define BLENDER_FILE_MIN_SUBVERSION 3
/** User readable version string. */
const char *BKE_blender_version_string(void);

View File

@ -51,5 +51,8 @@ struct GeometryDeformation {
GeometryDeformation get_evaluated_curves_deformation(const Object *ob_eval, const Object &ob_orig);
GeometryDeformation get_evaluated_curves_deformation(const Depsgraph &depsgraph,
const Object &ob_orig);
GeometryDeformation get_evaluated_grease_pencil_drawing_deformation(const Object *ob_eval,
const Object &ob_orig,
int drawing_index);
} // namespace blender::bke::crazyspace

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

@ -612,8 +612,8 @@ int CustomData_layertype_layers_max(eCustomDataType type);
#ifdef __cplusplus
/** \return The maximum length for a layer name with the given prefix. */
int CustomData_name_max_length_calc(blender::StringRef name);
/** \return The maximum size in bytes needed for a layer name with the given prefix. */
int CustomData_name_maxncpy_calc(blender::StringRef name);
#endif
@ -705,7 +705,8 @@ enum {
CD_FAKE_SHARP = CD_FAKE | 200, /* Sharp flag for edges, smooth flag for faces. */
CD_FAKE_BWEIGHT = CD_FAKE | 300, /* UV seam flag for edges. */
CD_FAKE_BWEIGHT = CD_FAKE | 300,
CD_FAKE_CREASE = CD_FAKE | 400,
};
enum {
@ -733,7 +734,7 @@ enum {
typedef struct CustomDataTransferLayerMap {
struct CustomDataTransferLayerMap *next, *prev;
eCustomDataType data_type;
int data_type;
int mix_mode;
float mix_factor;
/** If non-NULL, array of weights, one for each dest item, replaces mix_factor. */

View File

@ -59,7 +59,7 @@ typedef struct BMEditMesh {
int mirror_cdlayer;
/**
* Enable for evaluated copies, causes the edit-mesh to free the memory, not it's contents.
* Enable for evaluated copies, causes the edit-mesh to free the memory, not its contents.
*/
char is_shallow_copy;

View File

@ -180,9 +180,6 @@ struct Mesh *BKE_mesh_new_nomain_from_curve_displist(const struct Object *ob,
bool BKE_mesh_attribute_required(const char *name);
bool BKE_mesh_ensure_facemap_customdata(struct Mesh *me);
bool BKE_mesh_clear_facemap_customdata(struct Mesh *me);
float (*BKE_mesh_orco_verts_get(struct Object *ob))[3];
void BKE_mesh_orco_verts_transform(struct Mesh *me, float (*orco)[3], int totvert, int invert);

View File

@ -129,7 +129,7 @@ struct CornerNormalSpaceArray {
*/
Array<Array<int>> corners_by_space;
/** Whether to create the above map when calculating normals. */
bool create_corners_by_space;
bool create_corners_by_space = false;
};
void lnor_space_custom_normal_to_data(const CornerNormalSpace *lnor_space,

View File

@ -40,6 +40,7 @@ void BKE_mesh_legacy_face_set_to_generic(struct Mesh *mesh);
* Copy edge creases from edges to a separate layer.
*/
void BKE_mesh_legacy_edge_crease_to_layers(struct Mesh *mesh);
void BKE_mesh_legacy_crease_to_generic(struct Mesh *mesh);
/**
* Copy bevel weights from vertices and edges to separate layers.
@ -84,6 +85,8 @@ void BKE_mesh_legacy_convert_polys_to_offsets(Mesh *mesh);
void BKE_mesh_legacy_convert_loops_to_corners(struct Mesh *mesh);
void BKE_mesh_legacy_face_map_to_generic(struct Mesh *mesh);
#endif
#ifdef __cplusplus

View File

@ -1061,6 +1061,7 @@ void BKE_nodetree_remove_layer_n(struct bNodeTree *ntree, struct Scene *scene, i
#define CMP_NODE_INPAINT 272
#define CMP_NODE_DESPECKLE 273
#define CMP_NODE_ANTIALIASING 274
#define CMP_NODE_KUWAHARA 275
#define CMP_NODE_GLARE 301
#define CMP_NODE_TONEMAP 302

View File

@ -1,37 +0,0 @@
/* SPDX-FileCopyrightText: 2023 Blender Foundation
*
* SPDX-License-Identifier: GPL-2.0-or-later */
#pragma once
/** \file
* \ingroup bke
* \brief Functions for dealing with object face-maps.
*/
#ifdef __cplusplus
extern "C" {
#endif
struct ListBase;
struct Object;
struct bFaceMap;
struct bFaceMap *BKE_object_facemap_add(struct Object *ob);
struct bFaceMap *BKE_object_facemap_add_name(struct Object *ob, const char *name);
void BKE_object_facemap_remove(struct Object *ob, struct bFaceMap *fmap);
void BKE_object_facemap_clear(struct Object *ob);
int BKE_object_facemap_name_index(struct Object *ob, const char *name);
void BKE_object_facemap_unique_name(struct Object *ob, struct bFaceMap *fmap);
struct bFaceMap *BKE_object_facemap_find_name(struct Object *ob, const char *name);
void BKE_object_facemap_copy_list(struct ListBase *outbase, const struct ListBase *inbase);
int *BKE_object_facemap_index_map_create(struct Object *ob_src,
struct Object *ob_dst,
int *r_map_len);
void BKE_object_facemap_index_map_apply(int *fmap, int fmap_len, const int *map, int map_len);
#ifdef __cplusplus
}
#endif

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
@ -255,7 +255,7 @@ typedef struct PanelType {
char idname[BKE_ST_MAXNAME]; /* unique name */
char label[BKE_ST_MAXNAME]; /* for panel header */
char *description; /* for panel tooltip */
const char *description; /* for panel tooltip */
char translation_context[BKE_ST_MAXNAME];
char context[BKE_ST_MAXNAME]; /* for buttons window */
char category[BKE_ST_MAXNAME]; /* for category tabs */

View File

@ -59,11 +59,6 @@ void texttool_suggest_select(SuggItem *sel);
SuggItem *texttool_suggest_selected(void);
int *texttool_suggest_top(void);
/* Documentation */
void texttool_docs_show(const char *docs);
char *texttool_docs_get(void);
void texttool_docs_clear(void);
#ifdef __cplusplus
}
#endif

View File

@ -470,7 +470,7 @@ void BKE_tracking_camera_principal_point_pixel_set(struct MovieClip *clip,
* extra parameters of distortions models. */
bool BKE_tracking_camera_distortion_equal(const struct MovieTrackingCamera *a,
const struct MovieTrackingCamera *b);
/* Hashes distortion related paramaters of camera. Ideally, this implementation will be
/* Hashes distortion related parameters of camera. Ideally, this implementation will be
* abstracted away in the future, but for now, one needs to be careful about it and handle any
* extra parameters of distortions models. */
uint64_t BKE_tracking_camera_distortion_hash(const struct MovieTrackingCamera *camera);

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

@ -241,7 +241,6 @@ set(SRC
intern/object.cc
intern/object_deform.c
intern/object_dupli.cc
intern/object_facemap.c
intern/object_update.cc
intern/ocean.c
intern/ocean_spectrum.c
@ -457,7 +456,6 @@ set(SRC
BKE_node_tree_zones.hh
BKE_object.h
BKE_object_deform.h
BKE_object_facemap.h
BKE_ocean.h
BKE_outliner_treehash.hh
BKE_packedFile.h

View File

@ -65,7 +65,7 @@ static void pchan_deform_accumulate(const DualQuat *deform_dq,
BLI_assert(!co_accum);
if (deform_dq->scale_weight) {
/* FIX https://projects.blender.org/blender/blender/issues/32022 */
/* FIX #32022. */
DualQuat mdq = *deform_dq;
float dst[3];
mul_v3_m4v3(dst, mdq.scale, co_in);
@ -74,7 +74,7 @@ static void pchan_deform_accumulate(const DualQuat *deform_dq,
mdq.trans[1] += .5f * (mdq.quat[0] * dst[0] + mdq.quat[2] * dst[2] - mdq.quat[3] * dst[1]);
mdq.trans[2] += .5f * (mdq.quat[0] * dst[1] + mdq.quat[3] * dst[0] - mdq.quat[1] * dst[2]);
mdq.trans[3] += .5f * (mdq.quat[0] * dst[2] + mdq.quat[1] * dst[1] - mdq.quat[2] * dst[0]);
mdq.scale_weight = 0.f;
mdq.scale_weight = 0.0f;
add_weighted_dq_dq(dq_accum, &mdq, weight);
}
else {

View File

@ -39,6 +39,38 @@ void BKE_asset_metadata_free(AssetMetaData **asset_data)
*asset_data = nullptr;
}
AssetMetaData *BKE_asset_metadata_copy(const AssetMetaData *source)
{
AssetMetaData *copy = BKE_asset_metadata_create();
copy->local_type_info = source->local_type_info;
if (source->properties) {
copy->properties = IDP_CopyProperty(source->properties);
}
BKE_asset_metadata_catalog_id_set(copy, source->catalog_id, source->catalog_simple_name);
if (source->author) {
copy->author = BLI_strdup(source->author);
}
if (source->description) {
copy->description = BLI_strdup(source->description);
}
if (source->copyright) {
copy->copyright = BLI_strdup(source->copyright);
}
if (source->license) {
copy->license = BLI_strdup(source->license);
}
BLI_duplicatelist(&copy->tags, &source->tags);
copy->active_tag = source->active_tag;
copy->tot_tags = source->tot_tags;
return copy;
}
AssetMetaData::~AssetMetaData()
{
if (properties) {

View File

@ -174,7 +174,7 @@ bool BKE_id_attribute_rename(ID *id,
* is clamped to it's maximum length, otherwise assigning an over-long name multiple times
* will add `.001` suffix unnecessarily. */
{
const int new_name_maxncpy = CustomData_name_max_length_calc(new_name);
const int new_name_maxncpy = CustomData_name_maxncpy_calc(new_name);
/* NOTE: A function that performs a clamped comparison without copying would be handy here. */
char new_name_clamped[MAX_CUSTOMDATA_LAYER_NAME];
BLI_strncpy_utf8(new_name_clamped, new_name, new_name_maxncpy);
@ -255,7 +255,7 @@ static bool unique_name_cb(void *arg, const char *name)
bool BKE_id_attribute_calc_unique_name(ID *id, const char *name, char *outname)
{
AttrUniqueData data{id};
const int name_maxncpy = CustomData_name_max_length_calc(name);
const int name_maxncpy = CustomData_name_maxncpy_calc(name);
/* Set default name if none specified.
* NOTE: We only call IFACE_() if needed to avoid locale lookup overhead. */

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

@ -208,14 +208,13 @@ static void setup_app_userdef(BlendFileData *bfd)
BKE_blender_userdef_data_set_and_free(bfd->user);
bfd->user = nullptr;
/* Security issue: any blend file could include a USER block.
/* Security issue: any blend file could include a #BLO_CODE_USER block.
*
* Currently we load prefs from BLENDER_STARTUP_FILE and later on load BLENDER_USERPREF_FILE,
* to load the preferences defined in the users home dir.
* Preferences are loaded from #BLENDER_STARTUP_FILE and later on load #BLENDER_USERPREF_FILE,
* to load the preferences defined in the users home directory.
*
* This means we will never accidentally (or maliciously)
* enable scripts auto-execution by loading a `.blend` file.
*/
* enable scripts auto-execution by loading a `.blend` file. */
U.flag |= USER_SCRIPT_AUTOEXEC_DISABLE;
}
}
@ -417,7 +416,7 @@ static void swap_wm_data_for_blendfile(ReuseOldBMainData *reuse_data, const bool
* for further processing in WM code. */
if (load_ui && new_wm != nullptr) {
/* Support window-manager ID references being held between file load operations by keeping
* #Main.wm.first memory address in-place, while swapping all of it's contents.
* #Main.wm.first memory address in-place, while swapping all of its contents.
*
* This is needed so items such as key-maps can be held by an add-on,
* without it pointing to invalid memory, see: #86431. */

View File

@ -24,6 +24,7 @@
#include "BKE_curves.hh"
#include "BKE_editmesh.h"
#include "BKE_geometry_set.hh"
#include "BKE_grease_pencil.hh"
#include "BKE_lib_id.h"
#include "BKE_mesh.hh"
#include "BKE_mesh_wrapper.h"
@ -662,4 +663,37 @@ GeometryDeformation get_evaluated_curves_deformation(const Depsgraph &depsgraph,
return get_evaluated_curves_deformation(ob_eval, ob_orig);
}
GeometryDeformation get_evaluated_grease_pencil_drawing_deformation(const Object *ob_eval,
const Object &ob_orig,
const int drawing_index)
{
BLI_assert(ob_orig.type == OB_GREASE_PENCIL);
const GreasePencil &grease_pencil_orig = *static_cast<const GreasePencil *>(ob_orig.data);
GreasePencilDrawingBase *drawing_base = grease_pencil_orig.drawings()[drawing_index];
GeometryDeformation deformation;
if (drawing_base->type == GP_DRAWING) {
GreasePencilDrawing *drawing = reinterpret_cast<GreasePencilDrawing *>(drawing_base);
/* Use the undeformed positions by default. */
deformation.positions = drawing->geometry.wrap().positions();
}
else if (drawing_base->type == GP_DRAWING_REFERENCE) {
/* TODO */
}
if (ob_eval == nullptr) {
return deformation;
}
const GeometrySet *geometry_eval = ob_eval->runtime.geometry_set_eval;
if (geometry_eval == nullptr) {
return deformation;
}
/* TODO: Read `GeometryComponentEditData` from `geometry_eval` and populate deformation with it.
*/
return deformation;
}
} // namespace blender::bke::crazyspace

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

@ -1170,6 +1170,7 @@ void CurvesGeometry::remove_points(const IndexMask &points_to_delete,
}
if (points_to_delete.size() == this->points_num()) {
*this = {};
return;
}
IndexMaskMemory memory;
const IndexMask points_to_copy = points_to_delete.complement(this->points_range(), memory);

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