Mesh: Replace auto smooth with node group #108014
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -85,7 +85,6 @@ set(_CLANG_FIND_COMPONENTS
|
|||
clangAST
|
||||
clangLex
|
||||
clangBasic
|
||||
clangSupport
|
||||
)
|
||||
|
||||
set(_CLANG_LIBRARIES)
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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()
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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):
|
||||
|
|
|
@ -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="")
|
||||
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 ¶ms_,
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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]];
|
||||
|
||||
|
|
|
@ -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++) {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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];
|
||||
|
||||
|
|
|
@ -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__
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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__ */
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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_);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -34,7 +34,8 @@ class GHOST_EventString : public GHOST_Event {
|
|||
|
||||
~GHOST_EventString()
|
||||
{
|
||||
if (m_data)
|
||||
if (m_data) {
|
||||
free(m_data);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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.
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
Loading…
Reference in New Issue