Cycles: new Microfacet-based Hair BSDF with elliptical cross-section support #105600

Merged
Weizhen Huang merged 114 commits from weizhen/blender:microfacet_hair into main 2023-08-18 12:46:20 +02:00
204 changed files with 2188 additions and 4757 deletions
Showing only changes of commit 6ea34518b9 - Show all commits

View File

@ -333,10 +333,7 @@ option(WITH_MOD_OCEANSIM "Enable Ocean Modifier" ON)
# Image format support
option(WITH_IMAGE_OPENEXR "Enable OpenEXR Support (http://www.openexr.com)" ON)
option(WITH_IMAGE_OPENJPEG "Enable OpenJpeg Support (http://www.openjpeg.org)" ON)
option(WITH_IMAGE_TIFF "Enable LibTIFF Support" ON)
option(WITH_IMAGE_DDS "Enable DDS Image Support" ON)
option(WITH_IMAGE_CINEON "Enable CINEON and DPX Image Support" ON)
option(WITH_IMAGE_HDR "Enable HDR Image Support" ON)
option(WITH_IMAGE_WEBP "Enable WebP Image Support" ON)
# Audio/Video format support
@ -648,15 +645,15 @@ if(WIN32)
endif()
# Compiler tool-chain.
if(UNIX AND NOT APPLE)
if(UNIX)
if(CMAKE_COMPILER_IS_GNUCC)
option(WITH_LINKER_GOLD "Use ld.gold linker which is usually faster than ld.bfd" ON)
mark_as_advanced(WITH_LINKER_GOLD)
option(WITH_LINKER_LLD "Use ld.lld linker which is usually faster than ld.gold" OFF)
mark_as_advanced(WITH_LINKER_LLD)
endif()
if(CMAKE_COMPILER_IS_GNUCC OR CMAKE_C_COMPILER_ID MATCHES "Clang")
option(WITH_LINKER_MOLD "Use ld.mold linker which is usually faster than ld.gold & ld.lld." OFF)
option(WITH_LINKER_LLD "Use ld.lld linker which is usually faster than ld.gold" OFF)
mark_as_advanced(WITH_LINKER_LLD)
option(WITH_LINKER_MOLD "Use ld.mold linker which is usually faster than ld.gold & ld.lld. Needs \"sold\" subscription on macOS." OFF)
mark_as_advanced(WITH_LINKER_MOLD)
endif()
endif()
@ -896,9 +893,6 @@ set_and_warn_dependency(WITH_IMAGE_OPENEXR WITH_ALEMBIC OFF)
set_and_warn_dependency(WITH_IMAGE_OPENEXR WITH_VULKAN_BACKEND OFF)
set_and_warn_dependency(WITH_IMAGE_OPENEXR WITH_CYCLES_OSL OFF)
# Haru needs `TIFFFaxBlackCodes` & `TIFFFaxWhiteCodes` symbols from TIFF.
set_and_warn_dependency(WITH_IMAGE_TIFF WITH_HARU OFF)
# auto enable openimageio for cycles
if(WITH_CYCLES)
# auto enable llvm for cycles_osl
@ -1941,11 +1935,8 @@ if(FIRST_RUN)
info_cfg_text("Image Formats:")
info_cfg_option(WITH_IMAGE_CINEON)
info_cfg_option(WITH_IMAGE_DDS)
info_cfg_option(WITH_IMAGE_HDR)
info_cfg_option(WITH_IMAGE_OPENEXR)
info_cfg_option(WITH_IMAGE_OPENJPEG)
info_cfg_option(WITH_IMAGE_TIFF)
info_cfg_text("Audio:")
info_cfg_option(WITH_CODEC_AVI)

View File

@ -26,11 +26,8 @@ set(WITH_HARU ON CACHE BOOL "" FORCE)
set(WITH_IK_ITASC ON CACHE BOOL "" FORCE)
set(WITH_IK_SOLVER ON CACHE BOOL "" FORCE)
set(WITH_IMAGE_CINEON ON CACHE BOOL "" FORCE)
set(WITH_IMAGE_DDS ON CACHE BOOL "" FORCE)
set(WITH_IMAGE_HDR ON CACHE BOOL "" FORCE)
set(WITH_IMAGE_OPENEXR ON CACHE BOOL "" FORCE)
set(WITH_IMAGE_OPENJPEG ON CACHE BOOL "" FORCE)
set(WITH_IMAGE_TIFF ON CACHE BOOL "" FORCE)
set(WITH_IMAGE_WEBP ON CACHE BOOL "" FORCE)
set(WITH_INPUT_NDOF ON CACHE BOOL "" FORCE)
set(WITH_INPUT_IME ON CACHE BOOL "" FORCE)

View File

@ -27,11 +27,8 @@ set(WITH_HARU OFF CACHE BOOL "" FORCE)
set(WITH_IK_ITASC OFF CACHE BOOL "" FORCE)
set(WITH_IK_SOLVER OFF CACHE BOOL "" FORCE)
set(WITH_IMAGE_CINEON OFF CACHE BOOL "" FORCE)
set(WITH_IMAGE_DDS OFF CACHE BOOL "" FORCE)
set(WITH_IMAGE_HDR OFF CACHE BOOL "" FORCE)
set(WITH_IMAGE_OPENEXR OFF CACHE BOOL "" FORCE)
set(WITH_IMAGE_OPENJPEG OFF CACHE BOOL "" FORCE)
set(WITH_IMAGE_TIFF OFF CACHE BOOL "" FORCE)
set(WITH_IMAGE_WEBP OFF CACHE BOOL "" FORCE)
set(WITH_INPUT_IME OFF CACHE BOOL "" FORCE)
set(WITH_INPUT_NDOF OFF CACHE BOOL "" FORCE)

View File

@ -27,11 +27,8 @@ set(WITH_HARU ON CACHE BOOL "" FORCE)
set(WITH_IK_ITASC ON CACHE BOOL "" FORCE)
set(WITH_IK_SOLVER ON CACHE BOOL "" FORCE)
set(WITH_IMAGE_CINEON ON CACHE BOOL "" FORCE)
set(WITH_IMAGE_DDS ON CACHE BOOL "" FORCE)
set(WITH_IMAGE_HDR ON CACHE BOOL "" FORCE)
set(WITH_IMAGE_OPENEXR ON CACHE BOOL "" FORCE)
set(WITH_IMAGE_OPENJPEG ON CACHE BOOL "" FORCE)
set(WITH_IMAGE_TIFF ON CACHE BOOL "" FORCE)
set(WITH_IMAGE_WEBP ON CACHE BOOL "" FORCE)
set(WITH_INPUT_NDOF ON CACHE BOOL "" FORCE)
set(WITH_INPUT_IME ON CACHE BOOL "" FORCE)

View File

@ -221,10 +221,8 @@ find_package(PNG REQUIRED)
set(JPEG_ROOT ${LIBDIR}/jpeg)
find_package(JPEG REQUIRED)
if(WITH_IMAGE_TIFF)
set(TIFF_ROOT ${LIBDIR}/tiff)
find_package(TIFF REQUIRED)
endif()
set(TIFF_ROOT ${LIBDIR}/tiff)
find_package(TIFF REQUIRED)
if(WITH_IMAGE_WEBP)
set(WEBP_ROOT_DIR ${LIBDIR}/webp)
@ -453,6 +451,31 @@ if(WITH_COMPILER_CCACHE)
endif()
endif()
unset(_custom_LINKER_FUSE_FLAG)
if(WITH_LINKER_LLD)
find_program(LLD_PROGRAM ld.lld)
if(LLD_PROGRAM)
set(_custom_LINKER_FUSE_FLAG "-fuse-ld=lld")
else()
message(WARNING "LLD linker NOT found, disabling WITH_LINKER_LLD")
set(WITH_LINKER_LLD OFF)
endif()
endif()
if(WITH_LINKER_MOLD)
find_program(MOLD_PROGRAM mold)
if(MOLD_PROGRAM)
set(_custom_LINKER_FUSE_FLAG "-fuse-ld=mold")
else()
message(WARNING "Mold linker NOT found, disabling WITH_LINKER_MOLD")
set(WITH_LINKER_MOLD OFF)
endif()
endif()
if(_custom_LINKER_FUSE_FLAG)
add_link_options(${_custom_LINKER_FUSE_FLAG})
endif()
if(WITH_COMPILER_ASAN)
list(APPEND PLATFORM_BUNDLED_LIBRARIES ${COMPILER_ASAN_LIBRARY})
endif()

View File

@ -109,6 +109,10 @@ find_package_wrapper(ZLIB REQUIRED)
find_package_wrapper(Zstd REQUIRED)
find_package_wrapper(Epoxy REQUIRED)
# XXX Linking errors with debian static tiff :/
# find_package_wrapper(TIFF REQUIRED)
find_package(TIFF)
if(WITH_VULKAN_BACKEND)
find_package_wrapper(Vulkan REQUIRED)
find_package_wrapper(ShaderC REQUIRED)
@ -190,13 +194,6 @@ if(WITH_IMAGE_OPENJPEG)
set_and_warn_library_found("OpenJPEG" OPENJPEG_FOUND WITH_IMAGE_OPENJPEG)
endif()
if(WITH_IMAGE_TIFF)
# XXX Linking errors with debian static tiff :/
# find_package_wrapper(TIFF)
find_package(TIFF)
set_and_warn_library_found("TIFF" TIFF_FOUND WITH_IMAGE_TIFF)
endif()
if(WITH_OPENAL)
find_package_wrapper(OpenAL)
set_and_warn_library_found("OpenAL" OPENAL_FOUND WITH_OPENAL)
@ -818,64 +815,49 @@ if(CMAKE_COMPILER_IS_GNUCC)
string(PREPEND CMAKE_CXX_FLAGS_RELWITHDEBINFO "${GCC_EXTRA_FLAGS_RELEASE} ")
unset(GCC_EXTRA_FLAGS_RELEASE)
# NOTE(@campbellbarton): Eventually mold will be able to use `-fuse-ld=mold`,
# however at the moment this only works for GCC 12.1+ (unreleased at time of writing).
# So a workaround is used here "-B" which points to another path to find system commands
# such as `ld`.
if(WITH_LINKER_MOLD AND _IS_LINKER_DEFAULT)
find_program(MOLD_BIN "mold")
mark_as_advanced(MOLD_BIN)
if(NOT MOLD_BIN)
message(STATUS "The \"mold\" binary could not be found, using system linker.")
set(WITH_LINKER_MOLD OFF)
elseif(CMAKE_C_COMPILER_VERSION VERSION_LESS 12.1)
message(STATUS "GCC 12.1 or newer is required for th MOLD linker.")
set(WITH_LINKER_MOLD OFF)
else()
# By default mold installs the binary to:
# - `{PREFIX}/bin/mold` as well as a symbolic-link in...
# - `{PREFIX}/lib/mold/ld`.
# (where `PREFIX` is typically `/usr/`).
#
# This block of code finds `{PREFIX}/lib/mold` from the `mold` binary.
# Other methods of searching for the path could also be made to work,
# we could even make our own directory and symbolic-link, however it's more
# convenient to use the one provided by mold.
#
# Use the binary path to "mold", to find the common prefix which contains "lib/mold".
# The parent directory: e.g. `/usr/bin/mold` -> `/usr/bin/`.
get_filename_component(MOLD_PREFIX "${MOLD_BIN}" DIRECTORY)
# The common prefix path: e.g. `/usr/bin/` -> `/usr/` to use as a hint.
get_filename_component(MOLD_PREFIX "${MOLD_PREFIX}" DIRECTORY)
# Find `{PREFIX}/lib/mold/ld`, store the directory component (without the `ld`).
# Then pass `-B {PREFIX}/lib/mold` to GCC so the `ld` located there overrides the default.
find_path(
MOLD_BIN_DIR "ld"
HINTS "${MOLD_PREFIX}"
# The default path is `libexec`, Arch Linux for e.g.
# replaces this with `lib` so check both.
PATH_SUFFIXES "libexec/mold" "lib/mold" "lib64/mold"
NO_DEFAULT_PATH
NO_CACHE
get_filename_component(MOLD_BIN_DIR "${MOLD_BIN}" DIRECTORY)
# Check if the `-B` argument is required.
# This will happen when `MOLD_BIN` points to a non-standard location.
# Keep this option as mold is not yet a standard system component and
# users may have it installed in some unexpected place.
set(_mold_args "-fuse-ld=mold")
execute_process(
COMMAND ${CMAKE_C_COMPILER} -B ${MOLD_BIN_DIR} ${_mold_args} -Wl,--version
ERROR_QUIET OUTPUT_VARIABLE LD_VERSION_WITH_DIR
)
if(NOT MOLD_BIN_DIR)
message(STATUS
"The mold linker could not find the directory containing the linker command "
"(typically "
"\"${MOLD_PREFIX}/libexec/mold/ld\") or "
"\"${MOLD_PREFIX}/lib/mold/ld\") using system linker."
)
set(WITH_LINKER_MOLD OFF)
execute_process(
COMMAND ${CMAKE_C_COMPILER} ${_mold_args} -Wl,--version
ERROR_QUIET OUTPUT_VARIABLE LD_VERSION
)
if(NOT (LD_VERSION STREQUAL LD_VERSION_WITH_DIR))
string(PREPEND _mold_args "-B \"${MOLD_BIN_DIR}\" ")
set(LD_VERSION "${LD_VERSION_WITH_DIR}")
endif()
unset(MOLD_PREFIX)
endif()
if(WITH_LINKER_MOLD)
# GCC will search for `ld` in this directory first.
string(APPEND CMAKE_EXE_LINKER_FLAGS " -B \"${MOLD_BIN_DIR}\"")
string(APPEND CMAKE_SHARED_LINKER_FLAGS " -B \"${MOLD_BIN_DIR}\"")
string(APPEND CMAKE_MODULE_LINKER_FLAGS " -B \"${MOLD_BIN_DIR}\"")
set(_IS_LINKER_DEFAULT OFF)
if("${LD_VERSION}" MATCHES "mold ")
string(APPEND CMAKE_EXE_LINKER_FLAGS " ${_mold_args}")
string(APPEND CMAKE_SHARED_LINKER_FLAGS " ${_mold_args}")
string(APPEND CMAKE_MODULE_LINKER_FLAGS " ${_mold_args}")
set(_IS_LINKER_DEFAULT OFF)
else()
message(STATUS "GNU mold linker isn't available, using the default system linker.")
endif()
unset(_mold_args)
unset(MOLD_BIN_DIR)
unset(LD_VERSION)
endif()
unset(MOLD_BIN)
unset(MOLD_BIN_DIR)
endif()
if(WITH_LINKER_GOLD AND _IS_LINKER_DEFAULT)

View File

@ -487,14 +487,12 @@ if(WITH_IMAGE_OPENEXR)
endif()
endif()
if(WITH_IMAGE_TIFF)
# Try to find tiff first then complain and set static and maybe wrong paths
windows_find_package(TIFF)
if(NOT TIFF_FOUND)
warn_hardcoded_paths(libtiff)
set(TIFF_LIBRARY ${LIBDIR}/tiff/lib/libtiff.lib)
set(TIFF_INCLUDE_DIR ${LIBDIR}/tiff/include)
endif()
# Try to find tiff first then complain and set static and maybe wrong paths
windows_find_package(TIFF)
if(NOT TIFF_FOUND)
warn_hardcoded_paths(libtiff)
set(TIFF_LIBRARY ${LIBDIR}/tiff/lib/libtiff.lib)
set(TIFF_INCLUDE_DIR ${LIBDIR}/tiff/include)
endif()
if(WITH_JACK)

View File

@ -172,6 +172,8 @@ def system_info():
def list_render_passes(scene, srl):
import _cycles
crl = srl.cycles
# Combined pass.
@ -250,6 +252,12 @@ def list_render_passes(scene, srl):
for lightgroup in srl.lightgroups:
yield ("Combined_%s" % lightgroup.name, "RGB", 'COLOR')
# Path guiding debug passes.
if _cycles.with_debug:
yield ("Guiding Color", "RGB", 'COLOR')
yield ("Guiding Probability", "X", 'VALUE')
yield ("Guiding Average Roughness", "X", 'VALUE')
def register_passes(engine, scene, view_layer):
for name, channelids, channeltype in list_render_passes(scene, view_layer):

View File

@ -3,6 +3,7 @@
from __future__ import annotations
import bpy
from bpy.app.translations import contexts as i18n_contexts
from bpy_extras.node_utils import find_node_input
from bl_ui.utils import PresetPanel
@ -318,7 +319,7 @@ class CYCLES_RENDER_PT_sampling_path_guiding(CyclesButtonsPanel, Panel):
col = layout.column(align=True)
col.prop(cscene, "use_surface_guiding", text="Surface")
col.prop(cscene, "use_volume_guiding", text="Volume")
col.prop(cscene, "use_volume_guiding", text="Volume", text_ctxt=i18n_contexts.id_id)
class CYCLES_RENDER_PT_sampling_path_guiding_debug(CyclesDebugButtonsPanel, Panel):
@ -530,7 +531,7 @@ class CYCLES_RENDER_PT_light_paths_max_bounces(CyclesButtonsPanel, Panel):
col.prop(cscene, "diffuse_bounces", text="Diffuse")
col.prop(cscene, "glossy_bounces", text="Glossy")
col.prop(cscene, "transmission_bounces", text="Transmission")
col.prop(cscene, "volume_bounces", text="Volume")
col.prop(cscene, "volume_bounces", text="Volume", text_ctxt=i18n_contexts.id_id)
col = layout.column(align=True)
col.prop(cscene, "transparent_max_bounces", text="Transparent")
@ -980,7 +981,7 @@ class CYCLES_RENDER_PT_passes_light(CyclesButtonsPanel, Panel):
col.prop(view_layer, "use_pass_transmission_indirect", text="Indirect")
col.prop(view_layer, "use_pass_transmission_color", text="Color")
col = layout.column(heading="Volume", align=True)
col = layout.column(heading="Volume", heading_ctxt=i18n_contexts.id_id, align=True)
col.prop(cycles_view_layer, "use_pass_volume_direct", text="Direct")
col.prop(cycles_view_layer, "use_pass_volume_indirect", text="Indirect")
@ -1577,6 +1578,7 @@ class CYCLES_WORLD_PT_surface(CyclesButtonsPanel, Panel):
class CYCLES_WORLD_PT_volume(CyclesButtonsPanel, Panel):
bl_label = "Volume"
bl_translation_context = i18n_contexts.id_id
bl_context = "world"
bl_options = {'DEFAULT_CLOSED'}
@ -1696,6 +1698,7 @@ class CYCLES_WORLD_PT_settings_surface(CyclesButtonsPanel, Panel):
class CYCLES_WORLD_PT_settings_volume(CyclesButtonsPanel, Panel):
bl_label = "Volume"
bl_translation_context = i18n_contexts.id_id
bl_parent_id = "CYCLES_WORLD_PT_settings"
bl_context = "world"
@ -1791,6 +1794,7 @@ class CYCLES_MATERIAL_PT_surface(CyclesButtonsPanel, Panel):
class CYCLES_MATERIAL_PT_volume(CyclesButtonsPanel, Panel):
bl_label = "Volume"
bl_translation_context = i18n_contexts.id_id
bl_context = "material"
bl_options = {'DEFAULT_CLOSED'}
@ -1874,6 +1878,7 @@ class CYCLES_MATERIAL_PT_settings_surface(CyclesButtonsPanel, Panel):
class CYCLES_MATERIAL_PT_settings_volume(CyclesButtonsPanel, Panel):
bl_label = "Volume"
bl_translation_context = i18n_contexts.id_id
bl_parent_id = "CYCLES_MATERIAL_PT_settings"
bl_context = "material"

View File

@ -244,7 +244,7 @@ static void export_pointcloud_motion(PointCloud *pointcloud,
const int num_points = pointcloud->num_points();
/* Point cloud attributes are stored as float4 with the radius in the w element.
* This is explict now as float3 is no longer interchangeable with float4 as it
* This is explicit now as float3 is no longer interchangeable with float4 as it
* is packed now. */
float4 *mP = attr_mP->data_float4() + motion_step * num_points;
bool have_motion = false;

View File

@ -634,6 +634,10 @@ static bool get_known_pass_type(BL::RenderPass &b_pass, PassType &type, PassMode
MAP_PASS("AdaptiveAuxBuffer", PASS_ADAPTIVE_AUX_BUFFER, false);
MAP_PASS("Debug Sample Count", PASS_SAMPLE_COUNT, false);
MAP_PASS("Guiding Color", PASS_GUIDING_COLOR, false);
MAP_PASS("Guiding Probability", PASS_GUIDING_PROBABILITY, false);
MAP_PASS("Guiding Average Roughness", PASS_GUIDING_AVG_ROUGHNESS, false);
if (string_startswith(name, cryptomatte_prefix)) {
type = PASS_CRYPTOMATTE;
mode = PassMode::DENOISED;
@ -684,18 +688,6 @@ void BlenderSync::sync_render_passes(BL::RenderLayer &b_rlay, BL::ViewLayer &b_v
}
scene->film->set_cryptomatte_passes(cryptomatte_passes);
/* Path guiding debug passes. */
#ifdef WITH_CYCLES_DEBUG
b_engine.add_pass("Guiding Color", 3, "RGB", b_view_layer.name().c_str());
pass_add(scene, PASS_GUIDING_COLOR, "Guiding Color", PassMode::NOISY);
b_engine.add_pass("Guiding Probability", 1, "X", b_view_layer.name().c_str());
pass_add(scene, PASS_GUIDING_PROBABILITY, "Guiding Probability", PassMode::NOISY);
b_engine.add_pass("Guiding Average Roughness", 1, "X", b_view_layer.name().c_str());
pass_add(scene, PASS_GUIDING_AVG_ROUGHNESS, "Guiding Average Roughness", PassMode::NOISY);
#endif
unordered_set<string> expected_passes;
/* Custom AOV passes. */

View File

@ -1167,8 +1167,8 @@ BVHNode *BVHBuild::create_leaf_node(const BVHRange &range, const vector<BVHRefer
void BVHBuild::rotate(BVHNode *node, int max_depth, int iterations)
{
/* in tested scenes, this resulted in slightly slower raytracing, so disabled
* it for now. could be implementation bug, or depend on the scene */
/* In tested scenes, this resulted in slightly slower ray-tracing, so disabled
* it for now. could be implementation bug, or depend on the scene. */
if (node)
for (int i = 0; i < iterations; i++)
rotate(node, max_depth);

View File

@ -181,7 +181,7 @@ string OptiXDevice::compile_kernel_get_common_cflags(const uint kernel_features)
/* Add OptiX SDK include directory to include paths. */
common_cflags += string_printf(" -I\"%s\"", get_optix_include_dir().c_str());
/* Specialization for shader raytracing. */
/* Specialization for shader ray-tracing. */
if (kernel_features & KERNEL_FEATURE_NODE_RAYTRACE) {
common_cflags += " --keep-device-functions";
}
@ -483,7 +483,7 @@ bool OptiXDevice::load_kernels(const uint kernel_features)
group_descs[PG_HITL].hitgroup.entryFunctionNameAH = "__anyhit__kernel_optix_local_hit";
}
/* Shader raytracing replaces some functions with direct callables. */
/* Shader ray-tracing replaces some functions with direct callables. */
if (kernel_features & KERNEL_FEATURE_NODE_RAYTRACE) {
group_descs[PG_RGEN_SHADE_SURFACE_RAYTRACE].kind = OPTIX_PROGRAM_GROUP_KIND_RAYGEN;
group_descs[PG_RGEN_SHADE_SURFACE_RAYTRACE].raygen.module = optix_module;
@ -584,7 +584,7 @@ bool OptiXDevice::load_kernels(const uint kernel_features)
load_osl_kernels();
}
else if (kernel_features & (KERNEL_FEATURE_NODE_RAYTRACE | KERNEL_FEATURE_MNEE)) {
/* Create shader raytracing and MNEE pipeline. */
/* Create shader ray-tracing and MNEE pipeline. */
vector<OptixProgramGroup> pipeline_groups;
pipeline_groups.reserve(NUM_PROGRAM_GROUPS);
if (kernel_features & KERNEL_FEATURE_NODE_RAYTRACE) {

View File

@ -834,7 +834,7 @@ enum ShaderDataFlag {
SD_NEED_VOLUME_ATTRIBUTES = (1 << 28),
/* Shader has emission */
SD_HAS_EMISSION = (1 << 29),
/* Shader has raytracing */
/* Shader has ray-tracing. */
SD_HAS_RAYTRACE = (1 << 30),
/* Use back side for direct light sampling. */
SD_MIS_BACK = (1 << 31),

View File

@ -5890,7 +5890,7 @@ void SeparateHSVNode::compile(OSLCompiler &compiler)
compiler.add(this, "node_separate_hsv");
}
/* Hue Saturation Value */
/* Hue/Saturation/Value */
NODE_DEFINE(HSVNode)
{

View File

@ -204,7 +204,8 @@ GHOST_ContextEGL::GHOST_ContextEGL(const GHOST_System *const system,
m_swap_interval(1),
m_sharedContext(
choose_api(api, s_gl_sharedContext, s_gles_sharedContext, s_vg_sharedContext)),
m_sharedCount(choose_api(api, s_gl_sharedCount, s_gles_sharedCount, s_vg_sharedCount))
m_sharedCount(choose_api(api, s_gl_sharedCount, s_gles_sharedCount, s_vg_sharedCount)),
m_surface_from_native_window(false)
{
}
@ -454,6 +455,7 @@ GHOST_TSuccess GHOST_ContextEGL::initializeDrawingContext()
if (m_nativeWindow != 0) {
m_surface = ::eglCreateWindowSurface(m_display, m_config, m_nativeWindow, nullptr);
m_surface_from_native_window = true;
}
else {
static const EGLint pb_attrib_list[] = {
@ -598,8 +600,12 @@ error:
GHOST_TSuccess GHOST_ContextEGL::releaseNativeHandles()
{
m_nativeWindow = 0;
m_nativeDisplay = nullptr;
m_nativeWindow = 0;
if (m_surface_from_native_window) {
m_surface = EGL_NO_SURFACE;
}
return GHOST_kSuccess;
}

View File

@ -122,6 +122,11 @@ class GHOST_ContextEGL : public GHOST_Context {
EGLContext &m_sharedContext;
EGLint &m_sharedCount;
/**
* True when the surface is created from `m_nativeWindow`.
*/
bool m_surface_from_native_window;
static EGLContext s_gl_sharedContext;
static EGLint s_gl_sharedCount;

View File

@ -1400,7 +1400,9 @@ bool GHOST_SystemCocoa::handleOpenDocumentRequest(void *filepathStr)
[[windowsList objectAtIndex:0] makeKeyAndOrderFront:nil];
}
GHOST_Window *window = (GHOST_Window *)m_windowManager->getActiveWindow();
GHOST_Window *window = m_windowManager->getWindows().empty() ?
NULL :
(GHOST_Window *)m_windowManager->getWindows().front();
if (!window) {
return NO;

View File

@ -6339,14 +6339,15 @@ GHOST_TSuccess GHOST_SystemWayland::disposeContext(GHOST_IContext *context)
#ifdef USE_EVENT_BACKGROUND_THREAD
std::lock_guard lock_server_guard{*server_mutex};
#endif
struct wl_surface *wl_surface = (struct wl_surface *)((GHOST_Context *)context)->getUserData();
/* Delete the context before the window so the context is able to release
* native resources (such as the #EGLSurface) before WAYLAND frees them. */
delete context;
wl_egl_window *egl_window = (wl_egl_window *)wl_surface_get_user_data(wl_surface);
wl_egl_window_destroy(egl_window);
wl_surface_destroy(wl_surface);
delete context;
return GHOST_kSuccess;
}

View File

@ -2157,7 +2157,7 @@ char *GHOST_SystemX11::getClipboard(bool selection) const
Atom target = m_atom.UTF8_STRING;
Window owner;
/* from xclip.c doOut() v0.11 */
/* From `xclip.c` `doOut()` v0.11. */
char *sel_buf;
ulong sel_len = 0;
XEvent evt;
@ -2614,13 +2614,13 @@ static bool match_token(const char *haystack, const char *needle)
/* Determining if an X device is a Tablet style device is an imperfect science.
* We rely on common conventions around device names as well as the type reported
* by Wacom tablets. This code will likely need to be expanded for alternate tablet types
* by WACOM tablets. This code will likely need to be expanded for alternate tablet types
*
* Wintab refers to any device that interacts with the tablet as a cursor,
* WINTAB refers to any device that interacts with the tablet as a cursor,
* (stylus, eraser, tablet mouse, airbrush, etc)
* this is not to be confused with wacom x11 configuration "cursor" device.
* Wacoms x11 config "cursor" refers to its device slot (which we mirror with
* our gSysCursors) for puck like devices (tablet mice essentially).
* this is not to be confused with WACOM X11 configuration "cursor" device.
* WACOM tablets X11 configuration "cursor" refers to its device slot (which we mirror with
* our `gSysCursors`) for puck like devices (tablet mice essentially).
*/
static GHOST_TTabletMode tablet_mode_from_name(const char *name, const char *type)
{

View File

@ -138,8 +138,6 @@ enum eGWL_PendingWindowActions {
* The state of the window frame has changed, apply the state from #GWL_Window::frame_pending.
*/
PENDING_WINDOW_FRAME_CONFIGURE = 0,
/** The EGL buffer must be resized to match #GWL_WindowFrame::size. */
PENDING_EGL_WINDOW_RESIZE,
# ifdef GHOST_OPENGL_ALPHA
/** Draw an opaque region behind the window. */
PENDING_OPAQUE_SET,
@ -150,7 +148,17 @@ enum eGWL_PendingWindowActions {
*/
PENDING_OUTPUT_SCALE_UPDATE,
PENDING_WINDOW_SURFACE_SCALE,
/**
* Workaround for a bug/glitch in WLROOTS based compositors (RIVER for e.g.).
* Deferring the scale update one even-loop cycle resolves a bug
* where the output enter/exit events cause the surface buffer being an invalid size.
*
* While these kinds of glitches might be ignored in some cases,
* this caused newly created windows to immediately loose the connection to WAYLAND
* (crashing from a user perspective).
*/
PENDING_OUTPUT_SCALE_UPDATE_DEFERRED,
/**
* The surface needs a commit to run.
* Use this to avoid committing immediately which can cause flickering when other operations
@ -669,20 +677,20 @@ static void gwl_window_pending_actions_handle(GWL_Window *win)
if (actions[PENDING_WINDOW_FRAME_CONFIGURE]) {
gwl_window_frame_update_from_pending(win);
}
if (actions[PENDING_EGL_WINDOW_RESIZE]) {
wl_egl_window_resize(win->egl_window, UNPACK2(win->frame.size), 0, 0);
}
# ifdef GHOST_OPENGL_ALPHA
if (actions[PENDING_OPAQUE_SET]) {
win->ghost_window->setOpaque();
}
# endif
if (actions[PENDING_OUTPUT_SCALE_UPDATE_DEFERRED]) {
gwl_window_pending_actions_tag(win, PENDING_OUTPUT_SCALE_UPDATE);
/* Force postponing scale update to ensure all scale information has been taken into account
* before the actual update is performed. Failing to do so tends to cause flickering. */
actions[PENDING_OUTPUT_SCALE_UPDATE] = false;
}
if (actions[PENDING_OUTPUT_SCALE_UPDATE]) {
win->ghost_window->outputs_changed_update_scale();
}
if (actions[PENDING_WINDOW_SURFACE_SCALE]) {
wl_surface_set_buffer_scale(win->wl_surface, win->frame.buffer_scale);
}
if (actions[PENDING_WINDOW_SURFACE_COMMIT]) {
wl_surface_commit(win->wl_surface);
}
@ -727,19 +735,11 @@ static void gwl_window_frame_update_from_pending_no_lock(GWL_Window *win)
}
if (surface_needs_egl_resize) {
#ifdef USE_EVENT_BACKGROUND_THREAD
gwl_window_pending_actions_tag(win, PENDING_EGL_WINDOW_RESIZE);
#else
wl_egl_window_resize(win->egl_window, UNPACK2(win->frame.size), 0, 0);
#endif
}
if (surface_needs_buffer_scale) {
#ifdef USE_EVENT_BACKGROUND_THREAD
gwl_window_pending_actions_tag(win, PENDING_WINDOW_SURFACE_SCALE);
#else
wl_surface_set_buffer_scale(win->wl_surface, win->frame.buffer_scale);
#endif
}
if (surface_needs_commit) {
@ -1936,7 +1936,10 @@ GHOST_TSuccess GHOST_WindowWayland::notify_decor_redraw()
void GHOST_WindowWayland::outputs_changed_update_scale_tag()
{
#ifdef USE_EVENT_BACKGROUND_THREAD
gwl_window_pending_actions_tag(window_, PENDING_OUTPUT_SCALE_UPDATE);
/* NOTE: if deferring causes problems, it could be isolated to the first scale initialization
* See: #GWL_WindowFrame::is_scale_init. */
gwl_window_pending_actions_tag(window_, PENDING_OUTPUT_SCALE_UPDATE_DEFERRED);
#else
outputs_changed_update_scale();
#endif
@ -1975,16 +1978,6 @@ bool GHOST_WindowWayland::outputs_changed_update_scale()
fractional_scale_next = fractional_scale_from_output;
scale_next = fractional_scale_next / FRACTIONAL_DENOMINATOR;
}
else {
/* NOTE(@ideasman42): This often overrides #wp_fractional_scale_v1_listener::preferred_scale
* in favor of using the greatest overlapping scale.
* This was requested by the studio to prevent a tablet's built-in display of 75%
* from causing the main-display being up-scaled (showing pixelated). */
if (fractional_scale_next < fractional_scale_from_output) {
fractional_scale_next = fractional_scale_from_output;
scale_next = fractional_scale_next / FRACTIONAL_DENOMINATOR;
}
}
bool changed = false;

View File

@ -123,7 +123,7 @@ def expand(line, cursor, namespace, *, private=True):
[white_space + m[len(word_prefix):]
if (word_prefix and m.startswith(word_prefix))
else
white_space + m.split('.')[-1]
white_space + m.rsplit('.', 1)[-1]
for m in matches])
no_calltip = True

View File

@ -28,7 +28,7 @@ def rna_backup_gen(data, include_props=None, exclude_props=None, root=()):
# only writable properties...
for p in data.bl_rna.properties:
pid = p.identifier
if pid == "rna_type" or pid == "original":
if pid in {"rna_type", "original"}:
continue
path = root + (pid,)
if include_props is not None and path not in include_props:

View File

@ -355,7 +355,7 @@ def script_paths(*, subdir=None, user_pref=True, check_all=False, use_user=True)
:arg subdir: Optional subdir.
:type subdir: string
:arg user_pref: Include the user preference script path.
:arg user_pref: Include the user preference script paths.
:type user_pref: bool
:arg check_all: Include local, user and system paths rather just the paths Blender uses.
:type check_all: bool
@ -387,6 +387,9 @@ def script_paths(*, subdir=None, user_pref=True, check_all=False, use_user=True)
if use_user:
base_paths.append(path_user)
if user_pref:
base_paths.extend(script_paths_pref())
scripts = []
for path in base_paths:
if not path:

View File

@ -94,9 +94,7 @@ def keyconfig_test(kc):
if testEntry(kc, child, src, parent):
result = True
else:
for i in range(len(km.keymap_items)):
src = km.keymap_items[i]
for i, src in enumerate(km.keymap_items):
for child in children:
if testEntry(kc, child, src, km):
result = True

View File

@ -417,7 +417,7 @@ def ngon_tessellate(from_data, indices, fix_loops=True, debug_print=True):
if not flip:
for i, fi in enumerate(fill):
fill[i] = tuple([ii for ii in reversed(fi)])
fill[i] = tuple(reversed(fi))
return fill

View File

@ -5,6 +5,44 @@ __all__ = (
)
def connect_sockets(input, output):
"""
Connect sockets in a node tree.
This is useful because the links created through the normal Python API are
invalid when one of the sockets is a virtual socket (grayed out sockets in
Group Input and Group Output nodes).
It replaces node_tree.links.new(input, output)
"""
import bpy
# Swap sockets if they are not passed in the proper order
if input.is_output and not output.is_output:
input, output = output, input
input_node = output.node
output_node = input.node
if input_node.id_data is not output_node.id_data:
print("Sockets do not belong to the same node tree")
return
if type(input) == type(output) == bpy.types.NodeSocketVirtual:
print("Cannot connect two virtual sockets together")
return
if output_node.type == 'GROUP_OUTPUT' and type(input) == bpy.types.NodeSocketVirtual:
output_node.id_data.outputs.new(type(output).__name__, output.name)
input = output_node.inputs[-2]
if input_node.type == 'GROUP_INPUT' and type(output) == bpy.types.NodeSocketVirtual:
output_node.id_data.inputs.new(type(input).__name__, input.name)
output = input_node.outputs[-2]
return input_node.id_data.links.new(input, output)
# XXX Names are not unique. Returns the first match.
def find_node_input(node, name):
for input in node.inputs:

View File

@ -580,7 +580,6 @@ class Mesh(bpy_types.ID):
vertex_indices = tuple(chain.from_iterable(faces))
loop_starts = tuple(islice(chain([0], accumulate(face_lengths)), faces_len))
self.polygons.foreach_set("loop_total", face_lengths)
self.polygons.foreach_set("loop_start", loop_starts)
self.polygons.foreach_set("vertices", vertex_indices)

View File

@ -5600,9 +5600,13 @@ def km_font(params):
("font.move_select", {"type": 'PAGE_DOWN', "value": 'PRESS', "shift": True, "repeat": True},
{"properties": [("type", 'NEXT_PAGE')]}),
("font.change_spacing", {"type": 'LEFT_ARROW', "value": 'PRESS', "alt": True, "repeat": True},
{"properties": [("delta", -1)]}),
{"properties": [("delta", -1.0)]}),
("font.change_spacing", {"type": 'RIGHT_ARROW', "value": 'PRESS', "alt": True, "repeat": True},
{"properties": [("delta", 1)]}),
{"properties": [("delta", 1.0)]}),
("font.change_spacing", {"type": 'LEFT_ARROW', "value": 'PRESS', "shift": True, "alt": True, "repeat": True},
{"properties": [("delta", -0.1)]}),
("font.change_spacing", {"type": 'RIGHT_ARROW', "value": 'PRESS', "shift": True, "alt": True, "repeat": True},
{"properties": [("delta", 0.1)]}),
("font.change_character", {"type": 'UP_ARROW', "value": 'PRESS', "alt": True, "repeat": True},
{"properties": [("delta", 1)]}),
("font.change_character", {"type": 'DOWN_ARROW', "value": 'PRESS', "alt": True, "repeat": True},

View File

@ -242,7 +242,6 @@ class AddTorus(Operator, object_utils.AddObjectHelper):
mesh.vertices.foreach_set("co", verts_loc)
mesh.polygons.foreach_set("loop_start", range(0, nbr_loops, 4))
mesh.polygons.foreach_set("loop_total", (4,) * nbr_polys)
mesh.loops.foreach_set("vertex_index", faces)
if self.generate_uvs:

View File

@ -239,7 +239,6 @@ def find_next(ele_dst, ele_src):
# expose for operators
def select_next(bm, report):
import bmesh
ele_pair = [None, None]
for i, ele in enumerate(reversed(bm.select_history)):
ele_pair[i] = ele

View File

@ -488,7 +488,7 @@ class CLIP_OT_constraint_to_fcurve(Operator):
efra = max(efra, track.markers[-1].frame)
if sfra is None or efra is None:
return
return {'CANCELLED'}
# Store object matrices.
for x in range(sfra, efra + 1):
@ -516,6 +516,8 @@ class CLIP_OT_constraint_to_fcurve(Operator):
scene.frame_set(frame_current)
return {'FINISHED'}
def execute(self, context):
scene = context.scene
# XXX, should probably use context.selected_editable_objects
@ -662,8 +664,7 @@ class CLIP_OT_setup_tracking_scene(Operator):
if collection.collection.name == collection_name:
setattr(collection, attr_name, True)
break
else:
setup_collection_recursively(collection.children, collection_name, attr_name)
setup_collection_recursively(collection.children, collection_name, attr_name)
collections = context.scene.collection.children
vlayers = context.scene.view_layers
@ -868,7 +869,6 @@ class CLIP_OT_setup_tracking_scene(Operator):
mesh.polygons.add(nbr_polys)
mesh.polygons.foreach_set("loop_start", range(0, nbr_loops, 4))
mesh.polygons.foreach_set("loop_total", (4,) * nbr_polys)
mesh.loops.foreach_set("vertex_index", faces)
mesh.update()

View File

@ -101,9 +101,9 @@ class MeshMirrorUV(Operator):
for i, j in pmap.items():
if not puvsel[i] or not puvsel[j]:
continue
elif DIR == 0 and pcents[i][0] < 0.0:
if DIR == 0 and pcents[i][0] < 0.0:
continue
elif DIR == 1 and pcents[i][0] > 0.0:
if DIR == 1 and pcents[i][0] > 0.0:
continue
# copy UVs

View File

@ -9,8 +9,6 @@ from bpy.types import (
from bpy.props import (
BoolProperty,
CollectionProperty,
EnumProperty,
IntProperty,
StringProperty,
)

View File

@ -618,7 +618,6 @@ class MakeDupliFace(Operator):
mesh.vertices.foreach_set("co", face_verts)
mesh.loops.foreach_set("vertex_index", faces)
mesh.polygons.foreach_set("loop_start", range(0, nbr_faces * 4, 4))
mesh.polygons.foreach_set("loop_total", (4,) * nbr_faces)
mesh.update() # generates edge data
ob_new = bpy.data.objects.new(mesh.name, mesh)

View File

@ -121,8 +121,16 @@ class QuickFur(ObjectModeOperator, Operator):
material = bpy.data.materials.new("Fur Material")
mesh_with_zero_area = False
mesh_missing_uv_map = False
modifier_apply_error = False
for mesh_object in mesh_objects: