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
1547 changed files with 24492 additions and 11792 deletions
Showing only changes of commit 533f8cbce7 - Show all commits

View File

@ -47,6 +47,7 @@ set(OPENIMAGEIO_EXTRA_ARGS
-DBUILD_SHARED_LIBS=ON
${OPENIMAGEIO_LINKSTATIC}
${DEFAULT_BOOST_FLAGS}
-DREQUIRED_DEPS=WebP$<SEMICOLON>JPEGTurbo$<SEMICOLON>TIFF$<SEMICOLON>OpenEXR$<SEMICOLON>PNG$<SEMICOLON>OpenJPEG$<SEMICOLON>fmt$<SEMICOLON>Robinmap$<SEMICOLON>ZLIB$<SEMICOLON>pugixml$<SEMICOLON>Python
-DUSE_LIBSQUISH=OFF
-DUSE_QT5=OFF
-DUSE_NUKE=OFF

View File

@ -1,31 +1,50 @@
diff --git a/src/cmake/modules/FindWebP.cmake b/src/cmake/modules/FindWebP.cmake
index 87b880a..0e9850f 100644
--- a/src/cmake/modules/FindWebP.cmake
+++ b/src/cmake/modules/FindWebP.cmake
@@ -29,6 +29,12 @@ find_library (WEBPDEMUX_LIBRARY webpdemux
diff -Naur oiio-2.4.15.0/src/cmake/modules/FindWebP.cmake external_openimageio/src/cmake/modules/FindWebP.cmake
--- oiio-2.4.15.0/src/cmake/modules/FindWebP.cmake 2023-09-01 10:48:29.000000000 -0600
+++ external_openimageio/src/cmake/modules/FindWebP.cmake 2023-09-21 14:47:19.366083900 -0600
@@ -25,15 +25,30 @@
ENV WEBP_INCLUDE_PATH
DOC "The directory where Webp headers reside")
-find_library (WEBP_LIBRARY webp
+find_library (WEBP_LIBRARY
+ NAMES
+ webp
+ libwebp
HINTS
${WEBP_LIBRARY_PATH}
ENV WEBP_LIBRARY_PATH)
+# New in WebP 1.3
+find_library (WEBP_SHARPYUV_LIBRARY sharpyuv
-find_library (WEBPDEMUX_LIBRARY webpdemux
+find_library (WEBPDEMUX_LIBRARY
+ NAMES
+ webpdemux
+ libwebpdemux
+ HINTS
+ ${WEBP_LIBRARY_PATH}
+ ENV WEBP_LIBRARY_PATH)
+
+# New in WebP 1.3
+find_library (WEBP_SHARPYUV_LIBRARY
+ NAMES
+ sharpyuv
+ libsharpyuv
HINTS
${WEBP_LIBRARY_PATH}
ENV WEBP_LIBRARY_PATH)
+
include (FindPackageHandleStandardArgs)
find_package_handle_standard_args (WebP
@@ -38,7 +44,7 @@ find_package_handle_standard_args (WebP
REQUIRED_VARS WEBP_INCLUDE_DIR
@@ -42,7 +57,7 @@
if (WebP_FOUND)
set (WEBP_INCLUDES "${WEBP_INCLUDE_DIR}")
- set (WEBP_LIBRARIES ${WEBP_LIBRARY} ${WEBPDEMUX_LIBRARY})
+ set (WEBP_LIBRARIES ${WEBP_LIBRARY} ${WEBPDEMUX_LIBRARY} ${WEBP_SHARPYUV_LIBRARY})
if (NOT TARGET WebP::WebP)
add_library(WebP::WebP UNKNOWN IMPORTED)
@@ -54,10 +60,18 @@ if (WebP_FOUND)
set_property(TARGET WebP::WebPDemux APPEND PROPERTY
if (NOT TARGET WebP::webp)
add_library(WebP::webp UNKNOWN IMPORTED)
@@ -58,10 +73,18 @@
set_property(TARGET WebP::webpdemux APPEND PROPERTY
IMPORTED_LOCATION ${WEBPDEMUX_LIBRARY})
endif ()
+ if (WEBP_SHARPYUV_LIBRARY AND NOT TARGET WebP::sharpyuv)

View File

@ -85,7 +85,6 @@ set(_CLANG_FIND_COMPONENTS
clangAST
clangLex
clangBasic
clangSupport
)
set(_CLANG_LIBRARIES)

View File

@ -379,6 +379,7 @@ endif()
if(WITH_USD)
find_package_wrapper(USD)
set_and_warn_library_found("USD" USD_FOUND WITH_USD)
set_and_warn_library_found("Hydra" USD_FOUND WITH_HYDRA)
endif()
add_bundled_libraries(usd/lib)

View File

@ -388,7 +388,20 @@ endif()
if(WITH_IMAGE_WEBP)
set(WEBP_INCLUDE_DIRS ${LIBDIR}/webp/include)
set(WEBP_ROOT_DIR ${LIBDIR}/webp)
set(WEBP_LIBRARIES ${LIBDIR}/webp/lib/webp.lib ${LIBDIR}/webp/lib/webpdemux.lib ${LIBDIR}/webp/lib/webpmux.lib)
if(EXISTS ${LIBDIR}/webp/lib/libsharpyuv.lib) # webp 1.3.x+
set(WEBP_LIBRARIES
${LIBDIR}/webp/lib/libwebp.lib
${LIBDIR}/webp/lib/libwebpdemux.lib
${LIBDIR}/webp/lib/libwebpmux.lib
${LIBDIR}/webp/lib/libsharpyuv.lib
)
else()
set(WEBP_LIBRARIES
${LIBDIR}/webp/lib/webp.lib
${LIBDIR}/webp/lib/webpdemux.lib
${LIBDIR}/webp/lib/webpmux.lib
)
endif()
set(WEBP_FOUND ON)
endif()

View File

@ -38,7 +38,7 @@ PROJECT_NAME = Blender
# could be handy for archiving the generated documentation or if some version
# control system is used.
PROJECT_NUMBER = V4.0
PROJECT_NUMBER = V4.1
# Using the PROJECT_BRIEF tag one can provide an optional one line description
# for a project that appears at the top of each page and should give viewer a

View File

@ -16,6 +16,9 @@ class CustomHydraRenderEngine(bpy.types.HydraRenderEngine):
# Name of the render plugin.
bl_delegate_id = "HdCustomRendererPlugin"
# Use MaterialX instead of UsdPreviewSurface for materials.
bl_use_materialx = True
# Register path to plugin.
@classmethod
def register(cls):

View File

@ -375,7 +375,8 @@ class CYCLES_RENDER_PT_sampling_advanced(CyclesButtonsPanel, Panel):
layout.separator()
heading = layout.column(align=True, heading="Scrambling Distance")
heading.active = cscene.sampling_pattern == 'TABULATED_SOBOL'
# Tabulated Sobol is used when the debug UI is turned off.
heading.active = cscene.sampling_pattern == 'TABULATED_SOBOL' or not CyclesDebugButtonsPanel.poll(context)
heading.prop(cscene, "auto_scrambling_distance", text="Automatic")
heading.prop(cscene, "preview_scrambling_distance", text="Viewport")
heading.prop(cscene, "scrambling_distance", text="Multiplier")
@ -1367,10 +1368,14 @@ class CYCLES_OBJECT_PT_light_linking(CyclesButtonsPanel, Panel):
row = layout.row()
col = row.column()
col.template_light_linking_collection(light_linking, "receiver_collection")
col.template_light_linking_collection(row, light_linking, "receiver_collection")
col = row.column()
sub = col.column(align=True)
prop = sub.operator("object.light_linking_receivers_link", icon='ADD', text="")
prop.link_state = 'INCLUDE'
sub.operator("object.light_linking_unlink_from_collection", icon='REMOVE', text="")
sub = col.column()
sub.menu("CYCLES_OBJECT_MT_light_linking_context_menu", icon='DOWNARROW_HLT', text="")
@ -1399,10 +1404,14 @@ class CYCLES_OBJECT_PT_shadow_linking(CyclesButtonsPanel, Panel):
row = layout.row()
col = row.column()
col.template_light_linking_collection(light_linking, "blocker_collection")
col.template_light_linking_collection(row, light_linking, "blocker_collection")
col = row.column()
sub = col.column(align=True)
prop = sub.operator("object.light_linking_blockers_link", icon='ADD', text="")
prop.link_state = 'INCLUDE'
sub.operator("object.light_linking_unlink_from_collection", icon='REMOVE', text="")
sub = col.column()
sub.menu("CYCLES_OBJECT_MT_shadow_linking_context_menu", icon='DOWNARROW_HLT', text="")

View File

@ -222,10 +222,12 @@ struct ObjectKey {
ObjectKey(void *parent_, int id_[OBJECT_PERSISTENT_ID_SIZE], void *ob_, bool use_particle_hair_)
: parent(parent_), ob(ob_), use_particle_hair(use_particle_hair_)
{
if (id_)
if (id_) {
memcpy(id, id_, sizeof(id));
else
}
else {
memset(id, 0, sizeof(id));
}
}
bool operator<(const ObjectKey &k) const
@ -285,19 +287,23 @@ struct ParticleSystemKey {
ParticleSystemKey(void *ob_, int id_[OBJECT_PERSISTENT_ID_SIZE]) : ob(ob_)
{
if (id_)
if (id_) {
memcpy(id, id_, sizeof(id));
else
}
else {
memset(id, 0, sizeof(id));
}
}
bool operator<(const ParticleSystemKey &k) const
{
/* first id is particle index, we don't compare that */
if (ob < k.ob)
if (ob < k.ob) {
return true;
else if (ob == k.ob)
}
else if (ob == k.ob) {
return memcmp(id + 1, k.id + 1, sizeof(int) * (OBJECT_PERSISTENT_ID_SIZE - 1)) < 0;
}
return false;
}

View File

@ -537,12 +537,12 @@ static ShaderNode *add_node(Scene *scene,
case BL::ShaderNodeSubsurfaceScattering::falloff_BURLEY:
subsurface->set_method(CLOSURE_BSSRDF_BURLEY_ID);
break;
case BL::ShaderNodeSubsurfaceScattering::falloff_RANDOM_WALK_FIXED_RADIUS:
subsurface->set_method(CLOSURE_BSSRDF_RANDOM_WALK_FIXED_RADIUS_ID);
break;
case BL::ShaderNodeSubsurfaceScattering::falloff_RANDOM_WALK:
subsurface->set_method(CLOSURE_BSSRDF_RANDOM_WALK_ID);
break;
case BL::ShaderNodeSubsurfaceScattering::falloff_RANDOM_WALK_SKIN:
subsurface->set_method(CLOSURE_BSSRDF_RANDOM_WALK_SKIN_ID);
break;
}
node = subsurface;
@ -651,12 +651,12 @@ static ShaderNode *add_node(Scene *scene,
case BL::ShaderNodeBsdfPrincipled::subsurface_method_BURLEY:
principled->set_subsurface_method(CLOSURE_BSSRDF_BURLEY_ID);
break;
case BL::ShaderNodeBsdfPrincipled::subsurface_method_RANDOM_WALK_FIXED_RADIUS:
principled->set_subsurface_method(CLOSURE_BSSRDF_RANDOM_WALK_FIXED_RADIUS_ID);
break;
case BL::ShaderNodeBsdfPrincipled::subsurface_method_RANDOM_WALK:
principled->set_subsurface_method(CLOSURE_BSSRDF_RANDOM_WALK_ID);
break;
case BL::ShaderNodeBsdfPrincipled::subsurface_method_RANDOM_WALK_SKIN:
principled->set_subsurface_method(CLOSURE_BSSRDF_RANDOM_WALK_SKIN_ID);
break;
}
node = principled;
}

View File

@ -355,8 +355,14 @@ void BlenderSync::sync_integrator(BL::ViewLayer &b_view_layer, bool background)
scene->light_manager->tag_update(scene, LightManager::UPDATE_ALL);
}
SamplingPattern sampling_pattern = (SamplingPattern)get_enum(
cscene, "sampling_pattern", SAMPLING_NUM_PATTERNS, SAMPLING_PATTERN_TABULATED_SOBOL);
SamplingPattern sampling_pattern;
if (use_developer_ui) {
sampling_pattern = (SamplingPattern)get_enum(
cscene, "sampling_pattern", SAMPLING_NUM_PATTERNS, SAMPLING_PATTERN_TABULATED_SOBOL);
}
else {
sampling_pattern = SAMPLING_PATTERN_TABULATED_SOBOL;
}
integrator->set_sampling_pattern(sampling_pattern);
int samples = 1;

View File

@ -479,8 +479,9 @@ static inline string get_string(PointerRNA &ptr, const char *name)
char cstrbuf[1024];
char *cstr = RNA_string_get_alloc(&ptr, name, cstrbuf, sizeof(cstrbuf), NULL);
string str(cstr);
if (cstr != cstrbuf)
if (cstr != cstrbuf) {
MEM_freeN(cstr);
}
return str;
}
@ -501,8 +502,9 @@ static inline string blender_absolute_path(BL::BlendData &b_data, BL::ID &b_id,
BL::ID b_library_id(b_id.library());
dirname = blender_absolute_path(b_data, b_library_id, b_id.library().filepath());
}
else
else {
dirname = b_data.filepath();
}
return path_join(path_dirname(dirname), path.substr(2));
}
@ -535,12 +537,15 @@ static inline void mesh_texture_space(const ::Mesh &b_mesh, float3 &loc, float3
loc = make_float3(texspace_location[0], texspace_location[1], texspace_location[2]);
size = make_float3(texspace_size[0], texspace_size[1], texspace_size[2]);
if (size.x != 0.0f)
if (size.x != 0.0f) {
size.x = 0.5f / size.x;
if (size.y != 0.0f)
}
if (size.y != 0.0f) {
size.y = 0.5f / size.y;
if (size.z != 0.0f)
}
if (size.z != 0.0f) {
size.z = 0.5f / size.z;
}
loc = loc * size - make_float3(0.5f, 0.5f, 0.5f);
}

View File

@ -814,14 +814,14 @@ BVHNode *BVHBuild::build_node(const BVHRange &range,
BVHMixedSplit unaligned_split;
float unalignedSplitSAH = FLT_MAX;
/* float unalignedLeafSAH = FLT_MAX; */
// float unalignedLeafSAH = FLT_MAX;
Transform aligned_space;
bool do_unalinged_split = false;
if (params.use_unaligned_nodes && splitSAH > params.unaligned_split_threshold * leafSAH) {
aligned_space = unaligned_heuristic.compute_aligned_space(range, &references.at(0));
unaligned_split = BVHMixedSplit(
this, storage, range, references, level, &unaligned_heuristic, &aligned_space);
/* unalignedLeafSAH = params.sah_primitive_cost * split.leafSAH; */
// unalignedLeafSAH = params.sah_primitive_cost * split.leafSAH;
unalignedSplitSAH = params.sah_node_cost * unaligned_split.bounds.half_area() +
params.sah_primitive_cost * unaligned_split.nodeSAH;
/* TODO(sergey): Check we can create leaf already. */

View File

@ -18,7 +18,6 @@ class BVHMetal : public BVH {
public:
API_AVAILABLE(macos(11.0))
id<MTLAccelerationStructure> accel_struct = nil;
bool accel_struct_building = false;
API_AVAILABLE(macos(11.0))
vector<id<MTLAccelerationStructure>> blas_array;

View File

@ -23,6 +23,92 @@ CCL_NAMESPACE_BEGIN
metal_printf("%s\n", str.c_str()); \
}
//# define BVH_THROTTLE_DIAGNOSTICS
# ifdef BVH_THROTTLE_DIAGNOSTICS
# define bvh_throttle_printf(...) printf("BVHMetalBuildThrottler::" __VA_ARGS__)
# else
# define bvh_throttle_printf(...)
# endif
/* Limit the number of concurrent BVH builds so that we don't approach unsafe GPU working set
* sizes. */
struct BVHMetalBuildThrottler {
thread_mutex mutex;
size_t wired_memory = 0;
size_t safe_wired_limit = 0;
int requests_in_flight = 0;
BVHMetalBuildThrottler()
{
/* The default device will always be the one that supports MetalRT if the machine supports it.
*/
id<MTLDevice> mtlDevice = MTLCreateSystemDefaultDevice();
/* Set a conservative limit, but which will still only throttle in extreme cases. */
safe_wired_limit = [mtlDevice recommendedMaxWorkingSetSize] / 4;
bvh_throttle_printf("safe_wired_limit = %zu\n", safe_wired_limit);
}
/* Block until we're safely able to wire the requested resources. */
void acquire(size_t bytes_to_be_wired)
{
bool throttled = false;
while (true) {
{
thread_scoped_lock lock(mutex);
/* Always allow a BVH build to proceed if no other is in flight, otherwise
* only proceed if we're within safe limits. */
if (wired_memory == 0 || wired_memory + bytes_to_be_wired <= safe_wired_limit) {
wired_memory += bytes_to_be_wired;
requests_in_flight += 1;
bvh_throttle_printf("acquire -- success (requests_in_flight = %d, wired_memory = %zu)\n",
requests_in_flight,
wired_memory);
return;
}
if (!throttled) {
bvh_throttle_printf(
"acquire -- throttling (requests_in_flight = %d, wired_memory = %zu, "
"bytes_to_be_wired = %zu)\n",
requests_in_flight,
wired_memory,
bytes_to_be_wired);
}
throttled = true;
}
std::this_thread::sleep_for(std::chrono::milliseconds(10));
}
}
/* Notify of resources that have stopped being wired. */
void release(size_t bytes_just_unwired)
{
thread_scoped_lock lock(mutex);
wired_memory -= bytes_just_unwired;
requests_in_flight -= 1;
bvh_throttle_printf("release (requests_in_flight = %d, wired_memory = %zu)\n",
requests_in_flight,
wired_memory);
}
/* Wait for all outstanding work to finish. */
void wait_for_all()
{
while (true) {
{
thread_scoped_lock lock(mutex);
if (wired_memory == 0) {
return;
}
}
std::this_thread::sleep_for(std::chrono::milliseconds(10));
}
}
} g_bvh_build_throttler;
BVHMetal::BVHMetal(const BVHParams &params_,
const vector<Geometry *> &geometry_,
const vector<Object *> &objects_,
@ -204,6 +290,12 @@ bool BVHMetal::build_BLAS_mesh(Progress &progress,
sizeDataType:MTLDataTypeULong];
}
[accelEnc endEncoding];
/* Estimated size of resources that will be wired for the GPU accelerated build.
* Acceleration-struct size is doubled to account for possible compaction step. */
size_t wired_size = posBuf.allocatedSize + indexBuf.allocatedSize + scratchBuf.allocatedSize +
accel_uncompressed.allocatedSize * 2;
[accelCommands addCompletedHandler:^(id<MTLCommandBuffer> /*command_buffer*/) {
/* free temp resources */
[scratchBuf release];
@ -228,7 +320,9 @@ bool BVHMetal::build_BLAS_mesh(Progress &progress,
stats.mem_alloc(allocated_size);
accel_struct = accel;
[accel_uncompressed release];
accel_struct_building = false;
/* Signal that we've finished doing GPU acceleration struct build. */
g_bvh_build_throttler.release(wired_size);
}];
[accelCommands commit];
});
@ -239,12 +333,16 @@ bool BVHMetal::build_BLAS_mesh(Progress &progress,
uint64_t allocated_size = [accel_struct allocatedSize];
stats.mem_alloc(allocated_size);
accel_struct_building = false;
/* Signal that we've finished doing GPU acceleration struct build. */
g_bvh_build_throttler.release(wired_size);
}
[sizeBuf release];
}];
accel_struct_building = true;
/* Wait until it's safe to proceed with GPU acceleration struct build. */
g_bvh_build_throttler.acquire(wired_size);
[accelCommands commit];
return true;
@ -528,6 +626,13 @@ bool BVHMetal::build_BLAS_hair(Progress &progress,
sizeDataType:MTLDataTypeULong];
}
[accelEnc endEncoding];
/* Estimated size of resources that will be wired for the GPU accelerated build.
* Acceleration-struct size is doubled to account for possible compaction step. */
size_t wired_size = cpBuffer.allocatedSize + radiusBuffer.allocatedSize +
idxBuffer.allocatedSize + scratchBuf.allocatedSize +
accel_uncompressed.allocatedSize * 2;
[accelCommands addCompletedHandler:^(id<MTLCommandBuffer> /*command_buffer*/) {
/* free temp resources */
[scratchBuf release];
@ -552,7 +657,9 @@ bool BVHMetal::build_BLAS_hair(Progress &progress,
stats.mem_alloc(allocated_size);
accel_struct = accel;
[accel_uncompressed release];
accel_struct_building = false;
/* Signal that we've finished doing GPU acceleration struct build. */
g_bvh_build_throttler.release(wired_size);
}];
[accelCommands commit];
});
@ -563,12 +670,16 @@ bool BVHMetal::build_BLAS_hair(Progress &progress,
uint64_t allocated_size = [accel_struct allocatedSize];
stats.mem_alloc(allocated_size);
accel_struct_building = false;
/* Signal that we've finished doing GPU acceleration struct build. */
g_bvh_build_throttler.release(wired_size);
}
[sizeBuf release];
}];
accel_struct_building = true;
/* Wait until it's safe to proceed with GPU acceleration struct build. */
g_bvh_build_throttler.acquire(wired_size);
[accelCommands commit];
return true;
@ -763,6 +874,12 @@ bool BVHMetal::build_BLAS_pointcloud(Progress &progress,
sizeDataType:MTLDataTypeULong];
}
[accelEnc endEncoding];
/* Estimated size of resources that will be wired for the GPU accelerated build.
* Acceleration-struct size is doubled to account for possible compaction step. */
size_t wired_size = aabbBuf.allocatedSize + scratchBuf.allocatedSize +
accel_uncompressed.allocatedSize * 2;
[accelCommands addCompletedHandler:^(id<MTLCommandBuffer> /*command_buffer*/) {
/* free temp resources */
[scratchBuf release];
@ -786,7 +903,9 @@ bool BVHMetal::build_BLAS_pointcloud(Progress &progress,
stats.mem_alloc(allocated_size);
accel_struct = accel;
[accel_uncompressed release];
accel_struct_building = false;
/* Signal that we've finished doing GPU acceleration struct build. */
g_bvh_build_throttler.release(wired_size);
}];
[accelCommands commit];
});
@ -797,12 +916,16 @@ bool BVHMetal::build_BLAS_pointcloud(Progress &progress,
uint64_t allocated_size = [accel_struct allocatedSize];
stats.mem_alloc(allocated_size);
accel_struct_building = false;
/* Signal that we've finished doing GPU acceleration struct build. */
g_bvh_build_throttler.release(wired_size);
}
[sizeBuf release];
}];
accel_struct_building = true;
/* Wait until it's safe to proceed with GPU acceleration struct build. */
g_bvh_build_throttler.acquire(wired_size);
[accelCommands commit];
return true;
}
@ -814,22 +937,20 @@ bool BVHMetal::build_BLAS(Progress &progress,
id<MTLCommandQueue> queue,
bool refit)
{
if (@available(macos 12.0, *)) {
assert(objects.size() == 1 && geometry.size() == 1);
assert(objects.size() == 1 && geometry.size() == 1);
/* Build bottom level acceleration structures (BLAS) */
Geometry *const geom = geometry[0];
switch (geom->geometry_type) {
case Geometry::VOLUME:
case Geometry::MESH:
return build_BLAS_mesh(progress, device, queue, geom, refit);
case Geometry::HAIR:
return build_BLAS_hair(progress, device, queue, geom, refit);
case Geometry::POINTCLOUD:
return build_BLAS_pointcloud(progress, device, queue, geom, refit);
default:
return false;
}
/* Build bottom level acceleration structures (BLAS) */
Geometry *const geom = geometry[0];
switch (geom->geometry_type) {
case Geometry::VOLUME:
case Geometry::MESH:
return build_BLAS_mesh(progress, device, queue, geom, refit);
case Geometry::HAIR:
return build_BLAS_hair(progress, device, queue, geom, refit);
case Geometry::POINTCLOUD:
return build_BLAS_pointcloud(progress, device, queue, geom, refit);
default:
return false;
}
return false;
}
@ -839,38 +960,11 @@ bool BVHMetal::build_TLAS(Progress &progress,
id<MTLCommandQueue> queue,
bool refit)
{
/* Wait for all BLAS builds to finish. */
g_bvh_build_throttler.wait_for_all();
if (@available(macos 12.0, *)) {
/* we need to sync here and ensure that all BLAS have completed async generation by both GCD
* and Metal */
{
__block bool complete_bvh = false;
while (!complete_bvh) {
dispatch_sync(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
complete_bvh = true;
for (Object *ob : objects) {
/* Skip non-traceable objects */
if (!ob->is_traceable())
continue;
Geometry const *geom = ob->get_geometry();
BVHMetal const *blas = static_cast<BVHMetal const *>(geom->bvh);
if (blas->accel_struct_building) {
complete_bvh = false;
/* We're likely waiting on a command buffer that's in flight to complete.
* Queue up a command buffer and wait for it complete before checking the BLAS again
*/
id<MTLCommandBuffer> command_buffer = [queue commandBuffer];
[command_buffer commit];
[command_buffer waitUntilCompleted];
break;
}
}
});
}
}
uint32_t num_instances = 0;
uint32_t num_motion_transforms = 0;
for (Object *ob : objects) {
@ -1178,11 +1272,13 @@ bool BVHMetal::build(Progress &progress,
}
}
if (!params.top_level) {
return build_BLAS(progress, device, queue, refit);
}
else {
return build_TLAS(progress, device, queue, refit);
@autoreleasepool {
if (!params.top_level) {
return build_BLAS(progress, device, queue, refit);
}
else {
return build_TLAS(progress, device, queue, refit);
}
}
}

View File

@ -47,6 +47,7 @@ class MetalDevice : public Device {
MetalGPUVendor device_vendor;
uint kernel_features;
bool using_nanovdb = false;
MTLResourceOptions default_storage_mode;
int max_threads_per_threadgroup;

View File

@ -216,6 +216,8 @@ MetalDevice::MetalDevice(const DeviceInfo &info, Stats &stats, Profiler &profile
arg_desc_ift.index = index++;
[ancillary_desc addObject:[arg_desc_ift copy]]; /* ift_shadow */
arg_desc_ift.index = index++;
[ancillary_desc addObject:[arg_desc_ift copy]]; /* ift_volume */
arg_desc_ift.index = index++;
[ancillary_desc addObject:[arg_desc_ift copy]]; /* ift_local */
arg_desc_ift.index = index++;
[ancillary_desc addObject:[arg_desc_ift copy]]; /* ift_local_prim */
@ -347,7 +349,9 @@ string MetalDevice::preprocess_source(MetalPipelineType pso_type,
case METAL_GPU_APPLE:
global_defines += "#define __KERNEL_METAL_APPLE__\n";
# ifdef WITH_NANOVDB
if (DebugFlags().metal.use_nanovdb) {
/* Compiling in NanoVDB results in a marginal drop in render performance,
* so disable it for specialized PSOs when no textures are using it. */
if ((pso_type == PSO_GENERIC || using_nanovdb) && DebugFlags().metal.use_nanovdb) {
global_defines += "#define WITH_NANOVDB\n";
}
# endif
@ -1088,6 +1092,14 @@ void MetalDevice::tex_alloc_as_buffer(device_texture &mem)
texture_info[slot].data = *(uint64_t *)((uint64_t)buffer_bindings_1d.contents + offset);
texture_slot_map[slot] = nil;
need_texture_info = true;
if (mem.info.data_type == IMAGE_DATA_TYPE_NANOVDB_FLOAT ||
mem.info.data_type == IMAGE_DATA_TYPE_NANOVDB_FLOAT3 ||
mem.info.data_type == IMAGE_DATA_TYPE_NANOVDB_FPN ||
mem.info.data_type == IMAGE_DATA_TYPE_NANOVDB_FP16)
{
using_nanovdb = true;
}
}
void MetalDevice::tex_alloc(device_texture &mem)

View File

@ -18,6 +18,8 @@ enum {
METALRT_FUNC_DEFAULT_BOX,
METALRT_FUNC_SHADOW_TRI,
METALRT_FUNC_SHADOW_BOX,
METALRT_FUNC_VOLUME_TRI,
METALRT_FUNC_VOLUME_BOX,
METALRT_FUNC_LOCAL_TRI,
METALRT_FUNC_LOCAL_BOX,
METALRT_FUNC_LOCAL_TRI_PRIM,
@ -32,6 +34,7 @@ enum {
enum {
METALRT_TABLE_DEFAULT,
METALRT_TABLE_SHADOW,
METALRT_TABLE_VOLUME,
METALRT_TABLE_LOCAL,
METALRT_TABLE_LOCAL_PRIM,
METALRT_TABLE_NUM

View File

@ -489,6 +489,8 @@ void MetalKernelPipeline::compile()
"__anyhit__cycles_metalrt_visibility_test_box",
"__anyhit__cycles_metalrt_shadow_all_hit_tri",
"__anyhit__cycles_metalrt_shadow_all_hit_box",
"__anyhit__cycles_metalrt_volume_test_tri",
"__anyhit__cycles_metalrt_volume_test_box",
"__anyhit__cycles_metalrt_local_hit_tri",
"__anyhit__cycles_metalrt_local_hit_box",
"__anyhit__cycles_metalrt_local_hit_tri_prim",
@ -563,6 +565,11 @@ void MetalKernelPipeline::compile()
point_intersect_shadow :
rt_intersection_function[METALRT_FUNC_SHADOW_BOX],
nil];
table_functions[METALRT_TABLE_VOLUME] = [NSArray
arrayWithObjects:rt_intersection_function[METALRT_FUNC_VOLUME_TRI],
rt_intersection_function[METALRT_FUNC_VOLUME_BOX],
rt_intersection_function[METALRT_FUNC_VOLUME_BOX],
nil];
table_functions[METALRT_TABLE_LOCAL] = [NSArray
arrayWithObjects:rt_intersection_function[METALRT_FUNC_LOCAL_TRI],
rt_intersection_function[METALRT_FUNC_LOCAL_BOX],
@ -577,6 +584,7 @@ void MetalKernelPipeline::compile()
NSMutableSet *unique_functions = [[NSMutableSet alloc] init];
[unique_functions addObjectsFromArray:table_functions[METALRT_TABLE_DEFAULT]];
[unique_functions addObjectsFromArray:table_functions[METALRT_TABLE_SHADOW]];
[unique_functions addObjectsFromArray:table_functions[METALRT_TABLE_VOLUME]];
[unique_functions addObjectsFromArray:table_functions[METALRT_TABLE_LOCAL]];
[unique_functions addObjectsFromArray:table_functions[METALRT_TABLE_LOCAL_PRIM]];

View File

@ -489,7 +489,7 @@ bool MetalDeviceQueue::enqueue(DeviceKernel kernel,
[metal_device_->mtlAncillaryArgEncoder setAccelerationStructure:accel_struct atIndex:3];
[metal_device_->mtlAncillaryArgEncoder setBuffer:metal_device_->blas_buffer
offset:0
atIndex:8];
atIndex:9];
}
for (int table = 0; table < METALRT_TABLE_NUM; table++) {

View File

@ -151,8 +151,9 @@ ccl_device_noinline bool BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals kg,
prim_addr))
{
/* shadow ray early termination */
if (visibility & PATH_RAY_SHADOW_OPAQUE)
if (visibility & PATH_RAY_SHADOW_OPAQUE) {
return true;
}
}
break;
}

View File

@ -13,8 +13,9 @@ ccl_device ccl_private ShaderClosure *closure_alloc(ccl_private ShaderData *sd,
{
kernel_assert(size <= sizeof(ShaderClosure));
if (sd->num_closure_left == 0)
if (sd->num_closure_left == 0) {
return NULL;
}
ccl_private ShaderClosure *sc = &sd->closure[sd->num_closure];

View File

@ -359,7 +359,7 @@ ccl_device_inline int bsdf_label(const KernelGlobals kg,
case CLOSURE_BSDF_DIFFUSE_ID:
case CLOSURE_BSSRDF_BURLEY_ID:
case CLOSURE_BSSRDF_RANDOM_WALK_ID:
case CLOSURE_BSSRDF_RANDOM_WALK_FIXED_RADIUS_ID:
case CLOSURE_BSSRDF_RANDOM_WALK_SKIN_ID:
label = LABEL_REFLECT | LABEL_DIFFUSE;
break;
#ifdef __SVM__

View File

@ -26,6 +26,7 @@ enum MicrofacetFresnel {
DIELECTRIC_TINT, /* used by the OSL MaterialX closures */
CONDUCTOR,
GENERALIZED_SCHLICK,
F82_TINT,
};
typedef struct FresnelDielectricTint {
@ -46,6 +47,13 @@ typedef struct FresnelGeneralizedSchlick {
float exponent;
} FresnelGeneralizedSchlick;
typedef struct FresnelF82Tint {
/* Perpendicular reflectivity. */
Spectrum f0;
/* Precomputed (1-cos)^6 factor for edge tint. */
Spectrum b;
} FresnelF82Tint;
typedef struct MicrofacetBsdf {
SHADER_CLOSURE_BASE;
@ -236,6 +244,17 @@ ccl_device_forceinline void microfacet_fresnel(ccl_private const MicrofacetBsdf
*r_reflectance = fresnel_conductor(cos_theta_i, fresnel->n, fresnel->k);
*r_transmittance = zero_spectrum();
}
else if (bsdf->fresnel_type == MicrofacetFresnel::F82_TINT) {
/* F82-Tint model, described in "Novel aspects of the Adobe Standard Material" by Kutz et al.
* Essentially, this is the usual Schlick Fresnel with an additional cosI*(1-cosI)^6
* term which modulates the reflectivity around acos(1/7) degrees (ca. 82°). */
ccl_private FresnelF82Tint *fresnel = (ccl_private FresnelF82Tint *)bsdf->fresnel;
const float mu = saturatef(1.0f - cos_theta_i);
const float mu5 = sqr(sqr(mu)) * mu;
const Spectrum F_schlick = mix(fresnel->f0, one_spectrum(), mu5);
*r_reflectance = saturate(F_schlick - fresnel->b * cos_theta_i * mu5 * mu);
*r_transmittance = zero_spectrum();
}
else if (bsdf->fresnel_type == MicrofacetFresnel::GENERALIZED_SCHLICK) {
ccl_private FresnelGeneralizedSchlick *fresnel = (ccl_private FresnelGeneralizedSchlick *)
bsdf->fresnel;
@ -379,6 +398,14 @@ ccl_device Spectrum bsdf_microfacet_estimate_albedo(KernelGlobals kg,
}
reflectance = mix(fresnel->f0, fresnel->f90, s) * fresnel->reflection_tint;
}
else if (bsdf->fresnel_type == MicrofacetFresnel::F82_TINT) {
ccl_private FresnelF82Tint *fresnel = (ccl_private FresnelF82Tint *)bsdf->fresnel;
float rough = sqrtf(sqrtf(bsdf->alpha_x * bsdf->alpha_y));
const float s = lookup_table_read_3D(
kg, rough, cos_NI, 0.5f, kernel_data.tables.ggx_gen_schlick_s, 16, 16, 16);
/* TODO: Precompute B factor term and account for it here. */
reflectance = mix(fresnel->f0, one_spectrum(), s);
}
return reflectance + transmittance;
}
@ -738,6 +765,7 @@ ccl_device void bsdf_microfacet_setup_fresnel_generalized_schlick(
ccl_private FresnelGeneralizedSchlick *fresnel,
const bool preserve_energy)
{
fresnel->f0 = saturate(fresnel->f0);
bsdf->fresnel_type = MicrofacetFresnel::GENERALIZED_SCHLICK;
bsdf->fresnel = fresnel;
bsdf->sample_weight *= average(bsdf_microfacet_estimate_albedo(kg, sd, bsdf, true, true));
@ -780,6 +808,40 @@ ccl_device void bsdf_microfacet_setup_fresnel_generalized_schlick(
}
}
ccl_device void bsdf_microfacet_setup_fresnel_f82_tint(KernelGlobals kg,
ccl_private MicrofacetBsdf *bsdf,
ccl_private const ShaderData *sd,
ccl_private FresnelF82Tint *fresnel,
const Spectrum f82_tint,
const bool preserve_energy)
{
if (isequal(f82_tint, one_spectrum())) {
fresnel->b = zero_spectrum();
}
else {
/* Precompute the F82 term factor for the Fresnel model.
* In the classic F82 model, the F82 input directly determines the value of the Fresnel
* model at ~82°, similar to F0 and F90.
* With F82-Tint, on the other hand, the value at 82° is the value of the classic Schlick
* model multiplied by the tint input.
* Therefore, the factor follows by setting F82Tint(cosI) = FSchlick(cosI) - b*cosI*(1-cosI)^6
* and F82Tint(acos(1/7)) = FSchlick(acos(1/7)) * f82_tint and solving for b. */
const float f = 6.0f / 7.0f;
const float f5 = sqr(sqr(f)) * f;
const Spectrum F_schlick = mix(fresnel->f0, one_spectrum(), f5);
fresnel->b = F_schlick * (7.0f / (f5 * f)) * (one_spectrum() - f82_tint);
}
bsdf->fresnel_type = MicrofacetFresnel::F82_TINT;
bsdf->fresnel = fresnel;
bsdf->sample_weight *= average(bsdf_microfacet_estimate_albedo(kg, sd, bsdf, true, true));
if (preserve_energy) {
Spectrum Fss = mix(fresnel->f0, one_spectrum(), 1.0f / 21.0f) - fresnel->b * (1.0f / 126.0f);
microfacet_ggx_preserve_energy(kg, bsdf, sd, Fss);
}
}
ccl_device void bsdf_microfacet_setup_fresnel_constant(KernelGlobals kg,
ccl_private MicrofacetBsdf *bsdf,
ccl_private const ShaderData *sd,

View File

@ -37,6 +37,13 @@ ccl_device int bsdf_sheen_setup(KernelGlobals kg,
bsdf->transformB = lookup_table_read_2D(kg, cosNI, bsdf->roughness, offset + 32 * 32, 32, 32);
float albedo = lookup_table_read_2D(kg, cosNI, bsdf->roughness, offset + 2 * 32 * 32, 32, 32);
/* If the given roughness and angle result in an invalid LTC, skip the closure. */
if (fabsf(bsdf->transformA) < 1e-5f || albedo < 1e-5f) {
bsdf->type = CLOSURE_NONE_ID;
bsdf->sample_weight = 0.0f;
return 0;
}
bsdf->weight *= albedo;
bsdf->sample_weight *= albedo;

View File

@ -33,12 +33,15 @@ ccl_device float bsdf_toon_get_intensity(float max_angle, float smooth, float an
{
float is;
if (angle < max_angle)
if (angle < max_angle) {
is = 1.0f;
else if (angle < (max_angle + smooth) && smooth != 0.0f)
}
else if (angle < (max_angle + smooth) && smooth != 0.0f) {
is = (1.0f - (angle - max_angle) / smooth);
else
}
else {
is = 0.0f;
}
return is;
}

View File

@ -59,7 +59,7 @@ ccl_device float bssrdf_dipole_compute_alpha_prime(float rd, float fourthirdA)
ccl_device void bssrdf_setup_radius(ccl_private Bssrdf *bssrdf, const ClosureType type)
{
if (type == CLOSURE_BSSRDF_BURLEY_ID || type == CLOSURE_BSSRDF_RANDOM_WALK_FIXED_RADIUS_ID) {
if (type == CLOSURE_BSSRDF_BURLEY_ID || type == CLOSURE_BSSRDF_RANDOM_WALK_ID) {
/* Scale mean free path length so it gives similar looking result to older
* Cubic, Gaussian and Burley models. */
bssrdf->radius *= 0.25f * M_1_PI_F;
@ -291,8 +291,8 @@ ccl_device int bssrdf_setup(ccl_private ShaderData *sd,
int flag = 0;
if (type == CLOSURE_BSSRDF_RANDOM_WALK_ID) {
/* CLOSURE_BSSRDF_RANDOM_WALK_ID uses a fixed roughness. */
if (type == CLOSURE_BSSRDF_RANDOM_WALK_SKIN_ID) {
/* CLOSURE_BSSRDF_RANDOM_WALK_SKIN_ID uses a fixed roughness. */
bssrdf->alpha = 1.0f;
}

View File

@ -452,8 +452,8 @@ ccl_device_intersect bool scene_intersect_volume(KernelGlobals kg,
return false;
}
if (is_null_intersection_function_table(metal_ancillaries->ift_default)) {
kernel_assert(!"Invalid ift_default");
if (is_null_intersection_function_table(metal_ancillaries->ift_volume)) {
kernel_assert(!"Invalid ift_volume");
return false;
}
# endif
@ -479,11 +479,11 @@ ccl_device_intersect bool scene_intersect_volume(KernelGlobals kg,
metal_ancillaries->accel_struct,
visibility,
ray->time,
metal_ancillaries->ift_default,
metal_ancillaries->ift_volume,
payload);
# else
intersection = metalrt_intersect.intersect(
r, metal_ancillaries->accel_struct, visibility, metal_ancillaries->ift_default, payload);
r, metal_ancillaries->accel_struct, visibility, metal_ancillaries->ift_volume, payload);
# endif
if (intersection.type == intersection_type::none) {

View File

@ -331,6 +331,7 @@ struct MetalAncillaries {
metalrt_as_type accel_struct;
metalrt_ift_type ift_default;
metalrt_ift_type ift_shadow;
metalrt_ift_type ift_volume;
metalrt_ift_type ift_local;
metalrt_blas_ift_type ift_local_prim;
constant MetalRTBlasWrapper *blas_accel_structs;

View File

@ -371,6 +371,59 @@ __anyhit__cycles_metalrt_shadow_all_hit_box(const float ray_tmax [[max_distance]
return result;
}
[[intersection(triangle,
triangle_data,
curve_data,
METALRT_TAGS,
extended_limits)]] PrimitiveIntersectionResult
__anyhit__cycles_metalrt_volume_test_tri(
constant KernelParamsMetal &launch_params_metal [[buffer(1)]],
ray_data MetalKernelContext::MetalRTIntersectionPayload &payload [[payload]],
const unsigned int object [[instance_id]],
const unsigned int primitive_id [[primitive_id]],
const uint primitive_id_offset [[user_instance_id]])
{
PrimitiveIntersectionResult result;
result.continue_search = true;
# ifdef __VISIBILITY_FLAG__
if ((kernel_data_fetch(objects, object).visibility & payload.visibility) == 0) {
result.accept = false;
return result;
}
# endif
if ((kernel_data_fetch(object_flag, object) & SD_OBJECT_HAS_VOLUME) == 0) {
result.accept = false;
return result;
}
uint prim = primitive_id + primitive_id_offset;
MetalKernelContext context(launch_params_metal);
if (context.intersection_skip_self(payload.self, object, prim)) {
result.accept = false;
return result;
}
result.accept = true;
return result;
}
[[intersection(bounding_box,
triangle_data,
curve_data,
METALRT_TAGS,
extended_limits)]] BoundingBoxIntersectionResult
__anyhit__cycles_metalrt_volume_test_box(const float ray_tmax [[max_distance]])
{
/* unused function */
BoundingBoxIntersectionResult result;
result.distance = ray_tmax;
result.accept = false;
result.continue_search = false;
return result;
}
template<typename TReturnType, uint intersection_type>
inline TReturnType metalrt_visibility_test(
constant KernelParamsMetal &launch_params_metal,

View File

@ -15,8 +15,9 @@ template<typename T> ccl_device_forceinline T tex_fetch(const TextureInfo &info,
ccl_device_inline int svm_image_texture_wrap_periodic(int x, int width)
{
x %= width;
if (x < 0)
if (x < 0) {
x += width;
}
return x;
}
@ -28,8 +29,9 @@ ccl_device_inline int svm_image_texture_wrap_clamp(int x, int width)
ccl_device_inline int svm_image_texture_wrap_mirror(int x, int width)
{
const int m = abs(x + (x < 0)) % (2 * width);
if (m >= width)
if (m >= width) {
return 2 * width - m - 1;
}
return m;
}

View File

@ -37,8 +37,9 @@ ccl_device_inline void motion_triangle_verts_for_step(KernelGlobals kg,
}
else {
/* center step not store in this array */
if (step > numsteps)
if (step > numsteps) {
step--;
}
offset += step * numverts;
@ -64,8 +65,9 @@ ccl_device_inline void motion_triangle_normals_for_step(KernelGlobals kg,
}
else {
/* center step is not stored in this array */
if (step > numsteps)
if (step > numsteps) {
step--;
}
offset += step * numverts;

View File

@ -282,19 +282,23 @@ ccl_device float patch_eval_float(KernelGlobals kg,
kg, sd->object, patch, u, v, channel, indices, weights, weights_du, weights_dv);
float val = 0.0f;
if (du)
if (du) {
*du = 0.0f;
if (dv)
}
if (dv) {
*dv = 0.0f;
}
for (int i = 0; i < num_control; i++) {
float v = kernel_data_fetch(attributes_float, offset + indices[i]);
val += v * weights[i];
if (du)
if (du) {
*du += v * weights_du[i];
if (dv)
}
if (dv) {
*dv += v * weights_dv[i];
}
}
return val;
@ -328,10 +332,12 @@ ccl_device float2 patch_eval_float2(KernelGlobals kg,
float2 v = kernel_data_fetch(attributes_float2, offset + indices[i]);
val += v * weights[i];
if (du)
if (du) {
*du += v * weights_du[i];
if (dv)
}
if (dv) {
*dv += v * weights_dv[i];
}
}
return val;
@ -356,19 +362,23 @@ ccl_device float3 patch_eval_float3(KernelGlobals kg,
kg, sd->object, patch, u, v, channel, indices, weights, weights_du, weights_dv);
float3 val = make_float3(0.0f, 0.0f, 0.0f);
if (du)
if (du) {
*du = make_float3(0.0f, 0.0f, 0.0f);
if (dv)
}
if (dv) {
*dv = make_float3(0.0f, 0.0f, 0.0f);
}
for (int i = 0; i < num_control; i++) {
float3 v = kernel_data_fetch(attributes_float3, offset + indices[i]);
val += v * weights[i];
if (du)
if (du) {
*du += v * weights_du[i];
if (dv)
}
if (dv) {
*dv += v * weights_dv[i];
}
}
return val;
@ -402,10 +412,12 @@ ccl_device float4 patch_eval_float4(KernelGlobals kg,
float4 v = kernel_data_fetch(attributes_float4, offset + indices[i]);
val += v * weights[i];
if (du)
if (du) {
*du += v * weights_du[i];
if (dv)
}
if (dv) {
*dv += v * weights_dv[i];
}
}
return val;
@ -440,10 +452,12 @@ ccl_device float4 patch_eval_uchar4(KernelGlobals kg,
color_uchar4_to_float4(kernel_data_fetch(attributes_uchar4, offset + indices[i])));
val += v * weights[i];
if (du)
if (du) {
*du += v * weights_du[i];
if (dv)
}
if (dv) {
*dv += v * weights_dv[i];
}
}
return val;

View File

@ -400,10 +400,12 @@ ccl_device void integrator_intersect_closest(KernelGlobals kg,
bool has_receiver_ancestor = INTEGRATOR_STATE(state, path, mnee) & PATH_MNEE_RECEIVER_ANCESTOR;
INTEGRATOR_STATE_WRITE(state, path, mnee) &= ~PATH_MNEE_CULL_LIGHT_CONNECTION;
if (from_caustic_caster && has_receiver_ancestor)
if (from_caustic_caster && has_receiver_ancestor) {
INTEGRATOR_STATE_WRITE(state, path, mnee) |= PATH_MNEE_CULL_LIGHT_CONNECTION;
if (from_caustic_receiver)
}
if (from_caustic_receiver) {
INTEGRATOR_STATE_WRITE(state, path, mnee) |= PATH_MNEE_RECEIVER_ANCESTOR;
}
}
#endif /* __MNEE__ */

View File

@ -236,8 +236,9 @@ ccl_device void volume_shadow_heterogeneous(KernelGlobals kg,
tp = *throughput * exp(sum);
/* stop if nearly all light is blocked */
if (reduce_max(tp) < VOLUME_THROUGHPUT_EPSILON)
if (reduce_max(tp) < VOLUME_THROUGHPUT_EPSILON) {
break;
}
}
}
@ -396,8 +397,9 @@ ccl_device Spectrum volume_emission_integrate(ccl_private VolumeShaderCoefficien
t;
}
}
else
else {
emission *= t;
}
return emission;
}

View File

@ -31,8 +31,8 @@ ccl_device_inline bool subsurface_entry_bounce(KernelGlobals kg,
{
float2 rand_bsdf = path_state_rng_2D(kg, rng_state, PRNG_SUBSURFACE_BSDF);
if (bssrdf->type == CLOSURE_BSSRDF_RANDOM_WALK_ID) {
/* CLOSURE_BSSRDF_RANDOM_WALK_ID has a 50% chance to sample a diffuse entry bounce.
if (bssrdf->type == CLOSURE_BSSRDF_RANDOM_WALK_SKIN_ID) {
/* CLOSURE_BSSRDF_RANDOM_WALK_SKIN_ID has a 50% chance to sample a diffuse entry bounce.
* Also, for the refractive entry, it uses a fixed roughness of 1.0. */
if (rand_bsdf.x < 0.5f) {
rand_bsdf.x *= 2.0f;

View File

@ -219,8 +219,7 @@ ccl_device_inline void surface_shader_validate_bsdf_sample(const KernelGlobals k
{
/* Validate the #bsdf_label and #bsdf_roughness_eta functions
* by estimating the values after a BSDF sample. */
const int comp_label = bsdf_label(kg, sc, wo);
kernel_assert(org_label == comp_label);
kernel_assert(org_label == bsdf_label(kg, sc, wo));
float2 comp_roughness;
float comp_eta;
@ -1025,8 +1024,9 @@ ccl_device float3 surface_shader_average_normal(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_OR_BSSRDF(sc->type))
if (CLOSURE_IS_BSDF_OR_BSSRDF(sc->type)) {
N += sc->N * fabsf(average(sc->weight));
}
}
return (is_zero(N)) ? sd->N : normalize(N);

View File

@ -81,10 +81,12 @@ ccl_device_inline float area_light_rect_sample(float3 P,
}
/* return pdf */
if (S != 0.0f)
if (S != 0.0f) {
return 1.0f / S;
else
}
else {
return 0.0f;
}
}
/* Light spread. */

View File

@ -42,8 +42,9 @@ ccl_device_inline float triangle_light_pdf_area_sampling(const float3 Ng, const
{
float cos_pi = fabsf(dot(Ng, I));
if (cos_pi == 0.0f)
if (cos_pi == 0.0f) {
return 0.0f;
}
return t * t / cos_pi;
}

View File

@ -474,6 +474,53 @@ ccl_device void osl_closure_microfacet_setup(KernelGlobals kg,
/* Special-purpose Microfacet closures */
ccl_device void osl_closure_microfacet_f82_tint_setup(
KernelGlobals kg,
ccl_private ShaderData *sd,
uint32_t path_flag,
float3 weight,
ccl_private const MicrofacetF82TintClosure *closure,
float3 *layer_albedo)
{
if (osl_closure_skip(kg, sd, path_flag, LABEL_GLOSSY | LABEL_REFLECT)) {
return;
}
ccl_private MicrofacetBsdf *bsdf = (ccl_private MicrofacetBsdf *)bsdf_alloc(
sd, sizeof(MicrofacetBsdf), rgb_to_spectrum(weight));
if (!bsdf) {
return;
}
ccl_private FresnelF82Tint *fresnel = (ccl_private FresnelF82Tint *)closure_alloc_extra(
sd, sizeof(FresnelF82Tint));
if (!fresnel) {
return;
}
bsdf->N = maybe_ensure_valid_specular_reflection(sd, closure->N);
bsdf->alpha_x = closure->alpha_x;
bsdf->alpha_y = closure->alpha_y;
bsdf->ior = 0.0f;
bsdf->T = closure->T;
bool preserve_energy = false;
/* Beckmann */
if (closure->distribution == make_string("beckmann", 14712237670914973463ull)) {
sd->flag |= bsdf_microfacet_beckmann_setup(bsdf);
}
/* GGX (either single- or multi-scattering) */
else {
sd->flag |= bsdf_microfacet_ggx_setup(bsdf);
preserve_energy = (closure->distribution == make_string("multi_ggx", 16842698693386468366ull));
}
fresnel->f0 = rgb_to_spectrum(closure->f0);
bsdf_microfacet_setup_fresnel_f82_tint(
kg, bsdf, sd, fresnel, rgb_to_spectrum(closure->f82), preserve_energy);
}
ccl_device void osl_closure_microfacet_multi_ggx_glass_setup(
KernelGlobals kg,
ccl_private ShaderData *sd,
@ -714,8 +761,9 @@ ccl_device void osl_closure_diffuse_ramp_setup(KernelGlobals kg,
return;
}
for (int i = 0; i < 8; i++)
for (int i = 0; i < 8; i++) {
bsdf->colors[i] = closure->colors[i];
}
sd->flag |= bsdf_diffuse_ramp_setup(bsdf);
}
@ -741,8 +789,9 @@ ccl_device void osl_closure_phong_ramp_setup(KernelGlobals kg,
return;
}
for (int i = 0; i < 8; i++)
for (int i = 0; i < 8; i++) {
bsdf->colors[i] = closure->colors[i];
}
sd->flag |= bsdf_phong_ramp_setup(bsdf);
}
@ -758,12 +807,12 @@ ccl_device void osl_closure_bssrdf_setup(KernelGlobals kg,
if (closure->method == make_string("burley", 186330084368958868ull)) {
type = CLOSURE_BSSRDF_BURLEY_ID;
}
else if (closure->method == make_string("random_walk_fixed_radius", 5695810351010063150ull)) {
type = CLOSURE_BSSRDF_RANDOM_WALK_FIXED_RADIUS_ID;
}
else if (closure->method == make_string("random_walk", 11360609267673527222ull)) {
else if (closure->method == make_string("random_walk", 5695810351010063150ull)) {
type = CLOSURE_BSSRDF_RANDOM_WALK_ID;
}
else if (closure->method == make_string("random_walk_skin", 11360609267673527222ull)) {
type = CLOSURE_BSSRDF_RANDOM_WALK_SKIN_ID;
}
else {
return;
}

View File

@ -84,6 +84,16 @@ OSL_CLOSURE_STRUCT_BEGIN(Microfacet, microfacet)
OSL_CLOSURE_STRUCT_MEMBER(Microfacet, INT, int, refract, NULL)
OSL_CLOSURE_STRUCT_END(Microfacet, microfacet)
OSL_CLOSURE_STRUCT_BEGIN(MicrofacetF82Tint, microfacet_f82_tint)
OSL_CLOSURE_STRUCT_MEMBER(MicrofacetF82Tint, STRING, DeviceString, distribution, NULL)
OSL_CLOSURE_STRUCT_MEMBER(MicrofacetF82Tint, VECTOR, packed_float3, N, NULL)
OSL_CLOSURE_STRUCT_MEMBER(MicrofacetF82Tint, VECTOR, packed_float3, T, NULL)
OSL_CLOSURE_STRUCT_MEMBER(MicrofacetF82Tint, FLOAT, float, alpha_x, NULL)
OSL_CLOSURE_STRUCT_MEMBER(MicrofacetF82Tint, FLOAT, float, alpha_y, NULL)
OSL_CLOSURE_STRUCT_MEMBER(MicrofacetF82Tint, VECTOR, packed_float3, f0, NULL)
OSL_CLOSURE_STRUCT_MEMBER(MicrofacetF82Tint, VECTOR, packed_float3, f82, NULL)
OSL_CLOSURE_STRUCT_END(MicrofacetF82Tint, microfacet)
OSL_CLOSURE_STRUCT_BEGIN(MicrofacetMultiGGXGlass, microfacet_multi_ggx_glass)
OSL_CLOSURE_STRUCT_MEMBER(MicrofacetMultiGGXGlass, VECTOR, packed_float3, N, NULL)
OSL_CLOSURE_STRUCT_MEMBER(MicrofacetMultiGGXGlass, FLOAT, float, alpha_x, NULL)

View File

@ -73,7 +73,7 @@ ccl_device void flatten_closure_tree(KernelGlobals kg,
int layer_stack_level = -1;
float3 layer_albedo = zero_float3();
while (closure) {
while (true) {
switch (closure->id) {
case OSL_CLOSURE_MUL_ID: {
ccl_private const OSLClosureMul *mul = static_cast<ccl_private const OSLClosureMul *>(
@ -134,7 +134,12 @@ ccl_device void flatten_closure_tree(KernelGlobals kg,
break;
}
if (stack_size > 0) {
/* Pop the next closure from the stack (or return if we're done). */
do {
if (stack_size == 0) {
return;
}
weight = weight_stack[--stack_size];
closure = closure_stack[stack_size];
if (stack_size == layer_stack_level) {
@ -142,22 +147,13 @@ ccl_device void flatten_closure_tree(KernelGlobals kg,
* account for the layering. */
weight *= saturatef(1.0f - reduce_max(safe_divide_color(layer_albedo, weight)));
layer_stack_level = -1;
/* If it's fully occluded, skip the base layer we just popped from the stack and grab
* the next entry instead. */
if (is_zero(weight)) {
/* If it's fully occluded, skip the base layer we just popped from the stack and grab
* the next entry instead. */
if (stack_size > 0) {
weight = weight_stack[--stack_size];
closure = closure_stack[stack_size];
}
else {
closure = nullptr;
}
continue;
}
}
}
else {
closure = nullptr;
}
} while (closure == nullptr);
}
}

View File

@ -738,22 +738,28 @@ ccl_device_extern bool osl_transform_triple(ccl_private ShaderGlobals *sg,
if (res) {
if (vectype == 2 /* TypeDesc::POINT */) {
if (p_in_derivs)
if (p_in_derivs) {
osl_transform_dvmdv(p_out, m, p_in);
else
}
else {
osl_transform_vmv(p_out, m, p_in);
}
}
else if (vectype == 3 /* TypeDesc::VECTOR */) {
if (p_in_derivs)
if (p_in_derivs) {
osl_transformv_dvmdv(p_out, m, p_in);
else
}
else {
osl_transformv_vmv(p_out, m, p_in);
}
}
else if (vectype == 4 /* TypeDesc::NORMAL */) {
if (p_in_derivs)
if (p_in_derivs) {
osl_transformn_dvmdv(p_out, m, p_in);
else
}
else {
osl_transformn_vmv(p_out, m, p_in);
}
}
else {
res = false;
@ -1630,19 +1636,24 @@ ccl_device_extern bool osl_texture(ccl_private ShaderGlobals *sg,
switch (type) {
case OSL_TEXTURE_HANDLE_TYPE_SVM: {
const float4 rgba = kernel_tex_image_interp(nullptr, slot, s, 1.0f - t);
if (nchannels > 0)
if (nchannels > 0) {
result[0] = rgba.x;
if (nchannels > 1)
}
if (nchannels > 1) {
result[1] = rgba.y;
if (nchannels > 2)
}
if (nchannels > 2) {
result[2] = rgba.z;
if (alpha)
}
if (alpha) {
*alpha = rgba.w;
}
return true;
}
case OSL_TEXTURE_HANDLE_TYPE_IES: {
if (nchannels > 0)
if (nchannels > 0) {
result[0] = kernel_ies_interp(nullptr, slot, s, t);
}
return true;
}
default: {
@ -1674,14 +1685,18 @@ ccl_device_extern bool osl_texture3d(ccl_private ShaderGlobals *sg,
switch (type) {
case OSL_TEXTURE_HANDLE_TYPE_SVM: {
const float4 rgba = kernel_tex_image_interp_3d(nullptr, slot, *P, INTERPOLATION_NONE);
if (nchannels > 0)
if (nchannels > 0) {
result[0] = rgba.x;
if (nchannels > 1)
}
if (nchannels > 1) {
result[1] = rgba.y;
if (nchannels > 2)
}
if (nchannels > 2) {
result[2] = rgba.z;
if (alpha)
}
if (alpha) {
*alpha = rgba.w;
}
return true;
}
default: {
@ -1706,14 +1721,18 @@ ccl_device_extern bool osl_environment(ccl_private ShaderGlobals *sg,
ccl_private float *dalphay,
ccl_private void *errormessage)
{
if (nchannels > 0)
if (nchannels > 0) {
result[0] = 1.0f;
if (nchannels > 1)
}
if (nchannels > 1) {
result[1] = 0.0f;
if (nchannels > 2)
}
if (nchannels > 2) {
result[2] = 1.0f;
if (alpha)
}
if (alpha) {
*alpha = 1.0f;
}
return false;
}
@ -2095,22 +2114,25 @@ ccl_device_extern void osl_sincos_dfdff(ccl_private const float *a,
ccl_private float *b,
ccl_private float *c)
{
for (int i = 0; i < 3; ++i)
for (int i = 0; i < 3; ++i) {
sincos(a[i], b + i, c);
}
}
ccl_device_extern void osl_sincos_dffdf(ccl_private const float *a,
ccl_private float *b,
ccl_private float *c)
{
for (int i = 0; i < 3; ++i)
for (int i = 0; i < 3; ++i) {
sincos(a[i], b, c + i);
}
}
ccl_device_extern void osl_sincos_dfdfdf(ccl_private const float *a,
ccl_private float *b,
ccl_private float *c)
{
for (int i = 0; i < 3; ++i)
for (int i = 0; i < 3; ++i) {
sincos(a[i], b + i, c + i);
}
}
ccl_device_extern void osl_sincos_vvv(ccl_private const float3 *a,
ccl_private float3 *b,
@ -2232,10 +2254,12 @@ ccl_device_extern void osl_calculatenormal(ccl_private float3 *res,
ccl_private ShaderGlobals *sg,
ccl_private const float3 *p)
{
if (sg->flipHandedness)
if (sg->flipHandedness) {
*res = cross(p[2], p[1]);
else
}
else {
*res = cross(p[1], p[2]);
}
}
ccl_device_extern float osl_area(ccl_private const float3 *p)
@ -2250,8 +2274,9 @@ ccl_device_extern float osl_filterwidth_fdf(ccl_private const float *x)
ccl_device_extern void osl_filterwidth_vdv(ccl_private float *res, ccl_private const float *x)
{
for (int i = 0; i < 3; ++i)
for (int i = 0; i < 3; ++i) {
res[i] = osl_filterwidth_fdf(x + i);
}
}
ccl_device_extern bool osl_raytype_bit(ccl_private ShaderGlobals *sg, int bit)

View File

@ -6,18 +6,22 @@
float color_srgb_to_scene_linear(float c)
{
if (c < 0.04045)
if (c < 0.04045) {
return (c < 0.0) ? 0.0 : c * (1.0 / 12.92);
else
}
else {
return pow((c + 0.055) * (1.0 / 1.055), 2.4);
}
}
float color_scene_linear_to_srgb(float c)
{
if (c < 0.0031308)
if (c < 0.0031308) {
return (c < 0.0) ? 0.0 : c * 12.92;
else
}
else {
return 1.055 * pow(c, 1.0 / 2.4) - 0.055;
}
}
color color_srgb_to_scene_linear(color c)
@ -36,8 +40,9 @@ color color_scene_linear_to_srgb(color c)
color color_unpremultiply(color c, float alpha)
{
if (alpha != 1.0 && alpha != 0.0)
if (alpha != 1.0 && alpha != 0.0) {
return c / alpha;
}
return c;
}
@ -48,15 +53,19 @@ color xyY_to_xyz(float x, float y, float Y)
{
float X, Z;
if (y != 0.0)
if (y != 0.0) {
X = (x / y) * Y;
else
}
else {
X = 0.0;
}
if (y != 0.0 && Y != 0.0)
if (y != 0.0 && Y != 0.0) {
Z = ((1.0 - x - y) / y) * Y;
else
}
else {
Z = 0.0;
}
return color(X, Y, Z);
}
@ -93,17 +102,21 @@ color rgb_to_hsv(color rgb)
else {
c = (color(cmax, cmax, cmax) - rgb) / cdelta;
if (rgb[0] == cmax)
if (rgb[0] == cmax) {
h = c[2] - c[1];
else if (rgb[1] == cmax)
}
else if (rgb[1] == cmax) {
h = 2.0 + c[0] - c[2];
else
}
else {
h = 4.0 + c[1] - c[0];
}
h /= 6.0;
if (h < 0.0)
if (h < 0.0) {
h += 1.0;
}
}
return color(h, s, v);
@ -122,8 +135,9 @@ color hsv_to_rgb(color hsv)
rgb = color(v, v, v);
}
else {
if (h == 1.0)
if (h == 1.0) {
h = 0.0;
}
h *= 6.0;
i = floor(h);
@ -133,18 +147,24 @@ color hsv_to_rgb(color hsv)
q = v * (1.0 - (s * f));
t = v * (1.0 - (s * (1.0 - f)));
if (i == 0.0)
if (i == 0.0) {
rgb = color(v, t, p);
else if (i == 1.0)
}
else if (i == 1.0) {
rgb = color(q, v, p);
else if (i == 2.0)
}
else if (i == 2.0) {
rgb = color(p, v, t);
else if (i == 3.0)
}
else if (i == 3.0) {
rgb = color(p, q, v);
else if (i == 4.0)
}
else if (i == 4.0) {
rgb = color(t, p, v);
else
}
else {
rgb = color(v, p, q);
}
}
return rgb;

View File

@ -30,20 +30,26 @@ color node_mix_overlay(float t, color col1, color col2)
color outcol = col1;
if (outcol[0] < 0.5)
if (outcol[0] < 0.5) {
outcol[0] *= tm + 2.0 * t * col2[0];
else
}
else {
outcol[0] = 1.0 - (tm + 2.0 * t * (1.0 - col2[0])) * (1.0 - outcol[0]);
}
if (outcol[1] < 0.5)
if (outcol[1] < 0.5) {
outcol[1] *= tm + 2.0 * t * col2[1];
else
}
else {
outcol[1] = 1.0 - (tm + 2.0 * t * (1.0 - col2[1])) * (1.0 - outcol[1]);
}
if (outcol[2] < 0.5)
if (outcol[2] < 0.5) {
outcol[2] *= tm + 2.0 * t * col2[2];
else
}
else {
outcol[2] = 1.0 - (tm + 2.0 * t * (1.0 - col2[2])) * (1.0 - outcol[2]);
}
return outcol;
}
@ -59,12 +65,15 @@ color node_mix_div(float t, color col1, color col2)
color outcol = col1;
if (col2[0] != 0.0)
if (col2[0] != 0.0) {
outcol[0] = tm * outcol[0] + t * outcol[0] / col2[0];
if (col2[1] != 0.0)
}
if (col2[1] != 0.0) {
outcol[1] = tm * outcol[1] + t * outcol[1] / col2[1];
if (col2[2] != 0.0)
}
if (col2[2] != 0.0) {
outcol[2] = tm * outcol[2] + t * outcol[2] / col2[2];
}
return outcol;
}
@ -95,30 +104,39 @@ color node_mix_dodge(float t, color col1, color col2)
if (outcol[0] != 0.0) {
float tmp = 1.0 - t * col2[0];
if (tmp <= 0.0)
if (tmp <= 0.0) {
outcol[0] = 1.0;
else if ((tmp = outcol[0] / tmp) > 1.0)
}
else if ((tmp = outcol[0] / tmp) > 1.0) {
outcol[0] = 1.0;
else
}
else {
outcol[0] = tmp;
}
}
if (outcol[1] != 0.0) {
float tmp = 1.0 - t * col2[1];
if (tmp <= 0.0)
if (tmp <= 0.0) {
outcol[1] = 1.0;
else if ((tmp = outcol[1] / tmp) > 1.0)
}
else if ((tmp = outcol[1] / tmp) > 1.0) {
outcol[1] = 1.0;
else
}
else {
outcol[1] = tmp;
}
}
if (outcol[2] != 0.0) {
float tmp = 1.0 - t * col2[2];
if (tmp <= 0.0)
if (tmp <= 0.0) {
outcol[2] = 1.0;
else if ((tmp = outcol[2] / tmp) > 1.0)
}
else if ((tmp = outcol[2] / tmp) > 1.0) {
outcol[2] = 1.0;
else
}
else {
outcol[2] = tmp;
}
}
return outcol;
@ -131,34 +149,46 @@ color node_mix_burn(float t, color col1, color col2)
color outcol = col1;
tmp = tm + t * col2[0];
if (tmp <= 0.0)
if (tmp <= 0.0) {
outcol[0] = 0.0;
else if ((tmp = (1.0 - (1.0 - outcol[0]) / tmp)) < 0.0)
}
else if ((tmp = (1.0 - (1.0 - outcol[0]) / tmp)) < 0.0) {
outcol[0] = 0.0;
else if (tmp > 1.0)
}
else if (tmp > 1.0) {
outcol[0] = 1.0;
else
}
else {
outcol[0] = tmp;
}
tmp = tm + t * col2[1];
if (tmp <= 0.0)
if (tmp <= 0.0) {
outcol[1] = 0.0;
else if ((tmp = (1.0 - (1.0 - outcol[1]) / tmp)) < 0.0)
}
else if ((tmp = (1.0 - (1.0 - outcol[1]) / tmp)) < 0.0) {
outcol[1] = 0.0;
else if (tmp > 1.0)
}
else if (tmp > 1.0) {
outcol[1] = 1.0;
else
}
else {
outcol[1] = tmp;
}
tmp = tm + t * col2[2];
if (tmp <= 0.0)
if (tmp <= 0.0) {
outcol[2] = 0.0;
else if ((tmp = (1.0 - (1.0 - outcol[2]) / tmp)) < 0.0)
}
else if ((tmp = (1.0 - (1.0 - outcol[2]) / tmp)) < 0.0) {
outcol[2] = 0.0;
else if (tmp > 1.0)
}
else if (tmp > 1.0) {
outcol[2] = 1.0;
else
}
else {
outcol[2] = tmp;
}
return outcol;
}
@ -240,20 +270,26 @@ color node_mix_linear(float t, color col1, color col2)
{
color outcol = col1;
if (col2[0] > 0.5)
if (col2[0] > 0.5) {
outcol[0] = col1[0] + t * (2.0 * (col2[0] - 0.5));
else
}
else {
outcol[0] = col1[0] + t * (2.0 * (col2[0]) - 1.0);
}
if (col2[1] > 0.5)
if (col2[1] > 0.5) {
outcol[1] = col1[1] + t * (2.0 * (col2[1] - 0.5));
else
}
else {
outcol[1] = col1[1] + t * (2.0 * (col2[1]) - 1.0);
}
if (col2[2] > 0.5)
if (col2[2] > 0.5) {
outcol[2] = col1[2] + t * (2.0 * (col2[2] - 0.5));
else
}
else {
outcol[2] = col1[2] + t * (2.0 * (col2[2]) - 1.0);
}
return outcol;
}

View File

@ -19,8 +19,9 @@ float fresnel_dielectric_cos(float cosi, float eta)
float B = (c * (g + c) - 1) / (c * (g - c) + 1);
result = 0.5 * A * A * (1 + B * B);
}
else
else {
result = 1.0; /* TIR (no refracted component) */
}
return result;
}
@ -41,3 +42,9 @@ float F0_from_ior(float eta)
float f0 = (eta - 1.0) / (eta + 1.0);
return f0 * f0;
}
float ior_from_F0(float f0)
{
float sqrt_f0 = sqrt(clamp(f0, 0.0, 0.99));
return (1.0 + sqrt_f0) / (1.0 - sqrt_f0);
}

View File

@ -10,64 +10,72 @@
float safe_noise(float p)
{
float f = noise("noise", p);
if (isinf(f))
if (isinf(f)) {
return 0.5;
}
return f;
}
float safe_noise(vector2 p)
{
float f = noise("noise", p.x, p.y);
if (isinf(f))
if (isinf(f)) {
return 0.5;
}
return f;
}
float safe_noise(vector3 p)
{
float f = noise("noise", p);
if (isinf(f))
if (isinf(f)) {
return 0.5;
}
return f;
}
float safe_noise(vector4 p)
{
float f = noise("noise", vector3(p.x, p.y, p.z), p.w);
if (isinf(f))
if (isinf(f)) {
return 0.5;
}
return f;
}
float safe_snoise(float p)
{
float f = noise("snoise", p);
if (isinf(f))
if (isinf(f)) {
return 0.0;
}
return f;
}
float safe_snoise(vector2 p)
{
float f = noise("snoise", p.x, p.y);
if (isinf(f))
if (isinf(f)) {
return 0.0;
}
return f;
}
float safe_snoise(vector3 p)
{
float f = noise("snoise", p);
if (isinf(f))
if (isinf(f)) {
return 0.0;
}
return f;
}
float safe_snoise(vector4 p)
{
float f = noise("snoise", vector3(p.x, p.y, p.z), p.w);
if (isinf(f))
if (isinf(f)) {
return 0.0;
}
return f;
}

View File

@ -8,27 +8,27 @@
shader node_principled_bsdf(string distribution = "multi_ggx",
string subsurface_method = "random_walk",
color BaseColor = color(0.8, 0.8, 0.8),
float Subsurface = 0.0,
float SubsurfaceWeight = 0.0,
float SubsurfaceScale = 0.1,
vector SubsurfaceRadius = vector(1.0, 1.0, 1.0),
float SubsurfaceIOR = 1.4,
float SubsurfaceAnisotropy = 0.0,
float Metallic = 0.0,
float Specular = 0.5,
float SpecularTint = 0.0,
float SpecularIORLevel = 0.5,
color SpecularTint = color(1.0),
float Roughness = 0.5,
float Anisotropic = 0.0,
float AnisotropicRotation = 0.0,
float Sheen = 0.0,
float SheenWeight = 0.0,
float SheenRoughness = 0.5,
color SheenTint = 0.5,
float Coat = 0.0,
float CoatWeight = 0.0,
float CoatRoughness = 0.03,
float CoatIOR = 1.5,
color CoatTint = color(1.0, 1.0, 1.0),
float IOR = 1.45,
float Transmission = 0.0,
color Emission = 1.0,
float TransmissionWeight = 0.0,
color EmissionColor = 1.0,
float EmissionStrength = 0.0,
float Alpha = 1.0,
normal Normal = N,
@ -36,7 +36,11 @@ shader node_principled_bsdf(string distribution = "multi_ggx",
normal Tangent = normalize(dPdu),
output closure color BSDF = 0)
{
float r2 = Roughness * Roughness;
color specular_tint = max(SpecularTint, color(0.0));
float r2 = clamp(Roughness, 0.0, 1.0);
r2 = r2 * r2;
float alpha_x = r2, alpha_y = r2;
/* Handle anisotropy. */
@ -49,11 +53,22 @@ shader node_principled_bsdf(string distribution = "multi_ggx",
T = rotate(T, AnisotropicRotation * M_2PI, point(0.0, 0.0, 0.0), Normal);
}
if (Metallic < 1.0 && Transmission < 1.0) {
if (Metallic < 1.0 && TransmissionWeight < 1.0) {
float eta = IOR;
float f0 = F0_from_ior(eta);
if (SpecularIORLevel != 0.5) {
f0 *= 2.0 * max(SpecularIORLevel, 0.0);
eta = ior_from_F0(f0);
if (IOR < 1.0) {
eta = 1.0 / eta;
}
}
BSDF = BaseColor * diffuse(Normal);
if (Subsurface > 1e-5) {
if (SubsurfaceWeight > 1e-5) {
float subsurface_weight = min(SubsurfaceWeight, 1.0);
vector radius = SubsurfaceScale * SubsurfaceRadius;
float subsurface_ior = (subsurface_method == "random_walk") ? SubsurfaceIOR : IOR;
float subsurface_ior = (subsurface_method == "random_walk_skin") ? SubsurfaceIOR : eta;
closure color SubsurfBSDF = bssrdf(subsurface_method,
Normal,
SubsurfaceScale * SubsurfaceRadius,
@ -64,66 +79,64 @@ shader node_principled_bsdf(string distribution = "multi_ggx",
subsurface_ior,
"anisotropy",
SubsurfaceAnisotropy);
BSDF = mix(BSDF, BaseColor * SubsurfBSDF, Subsurface);
BSDF = mix(BSDF, BaseColor * SubsurfBSDF, subsurface_weight);
}
color f0 = color(F0_from_ior(IOR));
color f90 = color(1.0);
/* Apply specular tint */
float m_cdlum = luminance(BaseColor);
color m_ctint = m_cdlum > 0.0 ? BaseColor / m_cdlum : color(1.0);
color specTint = mix(color(1.0), m_ctint, SpecularTint);
f0 *= (specTint * 2.0 * Specular);
color F0 = f0 * specular_tint;
color F90 = color(1.0);
BSDF = layer(
generalized_schlick_bsdf(
Normal, T, color(1.0), color(0.0), alpha_x, alpha_y, f0, f90, -IOR, distribution),
Normal, T, color(1.0), color(0.0), alpha_x, alpha_y, F0, F90, -eta, distribution),
BSDF);
}
closure color TransmissionBSDF = 0;
if (Metallic < 1.0 && Transmission > 0.0) {
color reflectTint = mix(color(1.0), BaseColor, SpecularTint);
if (Metallic < 1.0 && TransmissionWeight > 0.0) {
float eta = max(IOR, 1e-5);
eta = backfacing() ? 1.0 / eta : eta;
TransmissionBSDF = dielectric_bsdf(
Normal, vector(0.0), reflectTint, sqrt(BaseColor), r2, r2, eta, distribution);
BSDF = mix(BSDF, TransmissionBSDF, clamp(Transmission, 0.0, 1.0));
color F0 = F0_from_ior(eta) * specular_tint;
color F90 = color(1.0);
TransmissionBSDF = generalized_schlick_bsdf(
Normal, vector(0.0), color(1.0), sqrt(BaseColor), r2, r2, F0, F90, -eta, distribution),
BSDF = mix(BSDF, TransmissionBSDF, clamp(TransmissionWeight, 0.0, 1.0));
}
closure color MetallicBSDF = 0;
if (Metallic > 0.0) {
color f0 = BaseColor;
color f90 = color(1.0);
MetallicBSDF = generalized_schlick_bsdf(
Normal, T, color(1.0), color(0.0), alpha_x, alpha_y, f0, f90, 5.0, distribution);
color F0 = BaseColor;
color F82 = specular_tint;
MetallicBSDF = microfacet_f82_tint(distribution, Normal, T, alpha_x, alpha_y, F0, F82);
BSDF = mix(BSDF, MetallicBSDF, clamp(Metallic, 0.0, 1.0));
}
if (EmissionStrength > 0.0 && Emission != color(0.0)) {
BSDF += EmissionStrength * Emission * emission();
if (EmissionStrength > 0.0 && EmissionColor != color(0.0)) {
BSDF += EmissionStrength * EmissionColor * emission();
}
if (Coat > 1e-5) {
if (CoatWeight > 1e-5) {
float coat_ior = max(CoatIOR, 1.0);
if (CoatTint != color(1.0)) {
float coat_neta = 1.0 / coat_ior;
float cosNI = dot(I, CoatNormal);
float cosNT = sqrt(1.0 - coat_neta * coat_neta * (1 - cosNI * cosNI));
BSDF *= pow(CoatTint, Coat / cosNT);
BSDF *= pow(CoatTint, CoatWeight / cosNT);
}
float coat_r2 = CoatRoughness * CoatRoughness;
float coat_r2 = clamp(CoatRoughness, 0.0, 1.0);
coat_r2 = coat_r2 * coat_r2;
closure color CoatBSDF = dielectric_bsdf(
CoatNormal, vector(0.0), color(1.0), color(0.0), coat_r2, coat_r2, coat_ior, "ggx");
BSDF = layer(Coat * CoatBSDF, BSDF);
BSDF = layer(clamp(CoatWeight, 0.0, 1.0) * CoatBSDF, BSDF);
}
if (Sheen > 1e-5) {
closure color SheenBSDF = sheen(Normal, SheenRoughness);
BSDF = layer(SheenTint * Sheen * SheenBSDF, BSDF);
if (SheenWeight > 1e-5) {
closure color SheenBSDF = sheen(Normal, clamp(SheenRoughness, 0.0, 1.0));
BSDF = layer(clamp(SheenWeight, 0.0, 1.0) * SheenTint * SheenBSDF, BSDF);
}
BSDF = mix(transparent(), BSDF, Alpha);
BSDF = mix(transparent(), BSDF, clamp(Alpha, 0.0, 1.0));
}

View File

@ -28,16 +28,19 @@ color rgb_ramp_lookup(color ramp[], float at, int interpolate, int extrapolate)
/* clamp int as well in case of NaN */
int i = (int)f;
if (i < 0)
if (i < 0) {
i = 0;
if (i >= table_size)
}
if (i >= table_size) {
i = table_size - 1;
}
float t = f - (float)i;
color result = ramp[i];
if (interpolate && t > 0.0)
if (interpolate && t > 0.0) {
result = (1.0 - t) * result + t * ramp[i + 1];
}
return result;
}
@ -66,16 +69,19 @@ float rgb_ramp_lookup(float ramp[], float at, int interpolate, int extrapolate)
/* clamp int as well in case of NaN */
int i = (int)f;
if (i < 0)
if (i < 0) {
i = 0;
if (i >= table_size)
}
if (i >= table_size) {
i = table_size - 1;
}
float t = f - (float)i;
float result = ramp[i];
if (interpolate && t > 0.0)
if (interpolate && t > 0.0) {
result = (1.0 - t) * result + t * ramp[i + 1];
}
return result;
}

View File

@ -26,6 +26,9 @@ closure color ashikhmin_velvet(normal N, float sigma) BUILTIN;
closure color sheen(normal N, float roughness) BUILTIN;
closure color ambient_occlusion() BUILTIN;
closure color microfacet_f82_tint(
string distribution, vector N, vector T, float ax, float ay, color f0, color f82) BUILTIN;
/* Needed to pass along the color for multi-scattering saturation adjustment,
* otherwise could be replaced by microfacet() */
closure color microfacet_multi_ggx_glass(normal N, float ag, float eta, color C) BUILTIN;

View File

@ -128,10 +128,10 @@ ccl_device_inline float3 sample_uniform_cone(const float3 N,
float2 xy = sample_uniform_disk(rand);
const float r2 = len_squared(xy);
/* Equivalent to `mix(cos_angle, 1.0f, 1.0f - r2)` */
/* Equivalent to `mix(cos_angle, 1.0f, 1.0f - r2)`. */
*cos_theta = 1.0f - r2 * one_minus_cos_angle;
/* Remap disk radius to cone radius, equivalent to `xy *= sin_theta / sqrt(r2); */
/* Remap disk radius to cone radius, equivalent to `xy *= sin_theta / sqrt(r2)`. */
xy *= safe_sqrtf(one_minus_cos_angle * (2.0f - one_minus_cos_angle * r2));
*pdf = M_1_2PI_F / one_minus_cos_angle;

View File

@ -23,8 +23,9 @@ ccl_device float svm_bevel_cubic_eval(const float radius, float r)
{
const float Rm = radius;
if (r >= Rm)
if (r >= Rm) {
return 0.0f;
}
/* integrate (2*pi*r * 10*(R - r)^3)/(pi * R^5) from 0 to R = 1 */
const float Rm5 = (Rm * Rm) * (Rm * Rm) * Rm;
@ -58,8 +59,9 @@ ccl_device_forceinline float svm_bevel_cubic_quintic_root_find(float xi)
float f = 10.0f * x2 - 20.0f * x3 + 15.0f * x2 * x2 - 4.0f * x2 * x3 - xi;
float f_ = 20.0f * (x * nx) * (nx * nx);
if (fabsf(f) < tolerance || f_ == 0.0f)
if (fabsf(f) < tolerance || f_ == 0.0f) {
break;
}
x = saturatef(x - f / f_);
}

View File

@ -22,14 +22,17 @@ ccl_device_noinline void svm_node_camera(KernelGlobals kg,
zdepth = vector.z;
distance = len(vector);
if (stack_valid(out_vector))
if (stack_valid(out_vector)) {
stack_store_float3(stack, out_vector, normalize(vector));
}
if (stack_valid(out_zdepth))
if (stack_valid(out_zdepth)) {
stack_store_float(stack, out_zdepth, zdepth);
}
if (stack_valid(out_distance))
if (stack_valid(out_distance)) {
stack_store_float(stack, out_distance, distance);
}
}
CCL_NAMESPACE_END

View File

@ -29,13 +29,19 @@ ccl_device_inline int svm_node_closure_bsdf_skip(KernelGlobals kg, int offset, u
}
template<uint node_feature_mask, ShaderType shader_type>
ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg,
ccl_private ShaderData *sd,
ccl_private float *stack,
Spectrum closure_weight,
uint4 node,
uint32_t path_flag,
int offset)
#ifndef __KERNEL_ONEAPI__
ccl_device_noinline
#else
ccl_device
#endif
int
svm_node_closure_bsdf(KernelGlobals kg,
ccl_private ShaderData *sd,
ccl_private float *stack,
Spectrum closure_weight,
uint4 node,
uint32_t path_flag,
int offset)
{
uint type, param1_offset, param2_offset;
@ -74,46 +80,50 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg,
switch (type) {
case CLOSURE_BSDF_PRINCIPLED_ID: {
uint specular_offset, roughness_offset, specular_tint_offset, anisotropic_offset,
sheen_offset, sheen_tint_offset, sheen_roughness_offset, coat_offset,
coat_roughness_offset, coat_ior_offset, eta_offset, transmission_offset,
uint specular_ior_level_offset, roughness_offset, specular_tint_offset, anisotropic_offset,
sheen_weight_offset, sheen_tint_offset, sheen_roughness_offset, coat_weight_offset,
coat_roughness_offset, coat_ior_offset, eta_offset, transmission_weight_offset,
anisotropic_rotation_offset, coat_tint_offset, coat_normal_offset, dummy, alpha_offset,
emission_strength_offset, emission_offset;
emission_strength_offset, emission_offset, unused;
uint4 data_node2 = read_node(kg, &offset);
float3 T = stack_load_float3(stack, data_node.y);
svm_unpack_node_uchar4(data_node.z,
&specular_offset,
&specular_ior_level_offset,
&roughness_offset,
&specular_tint_offset,
&anisotropic_offset);
svm_unpack_node_uchar4(
data_node.w, &sheen_offset, &sheen_tint_offset, &sheen_roughness_offset, &dummy);
data_node.w, &sheen_weight_offset, &sheen_tint_offset, &sheen_roughness_offset, &unused);
svm_unpack_node_uchar4(data_node2.x,
&eta_offset,
&transmission_offset,
&transmission_weight_offset,
&anisotropic_rotation_offset,
&coat_normal_offset);
svm_unpack_node_uchar4(
data_node2.w, &coat_offset, &coat_roughness_offset, &coat_ior_offset, &coat_tint_offset);
svm_unpack_node_uchar4(data_node2.w,
&coat_weight_offset,
&coat_roughness_offset,
&coat_ior_offset,
&coat_tint_offset);
// get Disney principled parameters
float metallic = saturatef(param1);
float subsurface = param2;
float specular = stack_load_float(stack, specular_offset);
float roughness = stack_load_float(stack, roughness_offset);
float specular_tint = stack_load_float(stack, specular_tint_offset);
float anisotropic = stack_load_float(stack, anisotropic_offset);
float sheen = stack_load_float(stack, sheen_offset);
float subsurface_weight = saturatef(param2);
float specular_ior_level = fmaxf(stack_load_float(stack, specular_ior_level_offset), 0.0f);
float roughness = saturatef(stack_load_float(stack, roughness_offset));
Spectrum specular_tint = rgb_to_spectrum(
max(stack_load_float3(stack, specular_tint_offset), zero_float3()));
float anisotropic = saturatef(stack_load_float(stack, anisotropic_offset));
float sheen_weight = saturatef(stack_load_float(stack, sheen_weight_offset));
float3 sheen_tint = stack_load_float3(stack, sheen_tint_offset);
float sheen_roughness = stack_load_float(stack, sheen_roughness_offset);
float coat = stack_load_float(stack, coat_offset);
float coat_roughness = stack_load_float(stack, coat_roughness_offset);
float sheen_roughness = saturatef(stack_load_float(stack, sheen_roughness_offset));
float coat_weight = saturatef(stack_load_float(stack, coat_weight_offset));
float coat_roughness = saturatef(stack_load_float(stack, coat_roughness_offset));
float coat_ior = fmaxf(stack_load_float(stack, coat_ior_offset), 1.0f);
float3 coat_tint = stack_load_float3(stack, coat_tint_offset);
float transmission = saturatef(stack_load_float(stack, transmission_offset));
float transmission_weight = saturatef(stack_load_float(stack, transmission_weight_offset));
float anisotropic_rotation = stack_load_float(stack, anisotropic_rotation_offset);
float eta = fmaxf(stack_load_float(stack, eta_offset), 1e-5f);
float ior = fmaxf(stack_load_float(stack, eta_offset), 1e-5f);
ClosureType distribution = (ClosureType)data_node2.y;
ClosureType subsurface_method = (ClosureType)data_node2.z;
@ -139,17 +149,18 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg,
&dummy);
float alpha = stack_valid(alpha_offset) ? stack_load_float(stack, alpha_offset) :
__uint_as_float(data_alpha_emission.y);
float3 emission = stack_load_float3(stack, emission_offset);
/* Emission strength */
emission *= stack_valid(emission_strength_offset) ?
stack_load_float(stack, emission_strength_offset) :
__uint_as_float(data_alpha_emission.z);
alpha = saturatef(alpha);
float emission_strength = stack_valid(emission_strength_offset) ?
stack_load_float(stack, emission_strength_offset) :
__uint_as_float(data_alpha_emission.z);
float3 emission = stack_load_float3(stack, emission_offset) * fmaxf(emission_strength, 0.0f);
Spectrum weight = closure_weight * mix_weight;
float alpha_x = sqr(roughness), alpha_y = sqr(roughness);
if (anisotropic > 0.0f) {
float aspect = sqrtf(1.0f - saturatef(anisotropic) * 0.9f);
float aspect = sqrtf(1.0f - anisotropic * 0.9f);
alpha_x /= aspect;
alpha_y *= aspect;
if (anisotropic_rotation != 0.0f)
@ -174,9 +185,9 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg,
}
/* First layer: Sheen */
if (sheen > CLOSURE_WEIGHT_CUTOFF) {
if (sheen_weight > CLOSURE_WEIGHT_CUTOFF) {
ccl_private SheenBsdf *bsdf = (ccl_private SheenBsdf *)bsdf_alloc(
sd, sizeof(SheenBsdf), sheen * rgb_to_spectrum(sheen_tint) * weight);
sd, sizeof(SheenBsdf), sheen_weight * rgb_to_spectrum(sheen_tint) * weight);
if (bsdf) {
bsdf->N = N;
@ -192,14 +203,14 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg,
}
/* Second layer: Coat */
if (coat > CLOSURE_WEIGHT_CUTOFF) {
if (coat_weight > CLOSURE_WEIGHT_CUTOFF) {
float3 coat_normal = stack_valid(coat_normal_offset) ?
stack_load_float3(stack, coat_normal_offset) :
sd->N;
coat_normal = maybe_ensure_valid_specular_reflection(sd, coat_normal);
if (reflective_caustics) {
ccl_private MicrofacetBsdf *bsdf = (ccl_private MicrofacetBsdf *)bsdf_alloc(
sd, sizeof(MicrofacetBsdf), coat * weight);
sd, sizeof(MicrofacetBsdf), coat_weight * weight);
if (bsdf) {
bsdf->N = coat_normal;
@ -242,7 +253,7 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg,
* TIR is no concern here since we're always coming from the outside. */
float cosNT = sqrtf(1.0f - sqr(1.0f / coat_ior) * (1 - sqr(cosNI)));
float optical_depth = 1.0f / cosNT;
weight *= power(rgb_to_spectrum(coat_tint), coat * optical_depth);
weight *= power(rgb_to_spectrum(coat_tint), coat_weight * optical_depth);
}
}
@ -255,10 +266,10 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg,
if (reflective_caustics && metallic > CLOSURE_WEIGHT_CUTOFF) {
ccl_private MicrofacetBsdf *bsdf = (ccl_private MicrofacetBsdf *)bsdf_alloc(
sd, sizeof(MicrofacetBsdf), metallic * weight);
ccl_private FresnelGeneralizedSchlick *fresnel =
(bsdf != NULL) ? (ccl_private FresnelGeneralizedSchlick *)closure_alloc_extra(
sd, sizeof(FresnelGeneralizedSchlick)) :
NULL;
ccl_private FresnelF82Tint *fresnel =
(bsdf != NULL) ?
(ccl_private FresnelF82Tint *)closure_alloc_extra(sd, sizeof(FresnelF82Tint)) :
NULL;
if (bsdf && fresnel) {
bsdf->N = valid_reflection_N;
@ -268,15 +279,12 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg,
bsdf->alpha_y = alpha_y;
fresnel->f0 = rgb_to_spectrum(base_color);
fresnel->f90 = one_spectrum();
fresnel->exponent = 5.0f;
fresnel->reflection_tint = one_spectrum();
fresnel->transmission_tint = zero_spectrum();
const Spectrum f82 = specular_tint;
/* setup bsdf */
sd->flag |= bsdf_microfacet_ggx_setup(bsdf);
const bool is_multiggx = (distribution == CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID);
bsdf_microfacet_setup_fresnel_generalized_schlick(kg, bsdf, sd, fresnel, is_multiggx);
bsdf_microfacet_setup_fresnel_f82_tint(kg, bsdf, sd, fresnel, f82, is_multiggx);
/* Attenuate other components */
weight *= (1.0f - metallic);
@ -284,12 +292,12 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg,
}
/* Transmission component */
if (glass_caustics && transmission > CLOSURE_WEIGHT_CUTOFF) {
if (glass_caustics && transmission_weight > CLOSURE_WEIGHT_CUTOFF) {
ccl_private MicrofacetBsdf *bsdf = (ccl_private MicrofacetBsdf *)bsdf_alloc(
sd, sizeof(MicrofacetBsdf), transmission * weight);
ccl_private FresnelDielectricTint *fresnel =
(bsdf != NULL) ? (ccl_private FresnelDielectricTint *)closure_alloc_extra(
sd, sizeof(FresnelDielectricTint)) :
sd, sizeof(MicrofacetBsdf), transmission_weight * weight);
ccl_private FresnelGeneralizedSchlick *fresnel =
(bsdf != NULL) ? (ccl_private FresnelGeneralizedSchlick *)closure_alloc_extra(
sd, sizeof(FresnelGeneralizedSchlick)) :
NULL;
if (bsdf && fresnel) {
@ -297,19 +305,21 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg,
bsdf->T = zero_float3();
bsdf->alpha_x = bsdf->alpha_y = sqr(roughness);
bsdf->ior = (sd->flag & SD_BACKFACING) ? 1.0f / eta : eta;
bsdf->ior = (sd->flag & SD_BACKFACING) ? 1.0f / ior : ior;
fresnel->reflection_tint = mix(
one_spectrum(), rgb_to_spectrum(base_color), specular_tint);
fresnel->f0 = make_float3(F0_from_ior(ior)) * specular_tint;
fresnel->f90 = one_spectrum();
fresnel->exponent = -ior;
fresnel->reflection_tint = one_spectrum();
fresnel->transmission_tint = sqrt(rgb_to_spectrum(base_color));
/* setup bsdf */
sd->flag |= bsdf_microfacet_ggx_glass_setup(bsdf);
const bool is_multiggx = (distribution == CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID);
bsdf_microfacet_setup_fresnel_dielectric_tint(kg, bsdf, sd, fresnel, is_multiggx);
bsdf_microfacet_setup_fresnel_generalized_schlick(kg, bsdf, sd, fresnel, is_multiggx);
/* Attenuate other components */
weight *= (1.0f - transmission);
weight *= (1.0f - transmission_weight);
}
}
@ -323,17 +333,24 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg,
NULL;
if (bsdf && fresnel) {
/* Apply IOR adjustment */
float eta = ior;
float f0 = F0_from_ior(eta);
if (specular_ior_level != 0.5f) {
f0 *= 2.0f * specular_ior_level;
eta = ior_from_F0(f0);
if (ior < 1.0f) {
eta = 1.0f / eta;
}
}
bsdf->N = valid_reflection_N;
bsdf->ior = eta;
bsdf->T = T;
bsdf->alpha_x = alpha_x;
bsdf->alpha_y = alpha_y;
float m_cdlum = linear_rgb_to_gray(kg, base_color);
float3 m_ctint = m_cdlum > 0.0f ? base_color / m_cdlum : one_float3();
float3 specTint = mix(one_spectrum(), rgb_to_spectrum(m_ctint), specular_tint);
fresnel->f0 = F0_from_ior(eta) * 2.0f * specular * specTint;
fresnel->f0 = f0 * specular_tint;
fresnel->f90 = one_spectrum();
fresnel->exponent = -eta;
fresnel->reflection_tint = one_spectrum();
@ -352,8 +369,8 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg,
/* Diffuse/Subsurface component */
#ifdef __SUBSURFACE__
ccl_private Bssrdf *bssrdf = bssrdf_alloc(sd,
rgb_to_spectrum(base_color) * subsurface * weight);
ccl_private Bssrdf *bssrdf = bssrdf_alloc(
sd, rgb_to_spectrum(base_color) * subsurface_weight * weight);
if (bssrdf) {
float3 subsurface_radius = stack_load_float3(stack, data_subsurf.y);
float subsurface_scale = stack_load_float(stack, data_subsurf.z);
@ -362,9 +379,9 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg,
bssrdf->albedo = rgb_to_spectrum(base_color);
bssrdf->N = N;
bssrdf->alpha = sqr(roughness);
bssrdf->ior = eta;
bssrdf->ior = ior;
bssrdf->anisotropy = stack_load_float(stack, data_subsurf.w);
if (subsurface_method == CLOSURE_BSSRDF_RANDOM_WALK_ID) {
if (subsurface_method == CLOSURE_BSSRDF_RANDOM_WALK_SKIN_ID) {
bssrdf->ior = stack_load_float(stack, data_subsurf.x);
}
@ -372,11 +389,13 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg,
sd->flag |= bssrdf_setup(sd, bssrdf, path_flag, subsurface_method);
}
#else
subsurface = 0.0f;
subsurface_weight = 0.0f;
#endif
ccl_private DiffuseBsdf *bsdf = (ccl_private DiffuseBsdf *)bsdf_alloc(
sd, sizeof(DiffuseBsdf), rgb_to_spectrum(base_color) * (1.0f - subsurface) * weight);
sd,
sizeof(DiffuseBsdf),
rgb_to_spectrum(base_color) * (1.0f - subsurface_weight) * weight);
if (bsdf) {
bsdf->N = N;
@ -456,8 +475,9 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg,
/* rotate tangent */
float rotation = stack_load_float(stack, data_node.z);
if (rotation != 0.0f)
if (rotation != 0.0f) {
bsdf->T = rotate_around_axis(bsdf->T, bsdf->N, rotation * M_2PI_F);
}
if (anisotropy < 0.0f) {
bsdf->alpha_x = roughness / (1.0f + anisotropy);
@ -603,10 +623,12 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg,
bsdf->size = param1;
bsdf->smooth = param2;
if (type == CLOSURE_BSDF_DIFFUSE_TOON_ID)
if (type == CLOSURE_BSDF_DIFFUSE_TOON_ID) {
sd->flag |= bsdf_diffuse_toon_setup(bsdf);
else
}
else {
sd->flag |= bsdf_glossy_toon_setup(bsdf);
}
}
break;
}
@ -801,7 +823,7 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg,
#ifdef __SUBSURFACE__
case CLOSURE_BSSRDF_BURLEY_ID:
case CLOSURE_BSSRDF_RANDOM_WALK_ID:
case CLOSURE_BSSRDF_RANDOM_WALK_FIXED_RADIUS_ID: {
case CLOSURE_BSSRDF_RANDOM_WALK_SKIN_ID: {
Spectrum weight = closure_weight * mix_weight;
ccl_private Bssrdf *bssrdf = bssrdf_alloc(sd, weight);
@ -1014,8 +1036,9 @@ ccl_device_noinline void svm_node_closure_emission(ccl_private ShaderData *sd,
if (stack_valid(mix_weight_offset)) {
float mix_weight = stack_load_float(stack, mix_weight_offset);
if (mix_weight == 0.0f)
if (mix_weight == 0.0f) {
return;
}
weight *= mix_weight;
}
@ -1034,8 +1057,9 @@ ccl_device_noinline void svm_node_closure_background(ccl_private ShaderData *sd,
if (stack_valid(mix_weight_offset)) {
float mix_weight = stack_load_float(stack, mix_weight_offset);
if (mix_weight == 0.0f)
if (mix_weight == 0.0f) {
return;
}
weight *= mix_weight;
}
@ -1053,13 +1077,15 @@ ccl_device_noinline void svm_node_closure_holdout(ccl_private ShaderData *sd,
if (stack_valid(mix_weight_offset)) {
float mix_weight = stack_load_float(stack, mix_weight_offset);
if (mix_weight == 0.0f)
if (mix_weight == 0.0f) {
return;
}
closure_alloc(sd, sizeof(ShaderClosure), CLOSURE_HOLDOUT_ID, closure_weight * mix_weight);
}
else
else {
closure_alloc(sd, sizeof(ShaderClosure), CLOSURE_HOLDOUT_ID, closure_weight);
}
sd->flag |= SD_HOLDOUT;
}

View File

@ -17,8 +17,9 @@ ccl_device_noinline void svm_node_gamma(ccl_private ShaderData *sd,
color = svm_math_gamma_color(color, gamma);
if (stack_valid(out_color))
if (stack_valid(out_color)) {
stack_store_float3(stack, out_color, color);
}
}
CCL_NAMESPACE_END

View File

@ -41,10 +41,12 @@ ccl_device float svm_gradient(float3 p, NodeGradientType type)
* on float precision. */
float r = fmaxf(0.999999f - sqrtf(x * x + y * y + z * z), 0.0f);
if (type == NODE_BLEND_QUADRATIC_SPHERE)
if (type == NODE_BLEND_QUADRATIC_SPHERE) {
return r * r;
else if (type == NODE_BLEND_SPHERICAL)
}
else if (type == NODE_BLEND_SPHERICAL) {
return r;
}
}
return 0.0f;

View File

@ -55,10 +55,12 @@ ccl_device_inline float kernel_ies_interp(KernelGlobals kg, int slot, float h_an
int h_i, v_i;
/* TODO(lukas): Consider using bisection.
* Probably not worth it for the vast majority of IES files. */
for (h_i = 0; IES_LOOKUP_ANGLE_H(h_i + 1) < h_angle; h_i++)
for (h_i = 0; IES_LOOKUP_ANGLE_H(h_i + 1) < h_angle; h_i++) {
;
for (v_i = 0; IES_LOOKUP_ANGLE_V(v_i + 1) < v_angle; v_i++)
}
for (v_i = 0; IES_LOOKUP_ANGLE_V(v_i + 1) < v_angle; v_i++) {
;
}
float h_frac = inverse_lerp(IES_LOOKUP_ANGLE_H(h_i), IES_LOOKUP_ANGLE_H(h_i + 1), h_angle);
float v_frac = inverse_lerp(IES_LOOKUP_ANGLE_V(v_i), IES_LOOKUP_ANGLE_V(v_i + 1), v_angle);

View File

@ -24,8 +24,9 @@ ccl_device_noinline void svm_node_invert(ccl_private ShaderData *sd,
color.y = invert(color.y, factor);
color.z = invert(color.z, factor);
if (stack_valid(out_color))
if (stack_valid(out_color)) {
stack_store_float3(stack, out_color, color);
}
}
CCL_NAMESPACE_END

View File

@ -24,11 +24,13 @@ ccl_device_noinline int svm_node_normal(KernelGlobals kg,
direction.z = __int_as_float(node1.z);
direction = normalize(direction);
if (stack_valid(out_normal_offset))
if (stack_valid(out_normal_offset)) {
stack_store_float3(stack, out_normal_offset, direction);
}
if (stack_valid(out_dot_offset))
if (stack_valid(out_dot_offset)) {
stack_store_float(stack, out_dot_offset, dot(direction, normalize(normal)));
}
return offset;
}

View File

@ -24,8 +24,9 @@ ccl_device_noinline void svm_node_combine_color(KernelGlobals kg,
/* Combine, and convert back to RGB */
float3 color = svm_combine_color((NodeCombSepColorType)color_type, make_float3(r, g, b));
if (stack_valid(result_stack_offset))
if (stack_valid(result_stack_offset)) {
stack_store_float3(stack, result_stack_offset, color);
}
}
ccl_device_noinline void svm_node_separate_color(KernelGlobals kg,

View File

@ -24,8 +24,9 @@ ccl_device_noinline int svm_node_combine_hsv(KernelGlobals kg,
/* Combine, and convert back to RGB */
float3 color = hsv_to_rgb(make_float3(hue, saturation, value));
if (stack_valid(color_out))
if (stack_valid(color_out)) {
stack_store_float3(stack, color_out, color);
}
return offset;
}

View File

@ -16,8 +16,9 @@ ccl_device void svm_node_combine_vector(ccl_private ShaderData *sd,
{
float vector = stack_load_float(stack, in_offset);
if (stack_valid(out_offset))
if (stack_valid(out_offset)) {
stack_store_float(stack, out_offset + vector_index, vector);
}
}
ccl_device void svm_node_separate_vector(ccl_private ShaderData *sd,
@ -29,12 +30,15 @@ ccl_device void svm_node_separate_vector(ccl_private ShaderData *sd,
float3 vector = stack_load_float3(stack, ivector_offset);
if (stack_valid(out_offset)) {
if (vector_index == 0)
if (vector_index == 0) {
stack_store_float(stack, out_offset, vector.x);
else if (vector_index == 1)
}
else if (vector_index == 1) {
stack_store_float(stack, out_offset, vector.y);
else
}
else {
stack_store_float(stack, out_offset, vector.z);
}
}
}

View File

@ -234,14 +234,18 @@ ccl_device void svm_eval_nodes(KernelGlobals kg,
return;
SVM_CASE(NODE_SHADER_JUMP)
{
if (type == SHADER_TYPE_SURFACE)
if (type == SHADER_TYPE_SURFACE) {
offset = node.y;
else if (type == SHADER_TYPE_VOLUME)
}
else if (type == SHADER_TYPE_VOLUME) {
offset = node.z;
else if (type == SHADER_TYPE_DISPLACEMENT)
}
else if (type == SHADER_TYPE_DISPLACEMENT) {
offset = node.w;
else
}
else {
return;
}
break;
}
SVM_CASE(NODE_CLOSURE_BSDF)
@ -276,12 +280,14 @@ ccl_device void svm_eval_nodes(KernelGlobals kg,
svm_node_mix_closure(sd, stack, node);
break;
SVM_CASE(NODE_JUMP_IF_ZERO)
if (stack_load_float(stack, node.z) <= 0.0f)
if (stack_load_float(stack, node.z) <= 0.0f) {
offset += node.y;
}
break;
SVM_CASE(NODE_JUMP_IF_ONE)
if (stack_load_float(stack, node.z) >= 1.0f)
if (stack_load_float(stack, node.z) >= 1.0f) {
offset += node.y;
}
break;
SVM_CASE(NODE_GEOMETRY)
svm_node_geometry(kg, sd, stack, node.y, node.z);

View File

@ -453,7 +453,7 @@ typedef enum ClosureType {
/* BSSRDF */
CLOSURE_BSSRDF_BURLEY_ID,
CLOSURE_BSSRDF_RANDOM_WALK_ID,
CLOSURE_BSSRDF_RANDOM_WALK_FIXED_RADIUS_ID,
CLOSURE_BSSRDF_RANDOM_WALK_SKIN_ID,
/* Other */
CLOSURE_HOLDOUT_ID,
@ -490,9 +490,9 @@ typedef enum ClosureType {
(type >= CLOSURE_BSDF_MICROFACET_BECKMANN_GLASS_ID && \
type <= CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID))
#define CLOSURE_IS_BSDF_OR_BSSRDF(type) \
(type != CLOSURE_NONE_ID && type <= CLOSURE_BSSRDF_RANDOM_WALK_FIXED_RADIUS_ID)
(type != CLOSURE_NONE_ID && type <= CLOSURE_BSSRDF_RANDOM_WALK_SKIN_ID)
#define CLOSURE_IS_BSSRDF(type) \
(type >= CLOSURE_BSSRDF_BURLEY_ID && type <= CLOSURE_BSSRDF_RANDOM_WALK_FIXED_RADIUS_ID)
(type >= CLOSURE_BSSRDF_BURLEY_ID && type <= CLOSURE_BSSRDF_RANDOM_WALK_SKIN_ID)
#define CLOSURE_IS_VOLUME(type) \
(type >= CLOSURE_VOLUME_ID && type <= CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID)
#define CLOSURE_IS_VOLUME_SCATTER(type) (type == CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID)

View File

@ -44,10 +44,12 @@ ccl_device_noinline int svm_node_tex_voxel(
}
#endif
if (stack_valid(density_out_offset))
if (stack_valid(density_out_offset)) {
stack_store_float(stack, density_out_offset, r.w);
if (stack_valid(color_out_offset))
}
if (stack_valid(color_out_offset)) {
stack_store_float3(stack, color_out_offset, make_float3(r.x, r.y, r.z));
}
return offset;
}

View File

@ -56,8 +56,9 @@ ccl_device_noinline_cpu float svm_wave(NodeWaveType type,
n += phase;
if (distortion != 0.0f)
if (distortion != 0.0f) {
n += distortion * (fractal_noise_3d(p * dscale, detail, droughness, 2.0f, true) * 2.0f - 1.0f);
}
if (profile == NODE_WAVE_PROFILE_SIN) {
return 0.5f + 0.5f * sinf(n - M_PI_2_F);

View File

@ -64,8 +64,9 @@ ccl_device_inline float wireframe(KernelGlobals kg,
// At this point dot(crs, crs) / dot(edge, edge) is
// the square of area / length(edge) == square of the
// distance to the edge.
if (dot(crs, crs) < (dot(edge, edge) * pixelwidth))
if (dot(crs, crs) < (dot(edge, edge) * pixelwidth)) {
return 1.0f;
}
}
}
return 0.0f;

View File

@ -69,13 +69,14 @@ ccl_device void differential_dudv(ccl_private differential *du,
* and the same for dudy and dvdy. the denominator is the same for both
* solutions, so we compute it only once.
*
* dP.dx = dPdu * dudx + dPdv * dvdx;
* dP.dy = dPdu * dudy + dPdv * dvdy; */
* `dP.dx = dPdu * dudx + dPdv * dvdx;`
* `dP.dy = dPdu * dudy + dPdv * dvdy;` */
float det = (dPdu.x * dPdv.y - dPdv.x * dPdu.y);
if (det != 0.0f)
if (det != 0.0f) {
det = 1.0f / det;
}
du->dx = (dP.dx.x * dPdv.y - dP.dx.y * dPdv.x) * det;
dv->dx = (dP.dx.y * dPdu.x - dP.dx.x * dPdu.y) * det;

View File

@ -17,8 +17,9 @@ ccl_device float lookup_table_read(KernelGlobals kg, float x, int offset, int si
float t = x - index;
float data0 = kernel_data_fetch(lookup_table, index + offset);
if (t == 0.0f)
if (t == 0.0f) {
return data0;
}
float data1 = kernel_data_fetch(lookup_table, nindex + offset);
return (1.0f - t) * data0 + t * data1;
@ -34,8 +35,9 @@ ccl_device float lookup_table_read_2D(
float t = y - index;
float data0 = lookup_table_read(kg, x, offset + xsize * index, xsize);
if (t == 0.0f)
if (t == 0.0f) {
return data0;
}
float data1 = lookup_table_read(kg, x, offset + xsize * nindex, xsize);
return (1.0f - t) * data0 + t * data1;
@ -51,8 +53,9 @@ ccl_device float lookup_table_read_3D(
float t = z - index;
float data0 = lookup_table_read_2D(kg, x, y, offset + xsize * ysize * index, xsize, ysize);
if (t == 0.0f)
if (t == 0.0f) {
return data0;
}
float data1 = lookup_table_read_2D(kg, x, y, offset + xsize * ysize * nindex, xsize, ysize);
return (1.0f - t) * data0 + t * data1;

View File

@ -607,10 +607,12 @@ void Mesh::tessellate(DiagSplit *split)
ngons++;
}
}
} break;
break;
}
case ATTR_ELEMENT_VERTEX_MOTION: {
// TODO(mai): implement
} break;
break;
}
case ATTR_ELEMENT_CORNER: {
for (int f = 0; f < num_faces; f++) {
SubdFace face = get_subd_face(f);
@ -629,7 +631,8 @@ void Mesh::tessellate(DiagSplit *split)
ngons++;
}
}
} break;
break;
}
case ATTR_ELEMENT_CORNER_BYTE: {
for (int f = 0; f < num_faces; f++) {
SubdFace face = get_subd_face(f);
@ -654,7 +657,8 @@ void Mesh::tessellate(DiagSplit *split)
ngons++;
}
}
} break;
break;
}
default:
break;
}

View File

@ -138,7 +138,7 @@ static float3 output_estimate_emission(ShaderOutput *output, bool &is_constant)
{
const bool is_principled = (node->type == PrincipledBsdfNode::get_node_type());
/* Emission and Background node. */
ShaderInput *color_in = node->input(is_principled ? "Emission" : "Color");
ShaderInput *color_in = node->input(is_principled ? "Emission Color" : "Color");
ShaderInput *strength_in = node->input(is_principled ? "Emission Strength" : "Strength");
if (is_principled) {

View File

@ -2690,9 +2690,8 @@ NODE_DEFINE(PrincipledBsdfNode)
static NodeEnum subsurface_method_enum;
subsurface_method_enum.insert("burley", CLOSURE_BSSRDF_BURLEY_ID);
subsurface_method_enum.insert("random_walk_fixed_radius",
CLOSURE_BSSRDF_RANDOM_WALK_FIXED_RADIUS_ID);
subsurface_method_enum.insert("random_walk", CLOSURE_BSSRDF_RANDOM_WALK_ID);
subsurface_method_enum.insert("random_walk_skin", CLOSURE_BSSRDF_RANDOM_WALK_SKIN_ID);
SOCKET_ENUM(subsurface_method,
"Subsurface Method",
subsurface_method_enum,
@ -2700,31 +2699,38 @@ NODE_DEFINE(PrincipledBsdfNode)
SOCKET_IN_COLOR(base_color, "Base Color", make_float3(0.8f, 0.8f, 0.8f))
SOCKET_IN_FLOAT(metallic, "Metallic", 0.0f);
SOCKET_IN_FLOAT(subsurface, "Subsurface", 0.0f);
SOCKET_IN_FLOAT(roughness, "Roughness", 0.5f);
SOCKET_IN_FLOAT(ior, "IOR", 0.0f);
SOCKET_IN_FLOAT(alpha, "Alpha", 1.0f);
SOCKET_IN_NORMAL(normal, "Normal", zero_float3(), SocketType::LINK_NORMAL);
SOCKET_IN_FLOAT(subsurface_weight, "Subsurface Weight", 0.0f);
SOCKET_IN_FLOAT(subsurface_scale, "Subsurface Scale", 0.1f);
SOCKET_IN_VECTOR(subsurface_radius, "Subsurface Radius", make_float3(0.1f, 0.1f, 0.1f));
SOCKET_IN_FLOAT(subsurface_ior, "Subsurface IOR", 1.4f);
SOCKET_IN_FLOAT(subsurface_anisotropy, "Subsurface Anisotropy", 0.0f);
SOCKET_IN_FLOAT(specular, "Specular", 0.0f);
SOCKET_IN_FLOAT(roughness, "Roughness", 0.5f);
SOCKET_IN_FLOAT(specular_tint, "Specular Tint", 0.0f);
SOCKET_IN_FLOAT(specular_ior_level, "Specular IOR Level", 0.0f);
SOCKET_IN_COLOR(specular_tint, "Specular Tint", one_float3());
SOCKET_IN_FLOAT(anisotropic, "Anisotropic", 0.0f);
SOCKET_IN_FLOAT(sheen, "Sheen", 0.0f);
SOCKET_IN_FLOAT(anisotropic_rotation, "Anisotropic Rotation", 0.0f);
SOCKET_IN_NORMAL(tangent, "Tangent", zero_float3(), SocketType::LINK_TANGENT);
SOCKET_IN_FLOAT(transmission_weight, "Transmission Weight", 0.0f);
SOCKET_IN_FLOAT(sheen_weight, "Sheen Weight", 0.0f);
SOCKET_IN_FLOAT(sheen_roughness, "Sheen Roughness", 0.5f);
SOCKET_IN_COLOR(sheen_tint, "Sheen Tint", one_float3());
SOCKET_IN_FLOAT(coat, "Coat", 0.0f);
SOCKET_IN_FLOAT(coat_weight, "Coat Weight", 0.0f);
SOCKET_IN_FLOAT(coat_roughness, "Coat Roughness", 0.03f);
SOCKET_IN_FLOAT(coat_ior, "Coat IOR", 1.5f);
SOCKET_IN_COLOR(coat_tint, "Coat Tint", one_float3());
SOCKET_IN_FLOAT(ior, "IOR", 0.0f);
SOCKET_IN_FLOAT(transmission, "Transmission", 0.0f);
SOCKET_IN_FLOAT(anisotropic_rotation, "Anisotropic Rotation", 0.0f);
SOCKET_IN_COLOR(emission, "Emission", one_float3());
SOCKET_IN_FLOAT(emission_strength, "Emission Strength", 0.0f);
SOCKET_IN_FLOAT(alpha, "Alpha", 1.0f);
SOCKET_IN_NORMAL(normal, "Normal", zero_float3(), SocketType::LINK_NORMAL);
SOCKET_IN_NORMAL(coat_normal, "Coat Normal", zero_float3(), SocketType::LINK_NORMAL);
SOCKET_IN_NORMAL(tangent, "Tangent", zero_float3(), SocketType::LINK_TANGENT);
SOCKET_IN_COLOR(emission_color, "Emission Color", one_float3());
SOCKET_IN_FLOAT(emission_strength, "Emission Strength", 0.0f);
SOCKET_IN_FLOAT(surface_mix_weight, "SurfaceMixWeight", 0.0f, SocketType::SVM_INTERNAL);
SOCKET_OUT_CLOSURE(BSDF, "BSDF");
@ -2742,7 +2748,7 @@ void PrincipledBsdfNode::simplify_settings(Scene * /* scene */)
{
if (!has_surface_emission()) {
/* Emission will be zero, so optimize away any connected emission input. */
ShaderInput *emission_in = input("Emission");
ShaderInput *emission_in = input("Emission Color");
ShaderInput *strength_in = input("Emission Strength");
if (emission_in->link) {
emission_in->disconnect();
@ -2761,16 +2767,18 @@ bool PrincipledBsdfNode::has_surface_transparent()
bool PrincipledBsdfNode::has_surface_emission()
{
ShaderInput *emission_in = input("Emission");
ShaderInput *emission_color_in = input("Emission Color");
ShaderInput *emission_strength_in = input("Emission Strength");
return (emission_in->link != NULL || reduce_max(emission) > CLOSURE_WEIGHT_CUTOFF) &&
return (emission_color_in->link != NULL || reduce_max(emission_color) > CLOSURE_WEIGHT_CUTOFF) &&
(emission_strength_in->link != NULL || emission_strength > CLOSURE_WEIGHT_CUTOFF);
}
bool PrincipledBsdfNode::has_surface_bssrdf()
{
ShaderInput *subsurface_in = input("Subsurface");
return (subsurface_in->link != NULL || subsurface > CLOSURE_WEIGHT_CUTOFF);
ShaderInput *subsurface_weight_in = input("Subsurface Weight");
ShaderInput *subsurface_scale_in = input("Subsurface Scale");
return (subsurface_weight_in->link != NULL || subsurface_weight > CLOSURE_WEIGHT_CUTOFF) &&
(subsurface_scale_in->link != NULL || subsurface_scale != 0.0f);
}
void PrincipledBsdfNode::attributes(Shader *shader, AttributeRequestSet *attributes)
@ -2791,7 +2799,7 @@ void PrincipledBsdfNode::compile(SVMCompiler &compiler)
ShaderInput *base_color_in = input("Base Color");
ShaderInput *p_metallic = input("Metallic");
ShaderInput *p_subsurface = input("Subsurface");
ShaderInput *p_subsurface_weight = input("Subsurface Weight");
ShaderInput *emission_strength_in = input("Emission Strength");
ShaderInput *alpha_in = input("Alpha");
@ -2803,19 +2811,19 @@ void PrincipledBsdfNode::compile(SVMCompiler &compiler)
int normal_offset = compiler.stack_assign_if_linked(input("Normal"));
int coat_normal_offset = compiler.stack_assign_if_linked(input("Coat Normal"));
int tangent_offset = compiler.stack_assign_if_linked(input("Tangent"));
int specular_offset = compiler.stack_assign(input("Specular"));
int specular_ior_level_offset = compiler.stack_assign(input("Specular IOR Level"));
int roughness_offset = compiler.stack_assign(input("Roughness"));
int specular_tint_offset = compiler.stack_assign(input("Specular Tint"));
int anisotropic_offset = compiler.stack_assign(input("Anisotropic"));
int sheen_offset = compiler.stack_assign(input("Sheen"));
int sheen_weight_offset = compiler.stack_assign(input("Sheen Weight"));
int sheen_roughness_offset = compiler.stack_assign(input("Sheen Roughness"));
int sheen_tint_offset = compiler.stack_assign(input("Sheen Tint"));
int coat_offset = compiler.stack_assign(input("Coat"));
int coat_weight_offset = compiler.stack_assign(input("Coat Weight"));
int coat_roughness_offset = compiler.stack_assign(input("Coat Roughness"));
int coat_ior_offset = compiler.stack_assign(input("Coat IOR"));
int coat_tint_offset = compiler.stack_assign(input("Coat Tint"));
int ior_offset = compiler.stack_assign(input("IOR"));
int transmission_offset = compiler.stack_assign(input("Transmission"));
int transmission_weight_offset = compiler.stack_assign(input("Transmission Weight"));
int anisotropic_rotation_offset = compiler.stack_assign(input("Anisotropic Rotation"));
int subsurface_radius_offset = compiler.stack_assign(input("Subsurface Radius"));
int subsurface_scale_offset = compiler.stack_assign(input("Subsurface Scale"));
@ -2823,31 +2831,31 @@ void PrincipledBsdfNode::compile(SVMCompiler &compiler)
int subsurface_anisotropy_offset = compiler.stack_assign(input("Subsurface Anisotropy"));
int alpha_offset = compiler.stack_assign_if_linked(alpha_in);
int emission_strength_offset = compiler.stack_assign_if_linked(emission_strength_in);
int emission_offset = compiler.stack_assign(input("Emission"));
int emission_color_offset = compiler.stack_assign(input("Emission Color"));
compiler.add_node(NODE_CLOSURE_BSDF,
compiler.encode_uchar4(closure,
compiler.stack_assign(p_metallic),
compiler.stack_assign(p_subsurface),
compiler.closure_mix_weight_offset()),
__float_as_int((p_metallic) ? get_float(p_metallic->socket_type) : 0.0f),
__float_as_int((p_subsurface) ? get_float(p_subsurface->socket_type) : 0.0f));
compiler.add_node(
NODE_CLOSURE_BSDF,
compiler.encode_uchar4(closure,
compiler.stack_assign(p_metallic),
compiler.stack_assign(p_subsurface_weight),
compiler.closure_mix_weight_offset()),
__float_as_int((p_metallic) ? get_float(p_metallic->socket_type) : 0.0f),
__float_as_int((p_subsurface_weight) ? get_float(p_subsurface_weight->socket_type) : 0.0f));
compiler.add_node(
normal_offset,
tangent_offset,
compiler.encode_uchar4(
specular_offset, roughness_offset, specular_tint_offset, anisotropic_offset),
compiler.encode_uchar4(
sheen_offset, sheen_tint_offset, sheen_roughness_offset, SVM_STACK_INVALID));
specular_ior_level_offset, roughness_offset, specular_tint_offset, anisotropic_offset),
compiler.encode_uchar4(sheen_weight_offset, sheen_tint_offset, sheen_roughness_offset));
compiler.add_node(
compiler.encode_uchar4(
ior_offset, transmission_offset, anisotropic_rotation_offset, coat_normal_offset),
ior_offset, transmission_weight_offset, anisotropic_rotation_offset, coat_normal_offset),
distribution,
subsurface_method,
compiler.encode_uchar4(
coat_offset, coat_roughness_offset, coat_ior_offset, coat_tint_offset));
coat_weight_offset, coat_roughness_offset, coat_ior_offset, coat_tint_offset));
float3 bc_default = get_float3(base_color_in->socket_type);
@ -2864,7 +2872,7 @@ void PrincipledBsdfNode::compile(SVMCompiler &compiler)
compiler.add_node(
compiler.encode_uchar4(
alpha_offset, emission_strength_offset, emission_offset, SVM_STACK_INVALID),
alpha_offset, emission_strength_offset, emission_color_offset, SVM_STACK_INVALID),
__float_as_int(get_float(alpha_in->socket_type)),
__float_as_int(get_float(emission_strength_in->socket_type)),
SVM_STACK_INVALID);
@ -2953,8 +2961,8 @@ NODE_DEFINE(SubsurfaceScatteringNode)
static NodeEnum method_enum;
method_enum.insert("burley", CLOSURE_BSSRDF_BURLEY_ID);
method_enum.insert("random_walk_fixed_radius", CLOSURE_BSSRDF_RANDOM_WALK_FIXED_RADIUS_ID);
method_enum.insert("random_walk", CLOSURE_BSSRDF_RANDOM_WALK_ID);
method_enum.insert("random_walk_skin", CLOSURE_BSSRDF_RANDOM_WALK_SKIN_ID);
SOCKET_ENUM(method, "Method", method_enum, CLOSURE_BSSRDF_RANDOM_WALK_ID);
SOCKET_IN_FLOAT(scale, "Scale", 0.01f);

View File

@ -519,35 +519,35 @@ class PrincipledBsdfNode : public BsdfBaseNode {
void simplify_settings(Scene *scene);
NODE_SOCKET_API(float3, base_color)
NODE_SOCKET_API(float, metallic)
NODE_SOCKET_API(float, roughness)
NODE_SOCKET_API(float, ior)
NODE_SOCKET_API(float3, normal)
NODE_SOCKET_API(float, alpha)
NODE_SOCKET_API(ClosureType, subsurface_method)
NODE_SOCKET_API(float, subsurface_weight)
NODE_SOCKET_API(float3, subsurface_radius)
NODE_SOCKET_API(float, subsurface_scale)
NODE_SOCKET_API(float, subsurface_ior)
NODE_SOCKET_API(float, subsurface_anisotropy)
NODE_SOCKET_API(float, metallic)
NODE_SOCKET_API(float, subsurface)
NODE_SOCKET_API(float, specular)
NODE_SOCKET_API(float, roughness)
NODE_SOCKET_API(float, specular_tint)
NODE_SOCKET_API(ClosureType, distribution)
NODE_SOCKET_API(float, specular_ior_level)
NODE_SOCKET_API(float3, specular_tint)
NODE_SOCKET_API(float, anisotropic)
NODE_SOCKET_API(float, sheen)
NODE_SOCKET_API(float, anisotropic_rotation)
NODE_SOCKET_API(float3, tangent)
NODE_SOCKET_API(float, transmission_weight)
NODE_SOCKET_API(float, sheen_weight)
NODE_SOCKET_API(float, sheen_roughness)
NODE_SOCKET_API(float3, sheen_tint)
NODE_SOCKET_API(float, coat)
NODE_SOCKET_API(float, coat_weight)
NODE_SOCKET_API(float, coat_roughness)
NODE_SOCKET_API(float, coat_ior)
NODE_SOCKET_API(float3, coat_tint)
NODE_SOCKET_API(float, ior)
NODE_SOCKET_API(float, transmission)
NODE_SOCKET_API(float, anisotropic_rotation)
NODE_SOCKET_API(float3, normal)
NODE_SOCKET_API(float3, coat_normal)
NODE_SOCKET_API(float3, tangent)
NODE_SOCKET_API(float, surface_mix_weight)
NODE_SOCKET_API(ClosureType, distribution)
NODE_SOCKET_API(ClosureType, subsurface_method)
NODE_SOCKET_API(float3, emission)
NODE_SOCKET_API(float3, emission_color)
NODE_SOCKET_API(float, emission_strength)
NODE_SOCKET_API(float, alpha)
NODE_SOCKET_API(float, surface_mix_weight)
public:
void attributes(Shader *shader, AttributeRequestSet *attributes);

View File

@ -135,9 +135,11 @@ class SVMCompiler {
bool empty()
{
for (int i = 0; i < SVM_STACK_SIZE; i++)
if (users[i])
for (int i = 0; i < SVM_STACK_SIZE; i++) {
if (users[i]) {
return false;
}
}
return true;
}
@ -146,8 +148,9 @@ class SVMCompiler {
{
printf("stack <");
for (int i = 0; i < SVM_STACK_SIZE; i++)
for (int i = 0; i < SVM_STACK_SIZE; i++) {
printf((users[i]) ? "*" : " ");
}
printf(">\n");
}

View File

@ -92,8 +92,9 @@ class BoundBox {
/* todo: avoid using this */
__forceinline float safe_area() const
{
if (!((min.x <= max.x) && (min.y <= max.y) && (min.z <= max.z)))
if (!((min.x <= max.x) && (min.y <= max.y) && (min.z <= max.z))) {
return 0.0f;
}
return area();
}

View File

@ -61,18 +61,22 @@ ccl_device_inline float4 color_uchar4_to_float4(uchar4 c)
ccl_device float color_srgb_to_linear(float c)
{
if (c < 0.04045f)
if (c < 0.04045f) {
return (c < 0.0f) ? 0.0f : c * (1.0f / 12.92f);
else
}
else {
return powf((c + 0.055f) * (1.0f / 1.055f), 2.4f);
}
}
ccl_device float color_linear_to_srgb(float c)
{
if (c < 0.0031308f)
if (c < 0.0031308f) {
return (c < 0.0f) ? 0.0f : c * 12.92f;
else
}
else {
return 1.055f * powf(c, 1.0f / 2.4f) - 0.055f;
}
}
ccl_device float3 rgb_to_hsv(float3 rgb)
@ -98,17 +102,21 @@ ccl_device float3 rgb_to_hsv(float3 rgb)
float3 cmax3 = make_float3(cmax, cmax, cmax);
c = (cmax3 - rgb) / cdelta;
if (rgb.x == cmax)
if (rgb.x == cmax) {
h = c.z - c.y;
else if (rgb.y == cmax)
}
else if (rgb.y == cmax) {
h = 2.0f + c.x - c.z;
else
}
else {
h = 4.0f + c.y - c.x;
}
h /= 6.0f;
if (h < 0.0f)
if (h < 0.0f) {
h += 1.0f;
}
}
else {
h = 0.0f;
@ -127,8 +135,9 @@ ccl_device float3 hsv_to_rgb(float3 hsv)
v = hsv.z;
if (s != 0.0f) {
if (h == 1.0f)
if (h == 1.0f) {
h = 0.0f;
}
h *= 6.0f;
i = floorf(h);
@ -138,18 +147,24 @@ ccl_device float3 hsv_to_rgb(float3 hsv)
q = v * (1.0f - (s * f));
t = v * (1.0f - (s * (1.0f - f)));
if (i == 0.0f)
if (i == 0.0f) {
rgb = make_float3(v, t, p);
else if (i == 1.0f)
}
else if (i == 1.0f) {
rgb = make_float3(q, v, p);
else if (i == 2.0f)
}
else if (i == 2.0f) {
rgb = make_float3(p, v, t);
else if (i == 3.0f)
}
else if (i == 3.0f) {
rgb = make_float3(p, q, v);
else if (i == 4.0f)
}
else if (i == 4.0f) {
rgb = make_float3(t, p, v);
else
}
else {
rgb = make_float3(v, p, q);
}
}
else {
rgb = make_float3(v, v, v);
@ -212,15 +227,19 @@ ccl_device float3 xyY_to_xyz(float x, float y, float Y)
{
float X, Z;
if (y != 0.0f)
if (y != 0.0f) {
X = (x / y) * Y;
else
}
else {
X = 0.0f;
}
if (y != 0.0f && Y != 0.0f)
if (y != 0.0f && Y != 0.0f) {
Z = (1.0f - x - y) / y * Y;
else
}
else {
Z = 0.0f;
}
return make_float3(X, Y, Z);
}

View File

@ -500,8 +500,9 @@ static inline uint hash_string(const char *str)
{
uint i = 0, c;
while ((c = *str++))
while ((c = *str++)) {
i = i * 37 + c;
}
return i;
}

View File

@ -382,10 +382,12 @@ ccl_device_inline float mix(float a, float b, float t)
ccl_device_inline float smoothstep(float edge0, float edge1, float x)
{
float result;
if (x < edge0)
if (x < edge0) {
result = 0.0f;
else if (x >= edge1)
}
else if (x >= edge1) {
result = 1.0f;
}
else {
float t = (x - edge0) / (edge1 - edge0);
result = (3.0f - 2.0f * t) * (t * t);
@ -464,10 +466,12 @@ ccl_device_inline float signf(float f)
ccl_device_inline float nonzerof(float f, float eps)
{
if (fabsf(f) < eps)
if (fabsf(f) < eps) {
return signf(f) * eps;
else
}
else {
return f;
}
}
/* `signum` function testing for zero. Matches GLSL and OSL functions. */
@ -620,16 +624,18 @@ ccl_device_inline float3 safe_divide_even_color(float3 a, float3 b)
x = y;
z = y;
}
else
else {
x = 0.5f * (y + z);
}
}
else if (b.y == 0.0f) {
if (b.z == 0.0f) {
y = x;
z = x;
}
else
else {
y = 0.5f * (x + z);
}
}
else if (b.z == 0.0f) {
z = 0.5f * (x + y);
@ -708,8 +714,9 @@ ccl_device float compatible_powf(float x, float y)
ccl_device float safe_powf(float a, float b)
{
if (UNLIKELY(a < 0.0f && b != float_to_int(b)))
if (UNLIKELY(a < 0.0f && b != float_to_int(b))) {
return 0.0f;
}
return compatible_powf(a, b);
}
@ -721,8 +728,9 @@ ccl_device float safe_divide(float a, float b)
ccl_device float safe_logf(float a, float b)
{
if (UNLIKELY(a <= 0.0f || b <= 0.0f))
if (UNLIKELY(a <= 0.0f || b <= 0.0f)) {
return 0.0f;
}
return safe_divide(logf(a), logf(b));
}

View File

@ -304,8 +304,9 @@ ccl_device void math_matrix_jacobi_eigendecomposition(ccl_private float *A,
if (abs_element > singular_epsilon * fabsf(singular_diff)) {
float cot_2phi = 0.5f * singular_diff / element;
ratio = 1.0f / (fabsf(cot_2phi) + sqrtf(1.0f + cot_2phi * cot_2phi));
if (cot_2phi < 0.0f)
if (cot_2phi < 0.0f) {
ratio = -ratio; /* Copy sign. */
}
}
else {
ratio = element / singular_diff;

View File

@ -386,8 +386,9 @@ __forceinline uint64_t bitscan(uint64_t v)
__forceinline uint32_t __bsf(const uint32_t x)
{
for (int i = 0; i < 32; i++) {
if (x & (1U << i))
if (x & (1U << i)) {
return i;
}
}
return 32;
}
@ -395,8 +396,9 @@ __forceinline uint32_t __bsf(const uint32_t x)
__forceinline uint32_t __bsr(const uint32_t x)
{
for (int i = 0; i < 32; i++) {
if (x & (1U << (31 - i)))
if (x & (1U << (31 - i))) {
return (31 - i);
}
}
return 32;
}
@ -410,8 +412,9 @@ __forceinline uint32_t __btc(const uint32_t x, const uint32_t bit)
__forceinline uint32_t __bsf(const uint64_t x)
{
for (int i = 0; i < 64; i++) {
if (x & (1UL << i))
if (x & (1UL << i)) {
return i;
}
}
return 64;
}
@ -419,8 +422,9 @@ __forceinline uint32_t __bsf(const uint64_t x)
__forceinline uint32_t __bsr(const uint64_t x)
{
for (int i = 0; i < 64; i++) {
if (x & (1UL << (63 - i)))
if (x & (1UL << (63 - i))) {
return (63 - i);
}
}
return 64;
}

View File

@ -155,7 +155,7 @@ static CPUCapabilities &system_cpu_capabilities()
const bool ssse3 = (result[2] & ((int)1 << 9)) != 0;
const bool sse41 = (result[2] & ((int)1 << 19)) != 0;
/* const bool sse42 = (result[2] & ((int)1 << 20)) != 0; */
// const bool sse42 = (result[2] & ((int)1 << 20)) != 0;
const bool fma3 = (result[2] & ((int)1 << 12)) != 0;
const bool os_uses_xsave_xrestore = (result[2] & ((int)1 << 27)) != 0;

View File

@ -19,8 +19,9 @@ class Cubes {
/// Get a triangle
void getTriangle(int mask, int index, int indices[3])
{
for (int i = 0; i < 3; i++)
for (int i = 0; i < 3; i++) {
indices[i] = marching_cubes_tris[mask][index][i];
}
}
#ifdef WITH_CXX_GUARDEDALLOC

View File

@ -509,10 +509,12 @@ class Octree {
{
printf("INFO AT: %d %d %d\n", st[0] >> minshift, st[1] >> minshift, st[2] >> minshift);
LeafNode *leaf = (LeafNode *)locateLeafCheck(st);
if (leaf)
if (leaf) {
printInfo(leaf);
else
}
else {
printf("Leaf not exists!\n");
}
}
void printInfo(const LeafNode *leaf)

View File

@ -74,8 +74,9 @@ class GHOST_EventDragnDrop : public GHOST_Event {
~GHOST_EventDragnDrop()
{
/* Free the dropped object data. */
if (m_dragnDropEventData.data == nullptr)
if (m_dragnDropEventData.data == nullptr) {
return;
}
switch (m_dragnDropEventData.dataType) {
case GHOST_kDragnDropTypeBitmap:
@ -85,12 +86,14 @@ class GHOST_EventDragnDrop : public GHOST_Event {
GHOST_TStringArray *strArray = (GHOST_TStringArray *)m_dragnDropEventData.data;
int i;
for (i = 0; i < strArray->count; i++)
for (i = 0; i < strArray->count; i++) {
free(strArray->strings[i]);
}
free(strArray->strings);
free(strArray);
} break;
break;
}
case GHOST_kDragnDropTypeString:
free(m_dragnDropEventData.data);
break;

View File

@ -34,7 +34,8 @@ class GHOST_EventString : public GHOST_Event {
~GHOST_EventString()
{
if (m_data)
if (m_data) {
free(m_data);
}
}
};

View File

@ -2537,7 +2537,7 @@ static void data_device_handle_drop(void *data, wl_data_device * /*wl_data_devic
flist->count = int(uris.size());
flist->strings = static_cast<uint8_t **>(malloc(uris.size() * sizeof(uint8_t *)));
for (size_t i = 0; i < uris.size(); i++) {
flist->strings[i] = (uint8_t *)GHOST_URL_decode_alloc(uris[i].c_str());
flist->strings[i] = reinterpret_cast<uint8_t *>(GHOST_URL_decode_alloc(uris[i].c_str()));
}
CLOG_INFO(LOG, 2, "drop_read_uris_fn file_count=%d", flist->count);
@ -3688,7 +3688,8 @@ static void tablet_seat_handle_tool_added(void *data,
tablet_tool->wl.surface_cursor = wl_compositor_create_surface(seat->system->wl_compositor_get());
ghost_wl_surface_tag_cursor_tablet(tablet_tool->wl.surface_cursor);
wl_surface_add_listener(tablet_tool->wl.surface_cursor, &cursor_surface_listener, (void *)seat);
wl_surface_add_listener(
tablet_tool->wl.surface_cursor, &cursor_surface_listener, static_cast<void *>(seat));
zwp_tablet_tool_v2_add_listener(id, &tablet_tool_listner, tablet_tool);
@ -5582,16 +5583,16 @@ static void gwl_display_event_thread_destroy(GWL_Display *display)
* \{ */
GHOST_SystemWayland::GHOST_SystemWayland(bool background)
: GHOST_System(), display_(new GWL_Display)
: GHOST_System(),
#ifdef USE_EVENT_BACKGROUND_THREAD
server_mutex(new std::mutex),
timer_mutex(new std::mutex),
main_thread_id(std::this_thread::get_id()),
#endif
display_(new GWL_Display)
{
wl_log_set_handler_client(ghost_wayland_log_handler);
#ifdef USE_EVENT_BACKGROUND_THREAD
server_mutex = new std::mutex;
timer_mutex = new std::mutex;
main_thread_id = std::this_thread::get_id();
#endif
display_->system = this;
/* Connect to the Wayland server. */
display_->wl.display = wl_display_connect(nullptr);
@ -6416,12 +6417,13 @@ GHOST_TSuccess GHOST_SystemWayland::disposeContext(GHOST_IContext *context)
#ifdef USE_EVENT_BACKGROUND_THREAD
std::lock_guard lock_server_guard{*server_mutex};
#endif
wl_surface *wl_surface = (struct wl_surface *)((GHOST_Context *)context)->getUserData();
wl_surface *wl_surface = static_cast<struct wl_surface *>(
(static_cast<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 *egl_window = static_cast<wl_egl_window *>(wl_surface_get_user_data(wl_surface));
if (egl_window != nullptr) {
wl_egl_window_destroy(egl_window);
}
@ -6811,7 +6813,7 @@ GHOST_TSuccess GHOST_SystemWayland::cursor_bitmap_get(GHOST_CursorBitmapRef *bit
bitmap->hot_spot[0] = cursor->wl.image.hotspot_x;
bitmap->hot_spot[1] = cursor->wl.image.hotspot_y;
bitmap->data = (uint8_t *)static_cast<void *>(cursor->custom_data);
bitmap->data = static_cast<uint8_t *>(cursor->custom_data);
return GHOST_kSuccess;
}
@ -6923,12 +6925,14 @@ static const char *ghost_wl_surface_cursor_tablet_tag_id = "GHOST-cursor-tablet"
bool ghost_wl_output_own(const wl_output *wl_output)
{
return wl_proxy_get_tag((wl_proxy *)wl_output) == &ghost_wl_output_tag_id;
const wl_proxy *proxy = reinterpret_cast<const wl_proxy *>(wl_output);
return wl_proxy_get_tag(const_cast<wl_proxy *>(proxy)) == &ghost_wl_output_tag_id;
}
bool ghost_wl_surface_own(const wl_surface *wl_surface)
{
return wl_proxy_get_tag((wl_proxy *)wl_surface) == &ghost_wl_surface_tag_id;
const wl_proxy *proxy = reinterpret_cast<const wl_proxy *>(wl_surface);
return wl_proxy_get_tag(const_cast<wl_proxy *>(proxy)) == &ghost_wl_surface_tag_id;
}
bool ghost_wl_surface_own_with_null_check(const wl_surface *wl_surface)
@ -6938,32 +6942,39 @@ bool ghost_wl_surface_own_with_null_check(const wl_surface *wl_surface)
bool ghost_wl_surface_own_cursor_pointer(const wl_surface *wl_surface)
{
return wl_proxy_get_tag((wl_proxy *)wl_surface) == &ghost_wl_surface_cursor_pointer_tag_id;
const wl_proxy *proxy = reinterpret_cast<const wl_proxy *>(wl_surface);
return wl_proxy_get_tag(const_cast<wl_proxy *>(proxy)) ==
&ghost_wl_surface_cursor_pointer_tag_id;
}
bool ghost_wl_surface_own_cursor_tablet(const wl_surface *wl_surface)
{
return wl_proxy_get_tag((wl_proxy *)wl_surface) == &ghost_wl_surface_cursor_tablet_tag_id;
const wl_proxy *proxy = reinterpret_cast<const wl_proxy *>(wl_surface);
return wl_proxy_get_tag(const_cast<wl_proxy *>(proxy)) == &ghost_wl_surface_cursor_tablet_tag_id;
}
void ghost_wl_output_tag(wl_output *wl_output)
{
wl_proxy_set_tag((wl_proxy *)wl_output, &ghost_wl_output_tag_id);
wl_proxy *proxy = reinterpret_cast<wl_proxy *>(wl_output);
wl_proxy_set_tag(proxy, &ghost_wl_output_tag_id);
}
void ghost_wl_surface_tag(wl_surface *wl_surface)
{
wl_proxy_set_tag((wl_proxy *)wl_surface, &ghost_wl_surface_tag_id);
wl_proxy *proxy = reinterpret_cast<wl_proxy *>(wl_surface);
wl_proxy_set_tag(proxy, &ghost_wl_surface_tag_id);
}
void ghost_wl_surface_tag_cursor_pointer(wl_surface *wl_surface)
{
wl_proxy_set_tag((wl_proxy *)wl_surface, &ghost_wl_surface_cursor_pointer_tag_id);
wl_proxy *proxy = reinterpret_cast<wl_proxy *>(wl_surface);
wl_proxy_set_tag(proxy, &ghost_wl_surface_cursor_pointer_tag_id);
}
void ghost_wl_surface_tag_cursor_tablet(wl_surface *wl_surface)
{
wl_proxy_set_tag((wl_proxy *)wl_surface, &ghost_wl_surface_cursor_tablet_tag_id);
wl_proxy *proxy = reinterpret_cast<wl_proxy *>(wl_surface);
wl_proxy_set_tag(proxy, &ghost_wl_surface_cursor_tablet_tag_id);
}
/** \} */
@ -7357,10 +7368,11 @@ bool GHOST_SystemWayland::window_cursor_grab_set(const GHOST_TGrabCursorMode mod
if (mode != GHOST_kGrabDisable) {
if (grab_state_next.use_lock) {
if (!grab_state_prev.use_lock) {
/* TODO(@ideasman42): As WAYLAND does not support warping the pointer it may not be
* possible to support #GHOST_kGrabWrap by pragmatically settings it's coordinates.
* An alternative could be to draw the cursor in software (and hide the real cursor),
* or just accept a locked cursor on WAYLAND. */
/* As WAYLAND does not support setting the cursor coordinates programmatically,
* #GHOST_kGrabWrap cannot be supported by positioning the cursor directly.
* Instead the cursor is locked in place, using a software cursor that is warped.
* Then WAYLAND's #zwp_locked_pointer_v1_set_cursor_position_hint is used to restore
* the cursor to the warped location. */
seat->wp.relative_pointer = zwp_relative_pointer_manager_v1_get_relative_pointer(
display_->wp.relative_pointer_manager, seat->wl.pointer);
zwp_relative_pointer_v1_add_listener(

View File

@ -16,6 +16,7 @@
*/
# define WL_ARRAY_FOR_EACH(pos, array) \
for (pos = (decltype(pos))((array)->data); \
(const char *)pos < ((const char *)(array)->data + (array)->size); \
reinterpret_cast<const char *>(pos) < \
(reinterpret_cast<const char *>((array)->data) + (array)->size); \
(pos)++)
#endif

View File

@ -62,7 +62,9 @@ static constexpr size_t base_dpi = 96;
#ifdef WITH_GHOST_WAYLAND_LIBDECOR
struct WGL_LibDecor_Window {
libdecor_frame *frame = nullptr;
bool configured = false;
/** The window has been configured (see #xdg_surface_ack_configure). */
bool initial_configure_seen = false;
};
static void gwl_libdecor_window_destroy(WGL_LibDecor_Window *decor)
@ -88,6 +90,9 @@ struct WGL_XDG_Decor_Window {
/** The serial to pass to ACK configure. */
uint32_t ack_configure_serial = 0;
} pending;
/** The window has been configured (see #xdg_surface_ack_configure). */
bool initial_configure_seen = false;
};
static void gwl_xdg_decor_window_destroy(WGL_XDG_Decor_Window *decor)
@ -776,6 +781,8 @@ static void gwl_window_frame_update_from_pending_no_lock(GWL_Window *win)
decor.pending.ack_configure = false;
decor.pending.ack_configure_serial = 0;
decor.initial_configure_seen = true;
}
}
@ -1111,11 +1118,11 @@ static void libdecor_frame_handle_configure(libdecor_frame *frame,
/* Commit the changes. */
{
GWL_Window *win = static_cast<GWL_Window *>(data);
WGL_LibDecor_Window &decor = *win->libdecor;
libdecor_state *state = libdecor_state_new(UNPACK2(size_next));
libdecor_frame_commit(frame, state, configuration);
libdecor_state_free(state);
win->libdecor->configured = true;
decor.initial_configure_seen = true;
}
/* Apply the changes. */
@ -1411,15 +1418,6 @@ GHOST_WindowWayland::GHOST_WindowWayland(GHOST_SystemWayland *system,
xdg_toplevel_set_min_size(decor.toplevel, UNPACK2(size_min));
xdg_toplevel_set_app_id(decor.toplevel, xdg_app_id);
if (system_->xdg_decor_manager_get()) {
decor.toplevel_decor = zxdg_decoration_manager_v1_get_toplevel_decoration(
system_->xdg_decor_manager_get(), decor.toplevel);
zxdg_toplevel_decoration_v1_add_listener(
decor.toplevel_decor, &xdg_toplevel_decoration_v1_listener, window_);
zxdg_toplevel_decoration_v1_set_mode(decor.toplevel_decor,
ZXDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE);
}
xdg_surface_add_listener(decor.surface, &xdg_surface_listener, window_);
xdg_toplevel_add_listener(decor.toplevel, &xdg_toplevel_listener, window_);
@ -1436,12 +1434,14 @@ GHOST_WindowWayland::GHOST_WindowWayland(GHOST_SystemWayland *system,
/* Call top-level callbacks. */
wl_surface_commit(window_->wl.surface);
wl_display_roundtrip(system_->wl_display_get());
#ifdef GHOST_OPENGL_ALPHA
setOpaque();
#endif
/* NOTE: the method used for XDG & LIBDECOR initialization (using `initial_configure_seen`)
* follows the method used in SDL 3.16. */
/* Causes a glitch with `libdecor` for some reason. */
#ifdef WITH_GHOST_WAYLAND_LIBDECOR
if (use_libdecor) {
@ -1451,12 +1451,33 @@ GHOST_WindowWayland::GHOST_WindowWayland(GHOST_SystemWayland *system,
/* NOTE: LIBDECOR requires the window to be created & configured before the state can be set.
* Workaround this by using the underlying `xdg_toplevel` */
WGL_LibDecor_Window &decor = *window_->libdecor;
while (!decor.initial_configure_seen) {
wl_display_flush(system->wl_display_get());
wl_display_dispatch(system->wl_display_get());
}
xdg_toplevel *toplevel = libdecor_frame_get_xdg_toplevel(decor.frame);
gwl_window_state_set_for_xdg(toplevel, state, GHOST_kWindowStateNormal);
}
else
#endif
#endif /* WITH_GHOST_WAYLAND_LIBDECOR */
{
/* Call top-level callbacks. */
WGL_XDG_Decor_Window &decor = *window_->xdg_decor;
while (!decor.initial_configure_seen) {
wl_display_flush(system->wl_display_get());
wl_display_dispatch(system->wl_display_get());
}
if (system_->xdg_decor_manager_get()) {
decor.toplevel_decor = zxdg_decoration_manager_v1_get_toplevel_decoration(
system_->xdg_decor_manager_get(), decor.toplevel);
zxdg_toplevel_decoration_v1_add_listener(
decor.toplevel_decor, &xdg_toplevel_decoration_v1_listener, window_);
zxdg_toplevel_decoration_v1_set_mode(decor.toplevel_decor,
ZXDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE);
}
gwl_window_state_set(window_, state);
}

View File

@ -297,7 +297,8 @@ bool processEvent(GHOST_EventHandle hEvent, GHOST_TUserDataPtr userData)
else {
view_rotz -= 5.f;
}
} break;
break;
}
case GHOST_kEventKeyUp:
break;
@ -313,7 +314,8 @@ bool processEvent(GHOST_EventHandle hEvent, GHOST_TUserDataPtr userData)
}
sCursor = (GHOST_TStandardCursor)cursor;
GHOST_SetCursorShape(window, sCursor);
} break;
break;
}
case GHOST_kKeyF:
if (!GHOST_GetFullScreen(shSystem)) {
/* Begin full-screen mode. */
@ -342,7 +344,8 @@ bool processEvent(GHOST_EventHandle hEvent, GHOST_TUserDataPtr userData)
case GHOST_kKeyH: {
visibility = GHOST_GetCursorVisibility(window);
GHOST_SetCursorVisibility(window, !visibility);
} break;
break;
}
case GHOST_kKeyQ:
if (GHOST_GetFullScreen(shSystem)) {
GHOST_EndFullScreen(shSystem);
@ -369,11 +372,13 @@ bool processEvent(GHOST_EventHandle hEvent, GHOST_TUserDataPtr userData)
free(ntitle);
free(title);
}
} break;
break;
}
default:
break;
}
} break;
break;
}
case GHOST_kEventWindowClose: {
GHOST_WindowHandle window2 = GHOST_GetEventWindow(hEvent);
@ -387,7 +392,8 @@ bool processEvent(GHOST_EventHandle hEvent, GHOST_TUserDataPtr userData)
}
GHOST_DisposeWindow(shSystem, window2);
}
} break;
break;
}
case GHOST_kEventWindowActivate:
handled = false;
@ -403,8 +409,8 @@ bool processEvent(GHOST_EventHandle hEvent, GHOST_TUserDataPtr userData)
setViewPortGL(window2);
drawGL();
GHOST_SwapWindowBuffers(window2);
} break;
break;
}
default:
handled = false;
break;

View File

@ -467,8 +467,8 @@ bool Application::processEvent(GHOST_IEvent *event)
else {
view_rotz -= 5.f;
}
} break;
break;
}
case GHOST_kEventKeyUp:
break;
@ -483,7 +483,8 @@ bool Application::processEvent(GHOST_IEvent *event)
}
m_cursor = (GHOST_TStandardCursor)cursor;
window->setCursorShape(m_cursor);
} break;
break;
}
case GHOST_kKeyE: {
int x = 200, y = 200;
@ -538,7 +539,8 @@ bool Application::processEvent(GHOST_IEvent *event)
if (down) {
std::cout << "right control down\n";
}
} break;
break;
}
case GHOST_kKeyQ:
if (m_system->getFullScreen()) {
@ -580,7 +582,8 @@ bool Application::processEvent(GHOST_IEvent *event)
default:
break;
}
} break;
break;
}
case GHOST_kEventWindowClose: {
GHOST_IWindow *window2 = event->getWindow();
@ -590,7 +593,8 @@ bool Application::processEvent(GHOST_IEvent *event)
else {
m_system->disposeWindow(window2);
}
} break;
break;
}
case GHOST_kEventWindowActivate:
handled = false;
@ -629,7 +633,8 @@ bool Application::processEvent(GHOST_IEvent *event)
glPopMatrix();
}
window2->swapBuffers();
} break;
break;
}
default:
handled = false;

View File

@ -56,12 +56,15 @@ static inline Eigen::Matrix3d CreateMatrix(double xx,
static inline Eigen::Matrix3d RotationMatrix(double sine, double cosine, int axis)
{
if (axis == 0)
if (axis == 0) {
return CreateMatrix(1.0, 0.0, 0.0, 0.0, cosine, -sine, 0.0, sine, cosine);
else if (axis == 1)
}
else if (axis == 1) {
return CreateMatrix(cosine, 0.0, sine, 0.0, 1.0, 0.0, -sine, 0.0, cosine);
else
}
else {
return CreateMatrix(cosine, -sine, 0.0, sine, cosine, 0.0, 0.0, 0.0, 1.0);
}
}
static inline Eigen::Matrix3d RotationMatrix(double angle, int axis)
@ -74,32 +77,41 @@ static inline double EulerAngleFromMatrix(const Eigen::Matrix3d &R, int axis)
double t = sqrt(R(0, 0) * R(0, 0) + R(0, 1) * R(0, 1));
if (t > 16.0 * IK_EPSILON) {
if (axis == 0)
if (axis == 0) {
return -atan2(R(1, 2), R(2, 2));
else if (axis == 1)
}
else if (axis == 1) {
return atan2(-R(0, 2), t);
else
}
else {
return -atan2(R(0, 1), R(0, 0));
}
}
else {
if (axis == 0)
if (axis == 0) {
return -atan2(-R(2, 1), R(1, 1));
else if (axis == 1)
}
else if (axis == 1) {
return atan2(-R(0, 2), t);
else
}
else {
return 0.0f;
}
}
}
static inline double safe_acos(double f)
{
// acos that does not return NaN with rounding errors
if (f <= -1.0)
if (f <= -1.0) {
return M_PI;
else if (f >= 1.0)
}
else if (f >= 1.0) {
return 0.0;
else
}
else {
return acos(f);
}
}
static inline Eigen::Vector3d normalize(const Eigen::Vector3d &v)
@ -152,11 +164,12 @@ static inline Eigen::Vector3d SphericalRangeParameters(const Eigen::Matrix3d &R)
double num = 2.0 * (1.0 + R(1, 1));
// singularity at pi
if (fabs(num) < IK_EPSILON)
if (fabs(num) < IK_EPSILON) {
// TODO: this does now rotation of size pi over z axis, but could
// be any axis, how to deal with this I'm not sure, maybe don't
// enforce limits at all then.
return Eigen::Vector3d(0.0, tau, 1.0);
}
num = 1.0 / sqrt(num);
double ax = -R(2, 1) * num;
@ -184,8 +197,9 @@ static inline Eigen::Vector3d MatrixToAxisAngle(const Eigen::Matrix3d &R)
double c = safe_acos((R(0, 0) + R(1, 1) + R(2, 2) - 1) / 2);
double l = delta.norm();
if (!FuzzyZero(l))
if (!FuzzyZero(l)) {
delta *= c / l;
}
return delta;
}
@ -213,20 +227,24 @@ static inline bool EllipseClamp(double &ax, double &az, double *amin, double *am
}
if (FuzzyZero(xlim) || FuzzyZero(zlim)) {
if (x <= xlim && z <= zlim)
if (x <= xlim && z <= zlim) {
return false;
}
if (x > xlim)
if (x > xlim) {
x = xlim;
if (z > zlim)
}
if (z > zlim) {
z = zlim;
}
}
else {
double invx = 1.0 / (xlim * xlim);
double invz = 1.0 / (zlim * zlim);
if ((x * x * invx + z * z * invz) <= 1.0)
if ((x * x * invx + z * z * invz) <= 1.0) {
return false;
}
if (FuzzyZero(x)) {
x = 0.0;
@ -236,8 +254,9 @@ static inline bool EllipseClamp(double &ax, double &az, double *amin, double *am
double rico = z / x;
double old_x = x;
x = sqrt(1.0 / (invx + invz * rico * rico));
if (old_x < 0.0)
if (old_x < 0.0) {
x = -x;
}
z = rico * x;
}
}

View File

@ -174,8 +174,9 @@ class ArrayND : public BaseArray {
/// Return the number of elements of the array.
int Size() const {
int size = 1;
for (int i = 0; i < N; ++i)
for (int i = 0; i < N; ++i) {
size *= Shape(i);
}
return size;
}
@ -191,8 +192,9 @@ class ArrayND : public BaseArray {
/// Distance between the first element and the element at position index.
int Offset(const Index& index) const {
int offset = 0;
for (int i = 0; i < N; ++i)
for (int i = 0; i < N; ++i) {
offset += index(i) * Stride(i);
}
return offset;
}
@ -260,9 +262,11 @@ class ArrayND : public BaseArray {
/// True if index is inside array.
bool Contains(const Index& index) const {
for (int i = 0; i < N; ++i)
if (index(i) < 0 || index(i) >= Shape(i))
for (int i = 0; i < N; ++i) {
if (index(i) < 0 || index(i) >= Shape(i)) {
return false;
}
}
return true;
}
@ -281,13 +285,16 @@ class ArrayND : public BaseArray {
}
bool operator==(const ArrayND<T, N>& other) const {
if (shape_ != other.shape_)
if (shape_ != other.shape_) {
return false;
if (strides_ != other.strides_)
}
if (strides_ != other.strides_) {
return false;
}
for (int i = 0; i < Size(); ++i) {
if (this->Data()[i] != other.Data()[i])
if (this->Data()[i] != other.Data()[i]) {
return false;
}
}
return true;
}
@ -401,8 +408,9 @@ void MultiplyElements(const AArrayType& a, const BArrayType& b, CArrayType* c) {
// The index starts at the maximum value for each dimension
const typename CArrayType::Index& cShape = c->Shape();
for (int i = 0; i < CArrayType::Index::SIZE; ++i)
for (int i = 0; i < CArrayType::Index::SIZE; ++i) {
index(i) = cShape(i) - 1;
}
// After each multiplication, the highest-dimensional index is reduced.
// if this reduces it less than zero, it resets to its maximum value

View File

@ -35,8 +35,9 @@ namespace libmv {
/// is inside the image.
template <class Image, class Color>
inline void safePutPixel(int yc, int xc, const Color& col, Image* pim) {
if (!pim)
if (!pim) {
return;
}
if (pim->Contains(yc, xc)) {
(*pim)(yc, xc) = col;
}
@ -46,11 +47,13 @@ inline void safePutPixel(int yc, int xc, const Color& col, Image* pim) {
/// \note The color pointer col must have size as the image depth
template <class Image, class Color>
inline void safePutPixel(int yc, int xc, const Color* col, Image* pim) {
if (!pim)
if (!pim) {
return;
}
if (pim->Contains(yc, xc)) {
for (int i = 0; i < pim->Depth(); ++i)
for (int i = 0; i < pim->Depth(); ++i) {
(*pim)(yc, xc, i) = *(col + i);
}
}
}
@ -195,8 +198,9 @@ void DrawLine(int xa, int ya, int xb, int yb, const Color& col, Image* pim) {
&yup = ydir ? ny0 : ny1, &xdown = ydir ? nx1 : nx0,
&ydown = ydir ? ny1 : ny0;
if (xright < 0 || xleft >= width)
if (xright < 0 || xleft >= width) {
return;
}
if (xleft < 0) {
yleft -= xleft * (yright - yleft) / (xright - xleft);
xleft = 0;
@ -205,8 +209,9 @@ void DrawLine(int xa, int ya, int xb, int yb, const Color& col, Image* pim) {
yright -= (xright - width) * (yright - yleft) / (xright - xleft);
xright = width - 1;
}
if (ydown < 0 || yup >= height)
if (ydown < 0 || yup >= height) {
return;
}
if (yup < 0) {
xup -= yup * (xdown - xup) / (ydown - yup);
yup = 0;

View File

@ -50,16 +50,18 @@ struct AsymmetricError {
static void Residuals(const Mat& H, const Mat& x1, const Mat& x2, Mat2X* dx) {
dx->resize(2, x1.cols());
Mat3X x2h_est;
if (x1.rows() == 2)
if (x1.rows() == 2) {
x2h_est = H * EuclideanToHomogeneous(static_cast<Mat2X>(x1));
else
} else {
x2h_est = H * x1;
}
dx->row(0) = x2h_est.row(0).array() / x2h_est.row(2).array();
dx->row(1) = x2h_est.row(1).array() / x2h_est.row(2).array();
if (x2.rows() == 2)
if (x2.rows() == 2) {
*dx = x2 - *dx;
else
} else {
*dx = HomogeneousToEuclidean(static_cast<Mat3X>(x2)) - *dx;
}
}
/**
* Computes the asymmetric residuals between a 2D point x2 and the transformed
@ -75,15 +77,17 @@ struct AsymmetricError {
*/
static void Residuals(const Mat& H, const Vec& x1, const Vec& x2, Vec2* dx) {
Vec3 x2h_est;
if (x1.rows() == 2)
if (x1.rows() == 2) {
x2h_est = H * EuclideanToHomogeneous(static_cast<Vec2>(x1));
else
} else {
x2h_est = H * x1;
if (x2.rows() == 2)
}
if (x2.rows() == 2) {
*dx = x2 - x2h_est.head<2>() / x2h_est[2];
else
} else {
*dx = HomogeneousToEuclidean(static_cast<Vec3>(x2)) -
x2h_est.head<2>() / x2h_est[2];
}
}
/**
* Computes the squared norm of the residuals between a set of 2D points x2
@ -190,14 +194,16 @@ struct AlgebraicError {
*/
static void Residuals(const Mat& H, const Vec& x1, const Vec& x2, Vec3* dx) {
Vec3 x2h_est;
if (x1.rows() == 2)
if (x1.rows() == 2) {
x2h_est = H * EuclideanToHomogeneous(static_cast<Vec2>(x1));
else
} else {
x2h_est = H * x1;
if (x2.rows() == 2)
}
if (x2.rows() == 2) {
*dx = SkewMat(EuclideanToHomogeneous(static_cast<Vec2>(x2))) * x2h_est;
else
} else {
*dx = SkewMat(x2) * x2h_est;
}
// TODO(julien) This is inefficient since it creates an
// identical 3x3 skew matrix for each evaluation.
}

View File

@ -183,10 +183,11 @@ double Depth(const Mat3& R, const Vec3& t, const Vec4& X);
inline bool isInFrontOfCamera(const Mat34& P, const Vec4& X) {
double condition_1 = P.row(2).dot(X) * X[3];
double condition_2 = X[2] * X[3];
if (condition_1 > 0 && condition_2 > 0)
if (condition_1 > 0 && condition_2 > 0) {
return true;
else
} else {
return false;
}
}
inline bool isInFrontOfCamera(const Mat34& P, const Vec3& X) {

View File

@ -229,12 +229,15 @@ class Dogleg {
}
Scalar rho = actual / predicted;
if (step == GAUSS_NEWTON)
if (step == GAUSS_NEWTON) {
printf(" GAUSS");
if (step == STEEPEST_DESCENT)
}
if (step == STEEPEST_DESCENT) {
printf(" STEE");
if (step == DOGLEG)
}
if (step == DOGLEG) {
printf(" DOGL");
}
printf(" %12g %12g %12g\n", rho, actual, predicted);

View File

@ -158,10 +158,11 @@ template <typename TMat, typename TVec>
double Nullspace(TMat* A, TVec* nullspace) {
Eigen::JacobiSVD<TMat> svd(*A, Eigen::ComputeFullV);
(*nullspace) = svd.matrixV().col(A->cols() - 1);
if (A->rows() >= A->cols())
if (A->rows() >= A->cols()) {
return svd.singularValues()(A->cols() - 1);
else
} else {
return 0.0;
}
}
// Solve the linear system Ax = 0 via SVD. Finds two solutions, x1 and x2, such
@ -174,10 +175,11 @@ double Nullspace2(TMat* A, TVec1* x1, TVec2* x2) {
Eigen::JacobiSVD<TMat> svd(*A, Eigen::ComputeFullV);
*x1 = svd.matrixV().col(A->cols() - 1);
*x2 = svd.matrixV().col(A->cols() - 2);
if (A->rows() >= A->cols())
if (A->rows() >= A->cols()) {
return svd.singularValues()(A->cols() - 1);
else
} else {
return 0.0;
}
}
// In place transpose for square matrices.

View File

@ -47,8 +47,9 @@ template<typename _Tp> struct MEM_Allocator {
_Tp *allocate(size_type __n, const void * = 0)
{
_Tp *__ret = NULL;
if (__n)
if (__n) {
__ret = static_cast<_Tp *>(MEM_mallocN(__n * sizeof(_Tp), "STL MEM_Allocator"));
}
return __ret;
}

View File

@ -196,8 +196,9 @@ template<class T> class MEM_CacheLimiter {
while (!queue.empty() && mem_in_use > max) {
MEM_CacheElementPtr elem = get_least_priority_destroyable_element();
if (!elem)
if (!elem) {
break;
}
if (data_size_func) {
cur_size = data_size_func(elem->get()->get_data());
@ -255,24 +256,27 @@ template<class T> class MEM_CacheLimiter {
return false;
}
if (item_destroyable_func) {
if (!item_destroyable_func(elem->get()->get_data()))
if (!item_destroyable_func(elem->get()->get_data())) {
return false;
}
}
return true;
}
MEM_CacheElementPtr get_least_priority_destroyable_element(void)
{
if (queue.empty())
if (queue.empty()) {
return NULL;
}
MEM_CacheElementPtr best_match_elem = NULL;
if (!item_priority_func) {
for (iterator it = queue.begin(); it != queue.end(); it++) {
MEM_CacheElementPtr elem = *it;
if (!can_destroy_element(elem))
if (!can_destroy_element(elem)) {
continue;
}
best_match_elem = elem;
break;
}
@ -284,8 +288,9 @@ template<class T> class MEM_CacheLimiter {
for (i = 0; i < queue.size(); i++) {
MEM_CacheElementPtr elem = queue[i];
if (!can_destroy_element(elem))
if (!can_destroy_element(elem)) {
continue;
}
/* By default 0 means highest priority element. */
/* Casting a size type to int is questionable,

View File

@ -106,8 +106,9 @@ class AtomicHashSet {
/* Get next power of two. Could be done more effiently with builtin_clz, but this is not
* performance-critical. */
kAnchorMask_ = 1;
while (kAnchorMask_ < capacity_)
while (kAnchorMask_ < capacity_) {
kAnchorMask_ *= 2;
}
/* Get mask for lower bits. */
kAnchorMask_ -= 1;

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