Add Chromium-only Blender WebEngine parity work
This commit is contained in:
50
blender-5.2.0/intern/cycles/kernel/osl/CMakeLists.txt
Normal file
50
blender-5.2.0/intern/cycles/kernel/osl/CMakeLists.txt
Normal file
@@ -0,0 +1,50 @@
|
||||
# SPDX-FileCopyrightText: 2011-2022 Blender Foundation
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
set(INC
|
||||
../..
|
||||
)
|
||||
|
||||
set(INC_SYS
|
||||
|
||||
)
|
||||
|
||||
set(SRC
|
||||
closures.cpp
|
||||
globals.cpp
|
||||
services.cpp
|
||||
)
|
||||
|
||||
set(HEADER_SRC
|
||||
closures_setup.h
|
||||
closures_template.h
|
||||
compat.h
|
||||
globals.h
|
||||
osl.h
|
||||
services.h
|
||||
services_shared.h
|
||||
types.h
|
||||
)
|
||||
|
||||
set(LIB
|
||||
PUBLIC cycles_scene
|
||||
|
||||
PUBLIC bf::dependencies::optional::osl
|
||||
PRIVATE bf::dependencies::openimageio
|
||||
PRIVATE bf::dependencies::optional::pugixml
|
||||
)
|
||||
|
||||
if(APPLE)
|
||||
# Disable allocation warning on macOS prior to 10.14: the OSLRenderServices
|
||||
# contains member which is 64 bytes aligned (cache inside of OIIO's
|
||||
# unordered_map_concurrent). This is not something what the SDK supports, but
|
||||
# since we take care of allocations ourselves is OK to ignore the
|
||||
# diagnostic message.
|
||||
string(APPEND CMAKE_CXX_FLAGS " -faligned-allocation")
|
||||
endif()
|
||||
|
||||
include_directories(${INC})
|
||||
include_directories(SYSTEM ${INC_SYS})
|
||||
|
||||
cycles_add_library(cycles_kernel_osl "${LIB}" ${SRC} ${HEADER_SRC})
|
||||
86
blender-5.2.0/intern/cycles/kernel/osl/camera.h
Normal file
86
blender-5.2.0/intern/cycles/kernel/osl/camera.h
Normal file
@@ -0,0 +1,86 @@
|
||||
/* SPDX-FileCopyrightText: 2009-2010 Sony Pictures Imageworks Inc., et al. All Rights Reserved.
|
||||
* SPDX-FileCopyrightText: 2011-2024 Blender Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "kernel/globals.h"
|
||||
|
||||
#include "kernel/osl/types.h"
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
||||
ccl_device_inline void cameradata_to_shaderglobals(ccl_private ShaderData *sd,
|
||||
const packed_float3 sensor,
|
||||
const packed_float3 dSdx,
|
||||
const packed_float3 dSdy,
|
||||
const float2 rand_lens,
|
||||
ccl_private ShaderGlobals *globals)
|
||||
{
|
||||
memset(globals, 0, sizeof(ShaderGlobals));
|
||||
|
||||
globals->P = sensor;
|
||||
globals->dPdx = dSdx;
|
||||
globals->dPdy = dSdy;
|
||||
globals->N = make_float3(rand_lens);
|
||||
globals->sd = sd;
|
||||
globals->raytype = OSL_RAYTYPE_PACK(PATH_RAY_VISIBILITY_CAMERA, PATH_RAY_FLAG_NONE);
|
||||
}
|
||||
|
||||
#ifndef __KERNEL_GPU__
|
||||
|
||||
packed_float3 osl_eval_camera(KernelGlobals kg,
|
||||
ccl_private ShaderData *sd,
|
||||
const packed_float3 sensor,
|
||||
const packed_float3 dSdx,
|
||||
const packed_float3 dSdy,
|
||||
const float2 rand_lens,
|
||||
packed_float3 &P,
|
||||
packed_float3 &dPdx,
|
||||
packed_float3 &dPdy,
|
||||
packed_float3 &D,
|
||||
packed_float3 &dDdx,
|
||||
packed_float3 &dDdy);
|
||||
|
||||
#else
|
||||
|
||||
ccl_device_inline packed_float3 osl_eval_camera(KernelGlobals kg,
|
||||
ccl_private ShaderData *sd,
|
||||
const packed_float3 sensor,
|
||||
const packed_float3 dSdx,
|
||||
const packed_float3 dSdy,
|
||||
const float2 rand_lens,
|
||||
packed_float3 &P,
|
||||
packed_float3 &dPdx,
|
||||
packed_float3 &dPdy,
|
||||
packed_float3 &D,
|
||||
packed_float3 &dDdx,
|
||||
packed_float3 &dDdy)
|
||||
{
|
||||
ShaderGlobals globals;
|
||||
cameradata_to_shaderglobals(sd, sensor, dSdx, dSdy, rand_lens, &globals);
|
||||
|
||||
float output[21] = {0.0f};
|
||||
# ifdef __KERNEL_OPTIX__
|
||||
optixDirectCall<void>(/*NUM_CALLABLE_PROGRAM_GROUPS*/ 2,
|
||||
/*shaderglobals_ptr*/ &globals,
|
||||
/*groupdata_ptr*/ (void *)nullptr,
|
||||
/*userdata_base_ptr*/ (void *)nullptr,
|
||||
/*output_base_ptr*/ (void *)output,
|
||||
/*shadeindex*/ 0,
|
||||
/*interactive_params_ptr*/ (void *)nullptr);
|
||||
# endif
|
||||
|
||||
P = make_float3(output[0], output[1], output[2]);
|
||||
dPdx = make_float3(output[3], output[4], output[5]);
|
||||
dPdy = make_float3(output[6], output[7], output[8]);
|
||||
D = make_float3(output[9], output[10], output[11]);
|
||||
dDdx = make_float3(output[12], output[13], output[14]);
|
||||
dDdy = make_float3(output[15], output[16], output[17]);
|
||||
return make_float3(output[18], output[19], output[20]);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
439
blender-5.2.0/intern/cycles/kernel/osl/closures.cpp
Normal file
439
blender-5.2.0/intern/cycles/kernel/osl/closures.cpp
Normal file
@@ -0,0 +1,439 @@
|
||||
/* SPDX-FileCopyrightText: 2009-2010 Sony Pictures Imageworks Inc., et al. All Rights Reserved.
|
||||
* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*
|
||||
* Adapted code from Open Shading Language. */
|
||||
|
||||
#include <OSL/genclosure.h>
|
||||
#include <OSL/oslclosure.h>
|
||||
|
||||
#include "kernel/types.h"
|
||||
|
||||
#include "kernel/osl/globals.h"
|
||||
#include "kernel/osl/services.h"
|
||||
|
||||
#include "util/math.h"
|
||||
#include "util/param.h"
|
||||
|
||||
#include "kernel/globals.h"
|
||||
|
||||
#include "kernel/geom/attribute.h"
|
||||
#include "kernel/geom/object.h"
|
||||
#include "kernel/geom/primitive.h"
|
||||
#include "kernel/util/differential.h"
|
||||
|
||||
#include "kernel/osl/camera.h"
|
||||
#include "kernel/osl/osl.h"
|
||||
|
||||
#define TO_VEC3(v) OSL::Vec3(v.x, v.y, v.z)
|
||||
#define TO_FLOAT3(v) make_float3(v[0], v[1], v[2])
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
||||
static_assert(sizeof(OSLClosure) == sizeof(OSL::ClosureColor) &&
|
||||
sizeof(OSLClosureAdd) == sizeof(OSL::ClosureAdd) &&
|
||||
sizeof(OSLClosureMul) == sizeof(OSL::ClosureMul) &&
|
||||
sizeof(OSLClosureComponent) == sizeof(OSL::ClosureComponent));
|
||||
static_assert(sizeof(ShaderGlobals) >= sizeof(OSL::ShaderGlobals) &&
|
||||
offsetof(ShaderGlobals, backfacing) == offsetof(OSL::ShaderGlobals, backfacing));
|
||||
|
||||
/* Registration */
|
||||
|
||||
#define OSL_CLOSURE_STRUCT_BEGIN(Upper, lower) \
|
||||
static OSL::ClosureParam *osl_closure_##lower##_params() \
|
||||
{ \
|
||||
static OSL::ClosureParam params[] = {
|
||||
#define OSL_CLOSURE_STRUCT_END(Upper, lower) \
|
||||
CLOSURE_STRING_KEYPARAM(Upper##Closure, label, "label"), CLOSURE_FINISH_PARAM(Upper##Closure) \
|
||||
} \
|
||||
; \
|
||||
return params; \
|
||||
}
|
||||
#define OSL_CLOSURE_STRUCT_MEMBER(Upper, TYPE, type, name, key) \
|
||||
CLOSURE_##TYPE##_KEYPARAM(Upper##Closure, name, key),
|
||||
#define OSL_CLOSURE_STRUCT_ARRAY_MEMBER(Upper, TYPE, type, name, key, size) \
|
||||
CLOSURE_##TYPE##_ARRAY_PARAM(Upper##Closure, name, size),
|
||||
|
||||
#include "closures_template.h"
|
||||
|
||||
static OSL::ClosureParam *osl_closure_layer_params()
|
||||
{
|
||||
static OSL::ClosureParam params[] = {CLOSURE_CLOSURE_PARAM(LayerClosure, top),
|
||||
CLOSURE_CLOSURE_PARAM(LayerClosure, base),
|
||||
CLOSURE_FINISH_PARAM(LayerClosure)};
|
||||
return params;
|
||||
}
|
||||
|
||||
void OSLRenderServices::register_closures(OSL::ShadingSystem *ss)
|
||||
{
|
||||
#define OSL_CLOSURE_STRUCT_BEGIN(Upper, lower) \
|
||||
ss->register_closure( \
|
||||
#lower, OSL_CLOSURE_##Upper##_ID, osl_closure_##lower##_params(), nullptr, nullptr);
|
||||
|
||||
#include "closures_template.h"
|
||||
|
||||
ss->register_closure(
|
||||
"layer", OSL_CLOSURE_LAYER_ID, osl_closure_layer_params(), nullptr, nullptr);
|
||||
}
|
||||
|
||||
/* Surface & Background */
|
||||
|
||||
template<typename IntegratorGenericState>
|
||||
void osl_eval_nodes_surface(const ThreadKernelGlobalsCPU *kg,
|
||||
IntegratorGenericState state,
|
||||
ShaderData *sd,
|
||||
const PathRayVisibility path_visibility,
|
||||
const uint32_t path_flag)
|
||||
{
|
||||
/* setup shader globals from shader data */
|
||||
shaderdata_to_shaderglobals(sd, path_visibility, path_flag, &kg->osl.shader_globals);
|
||||
|
||||
/* clear trace data */
|
||||
kg->osl.tracedata.init = false;
|
||||
|
||||
/* Used by render-services. */
|
||||
kg->osl.shader_globals.kg = kg;
|
||||
if constexpr (std::is_same_v<IntegratorGenericState, IntegratorShadowState>) {
|
||||
kg->osl.shader_globals.path_state = nullptr;
|
||||
kg->osl.shader_globals.shadow_path_state = (const IntegratorShadowStateCPU *)state;
|
||||
}
|
||||
else if constexpr (std::is_same_v<IntegratorGenericState, IntegratorBakeState>) {
|
||||
kg->osl.shader_globals.path_state = nullptr;
|
||||
kg->osl.shader_globals.shadow_path_state = nullptr;
|
||||
}
|
||||
else {
|
||||
kg->osl.shader_globals.path_state = (const IntegratorStateCPU *)state;
|
||||
kg->osl.shader_globals.shadow_path_state = nullptr;
|
||||
}
|
||||
|
||||
/* execute shader for this point */
|
||||
OSL::ShadingSystem *ss = (OSL::ShadingSystem *)kg->osl.ss;
|
||||
OSL::ShaderGlobals *globals = reinterpret_cast<OSL::ShaderGlobals *>(&kg->osl.shader_globals);
|
||||
OSL::ShadingContext *octx = kg->osl.context;
|
||||
const int shader = sd->shader & SHADER_MASK;
|
||||
|
||||
if (sd->object == OBJECT_NONE) {
|
||||
/* background */
|
||||
if (kg->osl.globals->background_state) {
|
||||
ss->execute(*octx,
|
||||
*(kg->osl.globals->background_state),
|
||||
kg->osl.thread_index,
|
||||
0,
|
||||
*globals,
|
||||
nullptr,
|
||||
nullptr);
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* automatic bump shader */
|
||||
if (kg->osl.globals->bump_state[shader]) {
|
||||
/* save state */
|
||||
const float3 P = sd->P;
|
||||
const float dP = sd->dP;
|
||||
const OSL::Vec3 dPdx = globals->dPdx;
|
||||
const OSL::Vec3 dPdy = globals->dPdy;
|
||||
|
||||
/* set state as if undisplaced */
|
||||
if (sd->flag & SD_HAS_DISPLACEMENT) {
|
||||
const AttributeDescriptor desc = find_attribute(kg, sd, ATTR_STD_POSITION_UNDISPLACED);
|
||||
kernel_assert(is_attribute_found(desc));
|
||||
|
||||
dual3 P = primitive_surface_attribute<dual3>(kg, sd, desc);
|
||||
object_position_transform(kg, sd, &P);
|
||||
|
||||
sd->P = P.val;
|
||||
sd->dP = differential_make_compact(P);
|
||||
|
||||
globals->P = TO_VEC3(sd->P);
|
||||
globals->dPdx = TO_VEC3(P.dx);
|
||||
globals->dPdy = TO_VEC3(P.dy);
|
||||
|
||||
/* Set normal as if undisplaced. */
|
||||
primitive_normal_set_undisplaced(kg, sd, desc.offset);
|
||||
globals->N = TO_VEC3(sd->N);
|
||||
}
|
||||
|
||||
/* execute bump shader */
|
||||
ss->execute(*octx,
|
||||
*(kg->osl.globals->bump_state[shader]),
|
||||
kg->osl.thread_index,
|
||||
0,
|
||||
*globals,
|
||||
nullptr,
|
||||
nullptr);
|
||||
|
||||
/* reset state */
|
||||
sd->P = P;
|
||||
sd->dP = dP;
|
||||
|
||||
/* Apply bump output to sd->N since it's used for shadow terminator logic, for example. */
|
||||
sd->N = TO_FLOAT3(globals->N);
|
||||
|
||||
globals->P = TO_VEC3(P);
|
||||
globals->dPdx = TO_VEC3(dPdx);
|
||||
globals->dPdy = TO_VEC3(dPdy);
|
||||
}
|
||||
|
||||
/* surface shader */
|
||||
if (kg->osl.globals->surface_state[shader]) {
|
||||
ss->execute(*octx,
|
||||
*(kg->osl.globals->surface_state[shader]),
|
||||
kg->osl.thread_index,
|
||||
0,
|
||||
*globals,
|
||||
nullptr,
|
||||
nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
/* flatten closure tree */
|
||||
if (kg->osl.shader_globals.Ci) {
|
||||
flatten_closure_tree(kg, sd, path_visibility, path_flag, kg->osl.shader_globals.Ci);
|
||||
}
|
||||
}
|
||||
|
||||
template<>
|
||||
void osl_eval_nodes<SHADER_TYPE_SURFACE, IntegratorShadowState>(
|
||||
const ThreadKernelGlobalsCPU *kg,
|
||||
IntegratorShadowState state,
|
||||
ShaderData *sd,
|
||||
const PathRayVisibility path_visibility,
|
||||
const uint32_t path_flag)
|
||||
{
|
||||
osl_eval_nodes_surface(kg, state, sd, path_visibility, path_flag);
|
||||
}
|
||||
|
||||
template<>
|
||||
void osl_eval_nodes<SHADER_TYPE_SURFACE, IntegratorState>(const ThreadKernelGlobalsCPU *kg,
|
||||
IntegratorState state,
|
||||
ShaderData *sd,
|
||||
const PathRayVisibility path_visibility,
|
||||
const uint32_t path_flag)
|
||||
{
|
||||
osl_eval_nodes_surface(kg, state, sd, path_visibility, path_flag);
|
||||
}
|
||||
|
||||
template<>
|
||||
void osl_eval_nodes<SHADER_TYPE_SURFACE, IntegratorBakeState>(
|
||||
const ThreadKernelGlobalsCPU *kg,
|
||||
IntegratorBakeState state,
|
||||
ShaderData *sd,
|
||||
const PathRayVisibility path_visibility,
|
||||
const uint32_t path_flag)
|
||||
{
|
||||
osl_eval_nodes_surface(kg, state, sd, path_visibility, path_flag);
|
||||
}
|
||||
|
||||
/* Volume */
|
||||
|
||||
template<typename IntegratorGenericState>
|
||||
void osl_eval_nodes_volume(const ThreadKernelGlobalsCPU *kg,
|
||||
IntegratorGenericState state,
|
||||
ShaderData *sd,
|
||||
const PathRayVisibility path_visibility,
|
||||
const uint32_t path_flag)
|
||||
{
|
||||
/* setup shader globals from shader data */
|
||||
shaderdata_to_shaderglobals(sd, path_visibility, path_flag, &kg->osl.shader_globals);
|
||||
|
||||
/* clear trace data */
|
||||
kg->osl.tracedata.init = false;
|
||||
|
||||
/* Used by render-services. */
|
||||
kg->osl.shader_globals.kg = kg;
|
||||
if constexpr (std::is_same_v<IntegratorGenericState, IntegratorShadowState>) {
|
||||
kg->osl.shader_globals.path_state = nullptr;
|
||||
kg->osl.shader_globals.shadow_path_state = (const IntegratorShadowStateCPU *)state;
|
||||
}
|
||||
else if constexpr (std::is_same_v<IntegratorGenericState, IntegratorBakeState>) {
|
||||
kg->osl.shader_globals.path_state = nullptr;
|
||||
kg->osl.shader_globals.shadow_path_state = nullptr;
|
||||
}
|
||||
else {
|
||||
kg->osl.shader_globals.path_state = (const IntegratorStateCPU *)state;
|
||||
kg->osl.shader_globals.shadow_path_state = nullptr;
|
||||
}
|
||||
|
||||
/* execute shader */
|
||||
OSL::ShadingSystem *ss = (OSL::ShadingSystem *)kg->osl.ss;
|
||||
OSL::ShaderGlobals *globals = reinterpret_cast<OSL::ShaderGlobals *>(&kg->osl.shader_globals);
|
||||
OSL::ShadingContext *octx = kg->osl.context;
|
||||
const int shader = sd->shader & SHADER_MASK;
|
||||
|
||||
if (kg->osl.globals->volume_state[shader]) {
|
||||
ss->execute(*octx,
|
||||
*(kg->osl.globals->volume_state[shader]),
|
||||
kg->osl.thread_index,
|
||||
0,
|
||||
*globals,
|
||||
nullptr,
|
||||
nullptr);
|
||||
}
|
||||
|
||||
/* flatten closure tree */
|
||||
if (kg->osl.shader_globals.Ci) {
|
||||
flatten_closure_tree(kg, sd, path_visibility, path_flag, kg->osl.shader_globals.Ci);
|
||||
}
|
||||
}
|
||||
|
||||
template<>
|
||||
void osl_eval_nodes<SHADER_TYPE_VOLUME, IntegratorShadowState>(
|
||||
const ThreadKernelGlobalsCPU *kg,
|
||||
IntegratorShadowState state,
|
||||
ShaderData *sd,
|
||||
const PathRayVisibility path_visibility,
|
||||
const uint32_t path_flag)
|
||||
{
|
||||
osl_eval_nodes_volume(kg, state, sd, path_visibility, path_flag);
|
||||
}
|
||||
|
||||
template<>
|
||||
void osl_eval_nodes<SHADER_TYPE_VOLUME, IntegratorState>(const ThreadKernelGlobalsCPU *kg,
|
||||
IntegratorState state,
|
||||
ShaderData *sd,
|
||||
const PathRayVisibility path_visibility,
|
||||
const uint32_t path_flag)
|
||||
{
|
||||
osl_eval_nodes_volume(kg, state, sd, path_visibility, path_flag);
|
||||
}
|
||||
|
||||
template<>
|
||||
void osl_eval_nodes<SHADER_TYPE_VOLUME, IntegratorBakeState>(
|
||||
const ThreadKernelGlobalsCPU *kg,
|
||||
IntegratorBakeState state,
|
||||
ShaderData *sd,
|
||||
const PathRayVisibility path_visibility,
|
||||
const uint32_t path_flag)
|
||||
{
|
||||
osl_eval_nodes_volume(kg, state, sd, path_visibility, path_flag);
|
||||
}
|
||||
|
||||
/* Displacement */
|
||||
|
||||
template<typename IntegratorGenericState>
|
||||
void osl_eval_nodes_displacement(const ThreadKernelGlobalsCPU *kg,
|
||||
IntegratorGenericState state,
|
||||
ShaderData *sd,
|
||||
const PathRayVisibility path_visibility,
|
||||
const uint32_t path_flag)
|
||||
{
|
||||
/* setup shader globals from shader data */
|
||||
shaderdata_to_shaderglobals(sd, path_visibility, path_flag, &kg->osl.shader_globals);
|
||||
|
||||
/* clear trace data */
|
||||
kg->osl.tracedata.init = false;
|
||||
|
||||
/* Used by render-services. */
|
||||
kg->osl.shader_globals.kg = kg;
|
||||
|
||||
if constexpr (std::is_same_v<IntegratorGenericState, IntegratorBakeState>) {
|
||||
kg->osl.shader_globals.path_state = nullptr;
|
||||
kg->osl.shader_globals.shadow_path_state = nullptr;
|
||||
}
|
||||
else {
|
||||
kg->osl.shader_globals.path_state = (const IntegratorStateCPU *)state;
|
||||
kg->osl.shader_globals.shadow_path_state = nullptr;
|
||||
}
|
||||
|
||||
/* execute shader */
|
||||
OSL::ShadingSystem *ss = (OSL::ShadingSystem *)kg->osl.ss;
|
||||
OSL::ShaderGlobals *globals = reinterpret_cast<OSL::ShaderGlobals *>(&kg->osl.shader_globals);
|
||||
OSL::ShadingContext *octx = kg->osl.context;
|
||||
const int shader = sd->shader & SHADER_MASK;
|
||||
|
||||
if (kg->osl.globals->displacement_state[shader]) {
|
||||
ss->execute(*octx,
|
||||
*(kg->osl.globals->displacement_state[shader]),
|
||||
kg->osl.thread_index,
|
||||
0,
|
||||
*globals,
|
||||
nullptr,
|
||||
nullptr);
|
||||
}
|
||||
|
||||
/* get back position */
|
||||
sd->P = TO_FLOAT3(globals->P);
|
||||
}
|
||||
|
||||
template<>
|
||||
void osl_eval_nodes<SHADER_TYPE_DISPLACEMENT, IntegratorShadowState>(
|
||||
const ThreadKernelGlobalsCPU *kg,
|
||||
IntegratorShadowState state,
|
||||
ShaderData *sd,
|
||||
const PathRayVisibility path_visibility,
|
||||
const uint32_t path_flag)
|
||||
{
|
||||
osl_eval_nodes_displacement(kg, state, sd, path_visibility, path_flag);
|
||||
}
|
||||
|
||||
template<>
|
||||
void osl_eval_nodes<SHADER_TYPE_DISPLACEMENT, IntegratorState>(
|
||||
const ThreadKernelGlobalsCPU *kg,
|
||||
IntegratorState state,
|
||||
ShaderData *sd,
|
||||
const PathRayVisibility path_visibility,
|
||||
const uint32_t path_flag)
|
||||
{
|
||||
osl_eval_nodes_displacement(kg, state, sd, path_visibility, path_flag);
|
||||
}
|
||||
|
||||
template<>
|
||||
void osl_eval_nodes<SHADER_TYPE_DISPLACEMENT, IntegratorBakeState>(
|
||||
const ThreadKernelGlobalsCPU *kg,
|
||||
IntegratorBakeState state,
|
||||
ShaderData *sd,
|
||||
const PathRayVisibility path_visibility,
|
||||
const uint32_t path_flag)
|
||||
{
|
||||
osl_eval_nodes_displacement(kg, state, sd, path_visibility, path_flag);
|
||||
}
|
||||
|
||||
/* Camera */
|
||||
|
||||
packed_float3 osl_eval_camera(const ThreadKernelGlobalsCPU *kg,
|
||||
ccl_private ShaderData *sd,
|
||||
const packed_float3 sensor,
|
||||
const packed_float3 dSdx,
|
||||
const packed_float3 dSdy,
|
||||
const float2 rand_lens,
|
||||
packed_float3 &P,
|
||||
packed_float3 &dPdx,
|
||||
packed_float3 &dPdy,
|
||||
packed_float3 &D,
|
||||
packed_float3 &dDdx,
|
||||
packed_float3 &dDdy)
|
||||
{
|
||||
if (!kg || !kg->osl.globals->camera_state) {
|
||||
return zero_spectrum();
|
||||
}
|
||||
|
||||
/* Setup shader globals from the sensor position. */
|
||||
cameradata_to_shaderglobals(sd, sensor, dSdx, dSdy, rand_lens, &kg->osl.shader_globals);
|
||||
|
||||
/* Clear trace data. */
|
||||
kg->osl.tracedata.init = false;
|
||||
|
||||
/* Provide kernel globals to the render-services. */
|
||||
kg->osl.shader_globals.kg = kg;
|
||||
|
||||
/* Execute the shader. */
|
||||
OSL::ShadingSystem *ss = (OSL::ShadingSystem *)kg->osl.ss;
|
||||
OSL::ShaderGlobals *globals = reinterpret_cast<OSL::ShaderGlobals *>(&kg->osl.shader_globals);
|
||||
OSL::ShadingContext *octx = kg->osl.context;
|
||||
|
||||
float output[21] = {0.0f};
|
||||
|
||||
ss->execute(
|
||||
*octx, *kg->osl.globals->camera_state, kg->osl.thread_index, 0, *globals, nullptr, output);
|
||||
|
||||
P = make_float3(output[0], output[1], output[2]);
|
||||
dPdx = make_float3(output[3], output[4], output[5]);
|
||||
dPdy = make_float3(output[6], output[7], output[8]);
|
||||
D = make_float3(output[9], output[10], output[11]);
|
||||
dDdx = make_float3(output[12], output[13], output[14]);
|
||||
dDdy = make_float3(output[15], output[16], output[17]);
|
||||
return make_float3(output[18], output[19], output[20]);
|
||||
}
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
1417
blender-5.2.0/intern/cycles/kernel/osl/closures_setup.h
Normal file
1417
blender-5.2.0/intern/cycles/kernel/osl/closures_setup.h
Normal file
File diff suppressed because it is too large
Load Diff
310
blender-5.2.0/intern/cycles/kernel/osl/closures_template.h
Normal file
310
blender-5.2.0/intern/cycles/kernel/osl/closures_template.h
Normal file
@@ -0,0 +1,310 @@
|
||||
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 */
|
||||
|
||||
#ifndef OSL_CLOSURE_STRUCT_BEGIN
|
||||
# define OSL_CLOSURE_STRUCT_BEGIN(Upper, lower)
|
||||
#endif
|
||||
#ifndef OSL_CLOSURE_STRUCT_END
|
||||
# define OSL_CLOSURE_STRUCT_END(Upper, lower)
|
||||
#endif
|
||||
#ifndef OSL_CLOSURE_STRUCT_MEMBER
|
||||
# define OSL_CLOSURE_STRUCT_MEMBER(Upper, TYPE, type, name, key)
|
||||
#endif
|
||||
#ifndef OSL_CLOSURE_STRUCT_ARRAY_MEMBER
|
||||
# define OSL_CLOSURE_STRUCT_ARRAY_MEMBER(Upper, TYPE, type, name, key, size)
|
||||
#endif
|
||||
|
||||
OSL_CLOSURE_STRUCT_BEGIN(Diffuse, diffuse)
|
||||
OSL_CLOSURE_STRUCT_MEMBER(Diffuse, VECTOR, packed_float3, N, nullptr)
|
||||
OSL_CLOSURE_STRUCT_END(Diffuse, diffuse)
|
||||
|
||||
/* Deprecated form, will be removed in OSL 2.0. */
|
||||
OSL_CLOSURE_STRUCT_BEGIN(OrenNayar, oren_nayar)
|
||||
OSL_CLOSURE_STRUCT_MEMBER(OrenNayar, VECTOR, packed_float3, N, nullptr)
|
||||
OSL_CLOSURE_STRUCT_MEMBER(OrenNayar, FLOAT, float, roughness, nullptr)
|
||||
OSL_CLOSURE_STRUCT_END(OrenNayar, oren_nayar)
|
||||
|
||||
OSL_CLOSURE_STRUCT_BEGIN(OrenNayarDiffuseBSDF, oren_nayar_diffuse_bsdf)
|
||||
OSL_CLOSURE_STRUCT_MEMBER(OrenNayarDiffuseBSDF, VECTOR, packed_float3, N, nullptr)
|
||||
OSL_CLOSURE_STRUCT_MEMBER(OrenNayarDiffuseBSDF, VECTOR, packed_float3, albedo, nullptr)
|
||||
OSL_CLOSURE_STRUCT_MEMBER(OrenNayarDiffuseBSDF, FLOAT, float, roughness, nullptr)
|
||||
OSL_CLOSURE_STRUCT_END(OrenNayarDiffuseBSDF, oren_nayar_diffuse_bsdf)
|
||||
|
||||
OSL_CLOSURE_STRUCT_BEGIN(BurleyDiffuseBSDF, burley_diffuse_bsdf)
|
||||
OSL_CLOSURE_STRUCT_MEMBER(BurleyDiffuseBSDF, VECTOR, packed_float3, N, NULL)
|
||||
OSL_CLOSURE_STRUCT_MEMBER(BurleyDiffuseBSDF, VECTOR, packed_float3, albedo, NULL)
|
||||
OSL_CLOSURE_STRUCT_MEMBER(BurleyDiffuseBSDF, FLOAT, float, roughness, NULL)
|
||||
OSL_CLOSURE_STRUCT_END(BurleyDiffuseBSDF, burley_diffuse_bsdf)
|
||||
|
||||
OSL_CLOSURE_STRUCT_BEGIN(Translucent, translucent)
|
||||
OSL_CLOSURE_STRUCT_MEMBER(Translucent, VECTOR, packed_float3, N, nullptr)
|
||||
OSL_CLOSURE_STRUCT_END(Translucent, translucent)
|
||||
|
||||
OSL_CLOSURE_STRUCT_BEGIN(TranslucentBSDF, translucent_bsdf)
|
||||
OSL_CLOSURE_STRUCT_MEMBER(TranslucentBSDF, VECTOR, packed_float3, N, nullptr)
|
||||
OSL_CLOSURE_STRUCT_MEMBER(TranslucentBSDF, VECTOR, packed_float3, albedo, NULL)
|
||||
OSL_CLOSURE_STRUCT_END(TranslucentBSDF, translucent_bsdf)
|
||||
|
||||
OSL_CLOSURE_STRUCT_BEGIN(Reflection, reflection)
|
||||
OSL_CLOSURE_STRUCT_MEMBER(Reflection, VECTOR, packed_float3, N, nullptr)
|
||||
OSL_CLOSURE_STRUCT_END(Reflection, reflection)
|
||||
|
||||
OSL_CLOSURE_STRUCT_BEGIN(Refraction, refraction)
|
||||
OSL_CLOSURE_STRUCT_MEMBER(Refraction, VECTOR, packed_float3, N, nullptr)
|
||||
OSL_CLOSURE_STRUCT_MEMBER(Refraction, FLOAT, float, ior, nullptr)
|
||||
OSL_CLOSURE_STRUCT_END(Refraction, refraction)
|
||||
|
||||
OSL_CLOSURE_STRUCT_BEGIN(Transparent, transparent)
|
||||
OSL_CLOSURE_STRUCT_END(Transparent, transparent)
|
||||
|
||||
OSL_CLOSURE_STRUCT_BEGIN(TransparentBSDF, transparent_bsdf)
|
||||
OSL_CLOSURE_STRUCT_END(TransparentBSDF, transparent_bsdf)
|
||||
|
||||
OSL_CLOSURE_STRUCT_BEGIN(RayPortalBSDF, ray_portal_bsdf)
|
||||
OSL_CLOSURE_STRUCT_MEMBER(RayPortalBSDF, VECTOR, packed_float3, position, nullptr)
|
||||
OSL_CLOSURE_STRUCT_MEMBER(RayPortalBSDF, VECTOR, packed_float3, direction, nullptr)
|
||||
OSL_CLOSURE_STRUCT_END(RayPortalBSDF, ray_portal_bsdf)
|
||||
|
||||
OSL_CLOSURE_STRUCT_BEGIN(DielectricBSDF, dielectric_bsdf)
|
||||
OSL_CLOSURE_STRUCT_MEMBER(DielectricBSDF, VECTOR, packed_float3, N, nullptr)
|
||||
OSL_CLOSURE_STRUCT_MEMBER(DielectricBSDF, VECTOR, packed_float3, T, nullptr)
|
||||
OSL_CLOSURE_STRUCT_MEMBER(DielectricBSDF, VECTOR, packed_float3, reflection_tint, nullptr)
|
||||
OSL_CLOSURE_STRUCT_MEMBER(DielectricBSDF, VECTOR, packed_float3, transmission_tint, nullptr)
|
||||
OSL_CLOSURE_STRUCT_MEMBER(DielectricBSDF, FLOAT, float, alpha_x, nullptr)
|
||||
OSL_CLOSURE_STRUCT_MEMBER(DielectricBSDF, FLOAT, float, alpha_y, nullptr)
|
||||
OSL_CLOSURE_STRUCT_MEMBER(DielectricBSDF, FLOAT, float, ior, nullptr)
|
||||
OSL_CLOSURE_STRUCT_MEMBER(DielectricBSDF, STRING, DeviceString, distribution, nullptr)
|
||||
OSL_CLOSURE_STRUCT_MEMBER(DielectricBSDF, FLOAT, float, thinfilm_thickness, "thinfilm_thickness")
|
||||
OSL_CLOSURE_STRUCT_MEMBER(DielectricBSDF, FLOAT, float, thinfilm_ior, "thinfilm_ior")
|
||||
OSL_CLOSURE_STRUCT_END(DielectricBSDF, dielectric_bsdf)
|
||||
|
||||
OSL_CLOSURE_STRUCT_BEGIN(ConductorBSDF, conductor_bsdf)
|
||||
OSL_CLOSURE_STRUCT_MEMBER(ConductorBSDF, VECTOR, packed_float3, N, nullptr)
|
||||
OSL_CLOSURE_STRUCT_MEMBER(ConductorBSDF, VECTOR, packed_float3, T, nullptr)
|
||||
OSL_CLOSURE_STRUCT_MEMBER(ConductorBSDF, FLOAT, float, alpha_x, nullptr)
|
||||
OSL_CLOSURE_STRUCT_MEMBER(ConductorBSDF, FLOAT, float, alpha_y, nullptr)
|
||||
OSL_CLOSURE_STRUCT_MEMBER(ConductorBSDF, VECTOR, packed_float3, ior, nullptr)
|
||||
OSL_CLOSURE_STRUCT_MEMBER(ConductorBSDF, VECTOR, packed_float3, extinction, nullptr)
|
||||
OSL_CLOSURE_STRUCT_MEMBER(ConductorBSDF, STRING, DeviceString, distribution, nullptr)
|
||||
OSL_CLOSURE_STRUCT_MEMBER(ConductorBSDF, FLOAT, float, thinfilm_thickness, "thinfilm_thickness")
|
||||
OSL_CLOSURE_STRUCT_MEMBER(ConductorBSDF, FLOAT, float, thinfilm_ior, "thinfilm_ior")
|
||||
OSL_CLOSURE_STRUCT_END(ConductorBSDF, conductor_bsdf)
|
||||
|
||||
OSL_CLOSURE_STRUCT_BEGIN(GeneralizedSchlickBSDF, generalized_schlick_bsdf)
|
||||
OSL_CLOSURE_STRUCT_MEMBER(GeneralizedSchlickBSDF, VECTOR, packed_float3, N, nullptr)
|
||||
OSL_CLOSURE_STRUCT_MEMBER(GeneralizedSchlickBSDF, VECTOR, packed_float3, T, nullptr)
|
||||
OSL_CLOSURE_STRUCT_MEMBER(
|
||||
GeneralizedSchlickBSDF, VECTOR, packed_float3, reflection_tint, nullptr)
|
||||
OSL_CLOSURE_STRUCT_MEMBER(
|
||||
GeneralizedSchlickBSDF, VECTOR, packed_float3, transmission_tint, nullptr)
|
||||
OSL_CLOSURE_STRUCT_MEMBER(GeneralizedSchlickBSDF, FLOAT, float, alpha_x, nullptr)
|
||||
OSL_CLOSURE_STRUCT_MEMBER(GeneralizedSchlickBSDF, FLOAT, float, alpha_y, nullptr)
|
||||
OSL_CLOSURE_STRUCT_MEMBER(GeneralizedSchlickBSDF, VECTOR, packed_float3, f0, nullptr)
|
||||
OSL_CLOSURE_STRUCT_MEMBER(GeneralizedSchlickBSDF, VECTOR, packed_float3, f90, nullptr)
|
||||
OSL_CLOSURE_STRUCT_MEMBER(GeneralizedSchlickBSDF, FLOAT, float, exponent, nullptr)
|
||||
OSL_CLOSURE_STRUCT_MEMBER(GeneralizedSchlickBSDF, STRING, DeviceString, distribution, nullptr)
|
||||
OSL_CLOSURE_STRUCT_MEMBER(
|
||||
GeneralizedSchlickBSDF, FLOAT, float, thinfilm_thickness, "thinfilm_thickness")
|
||||
OSL_CLOSURE_STRUCT_MEMBER(GeneralizedSchlickBSDF, FLOAT, float, thinfilm_ior, "thinfilm_ior")
|
||||
OSL_CLOSURE_STRUCT_END(GeneralizedSchlickBSDF, generalized_schlick_bsdf)
|
||||
|
||||
OSL_CLOSURE_STRUCT_BEGIN(ThinGlass, thin_glass)
|
||||
OSL_CLOSURE_STRUCT_MEMBER(ThinGlass, VECTOR, packed_float3, N, nullptr)
|
||||
OSL_CLOSURE_STRUCT_MEMBER(ThinGlass, VECTOR, packed_float3, T, nullptr)
|
||||
OSL_CLOSURE_STRUCT_MEMBER(ThinGlass, VECTOR, packed_float3, reflection_tint, nullptr)
|
||||
OSL_CLOSURE_STRUCT_MEMBER(ThinGlass, VECTOR, packed_float3, transmission_tint, nullptr)
|
||||
OSL_CLOSURE_STRUCT_MEMBER(ThinGlass, FLOAT, float, ior, nullptr)
|
||||
OSL_CLOSURE_STRUCT_MEMBER(ThinGlass, FLOAT, float, roughness, nullptr)
|
||||
OSL_CLOSURE_STRUCT_MEMBER(ThinGlass, FLOAT, float, thinfilm_thickness, nullptr)
|
||||
OSL_CLOSURE_STRUCT_MEMBER(ThinGlass, FLOAT, float, thinfilm_ior, nullptr)
|
||||
OSL_CLOSURE_STRUCT_END(ThinGlass, thin_glass)
|
||||
|
||||
OSL_CLOSURE_STRUCT_BEGIN(ThinSubsurface, thin_subsurface)
|
||||
OSL_CLOSURE_STRUCT_MEMBER(ThinSubsurface, VECTOR, packed_float3, N, nullptr)
|
||||
OSL_CLOSURE_STRUCT_MEMBER(ThinSubsurface, VECTOR, packed_float3, T, nullptr)
|
||||
OSL_CLOSURE_STRUCT_MEMBER(ThinSubsurface, COLOR, packed_float3, color, nullptr)
|
||||
OSL_CLOSURE_STRUCT_MEMBER(ThinSubsurface, FLOAT, float, anisotropy, nullptr)
|
||||
OSL_CLOSURE_STRUCT_MEMBER(ThinSubsurface, FLOAT, float, roughness, nullptr)
|
||||
OSL_CLOSURE_STRUCT_END(ThinSubsurface, thin_subsurface)
|
||||
|
||||
OSL_CLOSURE_STRUCT_BEGIN(Microfacet, microfacet)
|
||||
OSL_CLOSURE_STRUCT_MEMBER(Microfacet, STRING, DeviceString, distribution, nullptr)
|
||||
OSL_CLOSURE_STRUCT_MEMBER(Microfacet, VECTOR, packed_float3, N, nullptr)
|
||||
OSL_CLOSURE_STRUCT_MEMBER(Microfacet, VECTOR, packed_float3, T, nullptr)
|
||||
OSL_CLOSURE_STRUCT_MEMBER(Microfacet, FLOAT, float, alpha_x, nullptr)
|
||||
OSL_CLOSURE_STRUCT_MEMBER(Microfacet, FLOAT, float, alpha_y, nullptr)
|
||||
OSL_CLOSURE_STRUCT_MEMBER(Microfacet, FLOAT, float, ior, nullptr)
|
||||
OSL_CLOSURE_STRUCT_MEMBER(Microfacet, INT, int, refract, nullptr)
|
||||
OSL_CLOSURE_STRUCT_END(Microfacet, microfacet)
|
||||
|
||||
OSL_CLOSURE_STRUCT_BEGIN(MicrofacetF82Tint, microfacet_f82_tint)
|
||||
OSL_CLOSURE_STRUCT_MEMBER(MicrofacetF82Tint, STRING, DeviceString, distribution, nullptr)
|
||||
OSL_CLOSURE_STRUCT_MEMBER(MicrofacetF82Tint, VECTOR, packed_float3, N, nullptr)
|
||||
OSL_CLOSURE_STRUCT_MEMBER(MicrofacetF82Tint, VECTOR, packed_float3, T, nullptr)
|
||||
OSL_CLOSURE_STRUCT_MEMBER(MicrofacetF82Tint, FLOAT, float, alpha_x, nullptr)
|
||||
OSL_CLOSURE_STRUCT_MEMBER(MicrofacetF82Tint, FLOAT, float, alpha_y, nullptr)
|
||||
OSL_CLOSURE_STRUCT_MEMBER(MicrofacetF82Tint, VECTOR, packed_float3, f0, nullptr)
|
||||
OSL_CLOSURE_STRUCT_MEMBER(MicrofacetF82Tint, VECTOR, packed_float3, f82, nullptr)
|
||||
OSL_CLOSURE_STRUCT_MEMBER(
|
||||
MicrofacetF82Tint, FLOAT, float, thinfilm_thickness, "thinfilm_thickness")
|
||||
OSL_CLOSURE_STRUCT_MEMBER(MicrofacetF82Tint, FLOAT, float, thinfilm_ior, "thinfilm_ior")
|
||||
OSL_CLOSURE_STRUCT_END(MicrofacetF82Tint, microfacet)
|
||||
|
||||
OSL_CLOSURE_STRUCT_BEGIN(MicrofacetMultiGGXGlass, microfacet_multi_ggx_glass)
|
||||
OSL_CLOSURE_STRUCT_MEMBER(MicrofacetMultiGGXGlass, VECTOR, packed_float3, N, nullptr)
|
||||
OSL_CLOSURE_STRUCT_MEMBER(MicrofacetMultiGGXGlass, FLOAT, float, alpha_x, nullptr)
|
||||
OSL_CLOSURE_STRUCT_MEMBER(MicrofacetMultiGGXGlass, FLOAT, float, ior, nullptr)
|
||||
OSL_CLOSURE_STRUCT_MEMBER(MicrofacetMultiGGXGlass, VECTOR, packed_float3, color, nullptr)
|
||||
OSL_CLOSURE_STRUCT_END(MicrofacetMultiGGXGlass, microfacet_multi_ggx_glass)
|
||||
|
||||
OSL_CLOSURE_STRUCT_BEGIN(MicrofacetMultiGGX, microfacet_multi_ggx_aniso)
|
||||
OSL_CLOSURE_STRUCT_MEMBER(MicrofacetMultiGGX, VECTOR, packed_float3, N, nullptr)
|
||||
OSL_CLOSURE_STRUCT_MEMBER(MicrofacetMultiGGX, VECTOR, packed_float3, T, nullptr)
|
||||
OSL_CLOSURE_STRUCT_MEMBER(MicrofacetMultiGGX, FLOAT, float, alpha_x, nullptr)
|
||||
OSL_CLOSURE_STRUCT_MEMBER(MicrofacetMultiGGX, FLOAT, float, alpha_y, nullptr)
|
||||
OSL_CLOSURE_STRUCT_MEMBER(MicrofacetMultiGGX, VECTOR, packed_float3, color, nullptr)
|
||||
OSL_CLOSURE_STRUCT_END(MicrofacetMultiGGX, microfacet_multi_ggx_aniso)
|
||||
|
||||
OSL_CLOSURE_STRUCT_BEGIN(AshikhminVelvet, ashikhmin_velvet)
|
||||
OSL_CLOSURE_STRUCT_MEMBER(AshikhminVelvet, VECTOR, packed_float3, N, nullptr)
|
||||
OSL_CLOSURE_STRUCT_MEMBER(AshikhminVelvet, FLOAT, float, sigma, nullptr)
|
||||
OSL_CLOSURE_STRUCT_END(AshikhminVelvet, ashikhmin_velvet)
|
||||
|
||||
OSL_CLOSURE_STRUCT_BEGIN(Sheen, sheen)
|
||||
OSL_CLOSURE_STRUCT_MEMBER(Sheen, VECTOR, packed_float3, N, nullptr)
|
||||
OSL_CLOSURE_STRUCT_MEMBER(Sheen, FLOAT, float, roughness, nullptr)
|
||||
OSL_CLOSURE_STRUCT_END(Sheen, sheen)
|
||||
|
||||
OSL_CLOSURE_STRUCT_BEGIN(SheenBSDF, sheen_bsdf)
|
||||
OSL_CLOSURE_STRUCT_MEMBER(SheenBSDF, VECTOR, packed_float3, N, nullptr)
|
||||
OSL_CLOSURE_STRUCT_MEMBER(SheenBSDF, VECTOR, packed_float3, albedo, nullptr)
|
||||
OSL_CLOSURE_STRUCT_MEMBER(SheenBSDF, FLOAT, float, roughness, nullptr)
|
||||
OSL_CLOSURE_STRUCT_END(SheenBSDF, sheen_bsdf)
|
||||
|
||||
OSL_CLOSURE_STRUCT_BEGIN(DiffuseToon, diffuse_toon)
|
||||
OSL_CLOSURE_STRUCT_MEMBER(DiffuseToon, VECTOR, packed_float3, N, nullptr)
|
||||
OSL_CLOSURE_STRUCT_MEMBER(DiffuseToon, FLOAT, float, size, nullptr)
|
||||
OSL_CLOSURE_STRUCT_MEMBER(DiffuseToon, FLOAT, float, smooth, nullptr)
|
||||
OSL_CLOSURE_STRUCT_END(DiffuseToon, diffuse_toon)
|
||||
|
||||
OSL_CLOSURE_STRUCT_BEGIN(GlossyToon, glossy_toon)
|
||||
OSL_CLOSURE_STRUCT_MEMBER(GlossyToon, VECTOR, packed_float3, N, nullptr)
|
||||
OSL_CLOSURE_STRUCT_MEMBER(GlossyToon, FLOAT, float, size, nullptr)
|
||||
OSL_CLOSURE_STRUCT_MEMBER(GlossyToon, FLOAT, float, smooth, nullptr)
|
||||
OSL_CLOSURE_STRUCT_END(GlossyToon, glossy_toon)
|
||||
|
||||
OSL_CLOSURE_STRUCT_BEGIN(GenericEmissive, emission)
|
||||
OSL_CLOSURE_STRUCT_END(GenericEmissive, emission)
|
||||
|
||||
OSL_CLOSURE_STRUCT_BEGIN(GenericBackground, background)
|
||||
OSL_CLOSURE_STRUCT_END(GenericBackground, background)
|
||||
|
||||
OSL_CLOSURE_STRUCT_BEGIN(UniformEDF, uniform_edf)
|
||||
OSL_CLOSURE_STRUCT_MEMBER(UniformEDF, COLOR, packed_float3, emittance, nullptr)
|
||||
OSL_CLOSURE_STRUCT_END(UniformEDF, uniform_edf)
|
||||
|
||||
OSL_CLOSURE_STRUCT_BEGIN(Holdout, holdout)
|
||||
OSL_CLOSURE_STRUCT_END(Holdout, holdout)
|
||||
|
||||
OSL_CLOSURE_STRUCT_BEGIN(DiffuseRamp, diffuse_ramp)
|
||||
OSL_CLOSURE_STRUCT_MEMBER(DiffuseRamp, VECTOR, packed_float3, N, nullptr)
|
||||
OSL_CLOSURE_STRUCT_ARRAY_MEMBER(DiffuseRamp, COLOR, packed_float3, colors, nullptr, 8)
|
||||
OSL_CLOSURE_STRUCT_END(DiffuseRamp, diffuse_ramp)
|
||||
|
||||
OSL_CLOSURE_STRUCT_BEGIN(PhongRamp, phong_ramp)
|
||||
OSL_CLOSURE_STRUCT_MEMBER(PhongRamp, VECTOR, packed_float3, N, nullptr)
|
||||
OSL_CLOSURE_STRUCT_MEMBER(PhongRamp, FLOAT, float, exponent, nullptr)
|
||||
OSL_CLOSURE_STRUCT_ARRAY_MEMBER(PhongRamp, COLOR, packed_float3, colors, nullptr, 8)
|
||||
OSL_CLOSURE_STRUCT_END(PhongRamp, phong_ramp)
|
||||
|
||||
OSL_CLOSURE_STRUCT_BEGIN(BSSRDF, bssrdf)
|
||||
OSL_CLOSURE_STRUCT_MEMBER(BSSRDF, STRING, DeviceString, method, nullptr)
|
||||
OSL_CLOSURE_STRUCT_MEMBER(BSSRDF, VECTOR, packed_float3, N, nullptr)
|
||||
OSL_CLOSURE_STRUCT_MEMBER(BSSRDF, VECTOR, packed_float3, radius, nullptr)
|
||||
OSL_CLOSURE_STRUCT_MEMBER(BSSRDF, VECTOR, packed_float3, albedo, nullptr)
|
||||
OSL_CLOSURE_STRUCT_MEMBER(BSSRDF, FLOAT, float, roughness, "roughness")
|
||||
OSL_CLOSURE_STRUCT_MEMBER(BSSRDF, FLOAT, float, ior, "ior")
|
||||
OSL_CLOSURE_STRUCT_MEMBER(BSSRDF, FLOAT, float, anisotropy, "anisotropy")
|
||||
OSL_CLOSURE_STRUCT_END(BSSRDF, bssrdf)
|
||||
|
||||
OSL_CLOSURE_STRUCT_BEGIN(SubsurfaceBSSRDF, subsurface_bssrdf)
|
||||
OSL_CLOSURE_STRUCT_MEMBER(SubsurfaceBSSRDF, VECTOR, packed_float3, N, nullptr)
|
||||
OSL_CLOSURE_STRUCT_MEMBER(SubsurfaceBSSRDF, VECTOR, packed_float3, albedo, nullptr)
|
||||
#if OSL_LIBRARY_VERSION_CODE >= 11401
|
||||
OSL_CLOSURE_STRUCT_MEMBER(SubsurfaceBSSRDF, VECTOR, packed_float3, radius, nullptr)
|
||||
#else
|
||||
OSL_CLOSURE_STRUCT_MEMBER(SubsurfaceBSSRDF, FLOAT, float, transmission_depth, nullptr)
|
||||
OSL_CLOSURE_STRUCT_MEMBER(SubsurfaceBSSRDF, VECTOR, packed_float3, transmission_color, nullptr)
|
||||
#endif
|
||||
OSL_CLOSURE_STRUCT_MEMBER(SubsurfaceBSSRDF, FLOAT, float, anisotropy, nullptr)
|
||||
OSL_CLOSURE_STRUCT_END(SubsurfaceBSSRDF, subsurface_bssrdf)
|
||||
|
||||
OSL_CLOSURE_STRUCT_BEGIN(HairReflection, hair_reflection)
|
||||
OSL_CLOSURE_STRUCT_MEMBER(HairReflection, VECTOR, packed_float3, N, nullptr)
|
||||
OSL_CLOSURE_STRUCT_MEMBER(HairReflection, FLOAT, float, roughness1, nullptr)
|
||||
OSL_CLOSURE_STRUCT_MEMBER(HairReflection, FLOAT, float, roughness2, nullptr)
|
||||
OSL_CLOSURE_STRUCT_MEMBER(HairReflection, VECTOR, packed_float3, T, nullptr)
|
||||
OSL_CLOSURE_STRUCT_MEMBER(HairReflection, FLOAT, float, offset, nullptr)
|
||||
OSL_CLOSURE_STRUCT_END(HairReflection, hair_reflection)
|
||||
|
||||
OSL_CLOSURE_STRUCT_BEGIN(HairTransmission, hair_transmission)
|
||||
OSL_CLOSURE_STRUCT_MEMBER(HairTransmission, VECTOR, packed_float3, N, nullptr)
|
||||
OSL_CLOSURE_STRUCT_MEMBER(HairTransmission, FLOAT, float, roughness1, nullptr)
|
||||
OSL_CLOSURE_STRUCT_MEMBER(HairTransmission, FLOAT, float, roughness2, nullptr)
|
||||
OSL_CLOSURE_STRUCT_MEMBER(HairReflection, VECTOR, packed_float3, T, nullptr)
|
||||
OSL_CLOSURE_STRUCT_MEMBER(HairReflection, FLOAT, float, offset, nullptr)
|
||||
OSL_CLOSURE_STRUCT_END(HairTransmission, hair_transmission)
|
||||
|
||||
OSL_CLOSURE_STRUCT_BEGIN(ChiangHair, hair_chiang)
|
||||
OSL_CLOSURE_STRUCT_MEMBER(ChiangHair, VECTOR, packed_float3, N, nullptr)
|
||||
OSL_CLOSURE_STRUCT_MEMBER(ChiangHair, VECTOR, packed_float3, sigma, nullptr)
|
||||
OSL_CLOSURE_STRUCT_MEMBER(ChiangHair, FLOAT, float, v, nullptr)
|
||||
OSL_CLOSURE_STRUCT_MEMBER(ChiangHair, FLOAT, float, s, nullptr)
|
||||
OSL_CLOSURE_STRUCT_MEMBER(ChiangHair, FLOAT, float, m0_roughness, nullptr)
|
||||
OSL_CLOSURE_STRUCT_MEMBER(ChiangHair, FLOAT, float, alpha, nullptr)
|
||||
OSL_CLOSURE_STRUCT_MEMBER(ChiangHair, FLOAT, float, eta, nullptr)
|
||||
OSL_CLOSURE_STRUCT_END(ChiangHair, hair_chiang)
|
||||
|
||||
OSL_CLOSURE_STRUCT_BEGIN(HuangHair, hair_huang)
|
||||
OSL_CLOSURE_STRUCT_MEMBER(HuangHair, VECTOR, packed_float3, N, nullptr)
|
||||
OSL_CLOSURE_STRUCT_MEMBER(HuangHair, VECTOR, packed_float3, sigma, nullptr)
|
||||
OSL_CLOSURE_STRUCT_MEMBER(HuangHair, FLOAT, float, roughness, nullptr)
|
||||
OSL_CLOSURE_STRUCT_MEMBER(HuangHair, FLOAT, float, tilt, nullptr)
|
||||
OSL_CLOSURE_STRUCT_MEMBER(HuangHair, FLOAT, float, eta, nullptr)
|
||||
OSL_CLOSURE_STRUCT_MEMBER(HuangHair, FLOAT, float, aspect_ratio, nullptr)
|
||||
OSL_CLOSURE_STRUCT_MEMBER(HuangHair, FLOAT, float, r_lobe, nullptr)
|
||||
OSL_CLOSURE_STRUCT_MEMBER(HuangHair, FLOAT, float, tt_lobe, nullptr)
|
||||
OSL_CLOSURE_STRUCT_MEMBER(HuangHair, FLOAT, float, trt_lobe, nullptr)
|
||||
OSL_CLOSURE_STRUCT_END(HuangHair, hair_huang)
|
||||
|
||||
OSL_CLOSURE_STRUCT_BEGIN(VolumeAbsorption, absorption)
|
||||
OSL_CLOSURE_STRUCT_END(VolumeAbsorption, absorption)
|
||||
|
||||
OSL_CLOSURE_STRUCT_BEGIN(VolumeHenyeyGreenstein, henyey_greenstein)
|
||||
OSL_CLOSURE_STRUCT_MEMBER(VolumeHenyeyGreenstein, FLOAT, float, g, nullptr)
|
||||
OSL_CLOSURE_STRUCT_END(VolumeHenyeyGreenstein, henyey_greenstein)
|
||||
|
||||
OSL_CLOSURE_STRUCT_BEGIN(VolumeFournierForand, fournier_forand)
|
||||
OSL_CLOSURE_STRUCT_MEMBER(VolumeFournierForand, FLOAT, float, B, nullptr)
|
||||
OSL_CLOSURE_STRUCT_MEMBER(VolumeFournierForand, FLOAT, float, IOR, nullptr)
|
||||
OSL_CLOSURE_STRUCT_END(VolumeFournierForand, fournier_forand)
|
||||
|
||||
OSL_CLOSURE_STRUCT_BEGIN(VolumeDraine, draine)
|
||||
OSL_CLOSURE_STRUCT_MEMBER(VolumeDraine, FLOAT, float, g, nullptr)
|
||||
OSL_CLOSURE_STRUCT_MEMBER(VolumeDraine, FLOAT, float, alpha, nullptr)
|
||||
OSL_CLOSURE_STRUCT_END(VolumeDraine, draine)
|
||||
|
||||
OSL_CLOSURE_STRUCT_BEGIN(VolumeRayleigh, rayleigh)
|
||||
OSL_CLOSURE_STRUCT_END(VolumeRayleigh, rayleigh)
|
||||
|
||||
OSL_CLOSURE_STRUCT_BEGIN(AnisotropicVDF, anisotropic_vdf)
|
||||
OSL_CLOSURE_STRUCT_MEMBER(AnisotropicVDF, COLOR, packed_float3, albedo, nullptr)
|
||||
OSL_CLOSURE_STRUCT_MEMBER(AnisotropicVDF, COLOR, packed_float3, extinction, nullptr)
|
||||
OSL_CLOSURE_STRUCT_MEMBER(AnisotropicVDF, FLOAT, float, anisotropy, nullptr)
|
||||
OSL_CLOSURE_STRUCT_END(AnisotropicVDF, anisotropic_vdf)
|
||||
|
||||
#undef OSL_CLOSURE_STRUCT_BEGIN
|
||||
#undef OSL_CLOSURE_STRUCT_END
|
||||
#undef OSL_CLOSURE_STRUCT_MEMBER
|
||||
#undef OSL_CLOSURE_STRUCT_ARRAY_MEMBER
|
||||
23
blender-5.2.0/intern/cycles/kernel/osl/compat.h
Normal file
23
blender-5.2.0/intern/cycles/kernel/osl/compat.h
Normal file
@@ -0,0 +1,23 @@
|
||||
/* SPDX-FileCopyrightText: 2011-2023 Blender Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <OSL/oslconfig.h>
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
||||
using OSLUStringHash = OSL::ustringhash;
|
||||
#if OSL_LIBRARY_VERSION_CODE >= 11400
|
||||
using OSLUStringRep = OSL::ustringhash;
|
||||
#else
|
||||
using OSLUStringRep = OSL::ustringrep;
|
||||
#endif
|
||||
|
||||
static inline OSL::ustring to_ustring(OSLUStringHash h)
|
||||
{
|
||||
return OSL::ustring::from_hash(h.hash());
|
||||
}
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
62
blender-5.2.0/intern/cycles/kernel/osl/globals.cpp
Normal file
62
blender-5.2.0/intern/cycles/kernel/osl/globals.cpp
Normal file
@@ -0,0 +1,62 @@
|
||||
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 */
|
||||
|
||||
#include <cstdint> /* Needed before `sdlexec.h` for `int32_t` with GCC 15.1. */
|
||||
|
||||
#include <OSL/oslexec.h>
|
||||
|
||||
#include "kernel/osl/globals.h"
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
||||
OSLThreadData::OSLThreadData(OSLGlobals *osl_globals, const int thread_index)
|
||||
: globals(osl_globals), thread_index(thread_index)
|
||||
{
|
||||
/* If OSL is not used, we don't need this. */
|
||||
if (globals == nullptr || !(globals->use_shading || globals->use_camera)) {
|
||||
return;
|
||||
}
|
||||
|
||||
ss = globals->ss;
|
||||
|
||||
memset((void *)&shader_globals, 0, sizeof(shader_globals));
|
||||
shader_globals.tracedata = &tracedata;
|
||||
|
||||
if (ss) {
|
||||
osl_thread_info = ss->create_thread_info();
|
||||
/* Dummy texture thread info, we don't need it. */
|
||||
context = ss->get_context(osl_thread_info,
|
||||
reinterpret_cast<OSL::TextureSystem::Perthread *>(1));
|
||||
}
|
||||
}
|
||||
|
||||
OSLThreadData::~OSLThreadData()
|
||||
{
|
||||
if (context) {
|
||||
ss->release_context(context);
|
||||
}
|
||||
if (osl_thread_info) {
|
||||
ss->destroy_thread_info(osl_thread_info);
|
||||
}
|
||||
}
|
||||
|
||||
OSLThreadData::OSLThreadData(OSLThreadData &&other) noexcept
|
||||
: globals(other.globals),
|
||||
ss(other.ss),
|
||||
thread_index(other.thread_index),
|
||||
shader_globals(other.shader_globals),
|
||||
tracedata(other.tracedata),
|
||||
osl_thread_info(other.osl_thread_info),
|
||||
context(other.context)
|
||||
{
|
||||
shader_globals.tracedata = &tracedata;
|
||||
|
||||
memset((void *)&other.shader_globals, 0, sizeof(other.shader_globals));
|
||||
memset((void *)&other.tracedata, 0, sizeof(other.tracedata));
|
||||
other.thread_index = -1;
|
||||
other.context = nullptr;
|
||||
other.osl_thread_info = nullptr;
|
||||
}
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
104
blender-5.2.0/intern/cycles/kernel/osl/globals.h
Normal file
104
blender-5.2.0/intern/cycles/kernel/osl/globals.h
Normal file
@@ -0,0 +1,104 @@
|
||||
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 */
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef WITH_OSL
|
||||
|
||||
# include <OSL/oslexec.h>
|
||||
|
||||
# include "util/map.h"
|
||||
# include "util/param.h"
|
||||
# include "util/vector.h"
|
||||
|
||||
# include "kernel/types.h"
|
||||
|
||||
# include "kernel/osl/compat.h"
|
||||
# include "kernel/osl/types.h"
|
||||
|
||||
# ifndef WIN32
|
||||
using std::isfinite;
|
||||
# endif
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
||||
class OSLRenderServices;
|
||||
class ColorSpaceProcessor;
|
||||
struct ThreadKernelGlobalsCPU;
|
||||
|
||||
/* OSL Globals
|
||||
*
|
||||
* Data needed by OSL render services, that is global to a rendering session.
|
||||
* This includes all OSL shaders, name to attribute mapping and texture handles.
|
||||
*/
|
||||
|
||||
struct OSLGlobals {
|
||||
OSLGlobals()
|
||||
{
|
||||
ss = nullptr;
|
||||
services = nullptr;
|
||||
use_shading = false;
|
||||
use_camera = false;
|
||||
}
|
||||
|
||||
bool use_shading;
|
||||
bool use_camera;
|
||||
|
||||
/* shading system */
|
||||
OSL::ShadingSystem *ss;
|
||||
OSLRenderServices *services;
|
||||
|
||||
/* shader states */
|
||||
vector<OSL::ShaderGroupRef> surface_state;
|
||||
vector<OSL::ShaderGroupRef> volume_state;
|
||||
vector<OSL::ShaderGroupRef> displacement_state;
|
||||
vector<OSL::ShaderGroupRef> bump_state;
|
||||
OSL::ShaderGroupRef background_state;
|
||||
OSL::ShaderGroupRef camera_state;
|
||||
|
||||
/* attributes */
|
||||
using ObjectNameMap = unordered_map<OSLUStringHash, int>;
|
||||
|
||||
ObjectNameMap object_name_map;
|
||||
vector<ustring> object_names;
|
||||
};
|
||||
|
||||
/* trace() call result */
|
||||
struct OSLTraceData {
|
||||
Ray ray;
|
||||
Intersection isect;
|
||||
ShaderData sd;
|
||||
bool setup;
|
||||
bool init;
|
||||
bool hit;
|
||||
bool self_hit;
|
||||
};
|
||||
|
||||
/* thread key for thread specific data lookup */
|
||||
struct OSLThreadData {
|
||||
/* Global Data */
|
||||
OSLGlobals *globals = nullptr;
|
||||
OSL::ShadingSystem *ss = nullptr;
|
||||
|
||||
/* Per-thread data. */
|
||||
int thread_index = -1;
|
||||
|
||||
mutable ShaderGlobals shader_globals;
|
||||
mutable OSLTraceData tracedata;
|
||||
|
||||
OSL::PerThreadInfo *osl_thread_info = nullptr;
|
||||
OSL::ShadingContext *context = nullptr;
|
||||
|
||||
OSLThreadData(OSLGlobals *globals, const int thread_index);
|
||||
~OSLThreadData();
|
||||
|
||||
OSLThreadData(OSLThreadData &other) = delete;
|
||||
OSLThreadData(OSLThreadData &&other) noexcept;
|
||||
OSLThreadData &operator=(const OSLThreadData &other) = delete;
|
||||
OSLThreadData &operator=(OSLThreadData &&other) = delete;
|
||||
};
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
|
||||
#endif
|
||||
290
blender-5.2.0/intern/cycles/kernel/osl/osl.h
Normal file
290
blender-5.2.0/intern/cycles/kernel/osl/osl.h
Normal file
@@ -0,0 +1,290 @@
|
||||
/* SPDX-FileCopyrightText: 2009-2010 Sony Pictures Imageworks Inc., et al. All Rights Reserved.
|
||||
* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*
|
||||
* Adapted code from Open Shading Language. */
|
||||
|
||||
#pragma once
|
||||
|
||||
/* OSL Shader Engine
|
||||
*
|
||||
* Holds all variables to execute and use OSL shaders from the kernel.
|
||||
*/
|
||||
|
||||
#ifdef __KERNEL_OPTIX__
|
||||
# include "kernel/geom/attribute.h"
|
||||
# include "kernel/geom/primitive.h"
|
||||
#endif
|
||||
|
||||
#include "kernel/osl/closures_setup.h"
|
||||
#include "kernel/osl/types.h"
|
||||
|
||||
#include "kernel/util/differential.h"
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
||||
ccl_device_inline void shaderdata_to_shaderglobals(ccl_private ShaderData *sd,
|
||||
const PathRayVisibility path_visibility,
|
||||
const uint32_t path_flag,
|
||||
ccl_private ShaderGlobals *globals)
|
||||
{
|
||||
const differential3 dP = differential_from_compact(sd->Ng, sd->dP);
|
||||
const differential3 dI = differential_from_compact(sd->wi, sd->dI);
|
||||
|
||||
/* copy from shader data to shader globals */
|
||||
globals->P = sd->P;
|
||||
globals->dPdx = dP.dx;
|
||||
globals->dPdy = dP.dy;
|
||||
globals->I = sd->wi;
|
||||
globals->dIdx = dI.dx;
|
||||
globals->dIdy = dI.dy;
|
||||
globals->N = sd->N;
|
||||
globals->Ng = sd->Ng;
|
||||
globals->u = sd->u;
|
||||
globals->dudx = sd->du.dx;
|
||||
globals->dudy = sd->du.dy;
|
||||
globals->v = sd->v;
|
||||
globals->dvdx = sd->dv.dx;
|
||||
globals->dvdy = sd->dv.dy;
|
||||
globals->dPdu = sd->dPdu;
|
||||
globals->dPdv = sd->dPdv;
|
||||
globals->time = sd->time;
|
||||
globals->dtime = 1.0f;
|
||||
globals->surfacearea = 1.0f;
|
||||
globals->raytype = OSL_RAYTYPE_PACK(path_visibility, path_flag);
|
||||
globals->flipHandedness = 0;
|
||||
globals->backfacing = (sd->flag & SD_BACKFACING);
|
||||
|
||||
/* shader data to be used in services callbacks */
|
||||
globals->sd = sd;
|
||||
globals->shadingStateUniform = nullptr;
|
||||
globals->thread_index = 0;
|
||||
globals->shade_index = 0;
|
||||
|
||||
/* hacky, we leave it to services to fetch actual object matrix */
|
||||
globals->shader2common = sd;
|
||||
globals->object2common = sd;
|
||||
|
||||
/* must be set to nullptr before execute */
|
||||
globals->Ci = nullptr;
|
||||
}
|
||||
|
||||
ccl_device void flatten_closure_tree(KernelGlobals kg,
|
||||
ccl_private ShaderData *sd,
|
||||
const PathRayVisibility ray_visibility,
|
||||
const uint32_t path_flag,
|
||||
const ccl_private OSLClosure *closure)
|
||||
{
|
||||
int stack_size = 0;
|
||||
float3 weight = one_float3();
|
||||
float3 weight_stack[16];
|
||||
const ccl_private OSLClosure *closure_stack[16];
|
||||
int layer_stack_level = -1;
|
||||
float3 layer_albedo = zero_float3();
|
||||
|
||||
while (true) {
|
||||
switch (closure->id) {
|
||||
case OSL_CLOSURE_MUL_ID: {
|
||||
const ccl_private OSLClosureMul *mul = static_cast<const ccl_private OSLClosureMul *>(
|
||||
closure);
|
||||
weight *= mul->weight;
|
||||
closure = mul->closure;
|
||||
continue;
|
||||
}
|
||||
case OSL_CLOSURE_ADD_ID: {
|
||||
if (stack_size >= 16) {
|
||||
kernel_assert(!"Exhausted OSL closure stack");
|
||||
break;
|
||||
}
|
||||
const ccl_private OSLClosureAdd *add = static_cast<const ccl_private OSLClosureAdd *>(
|
||||
closure);
|
||||
closure = add->closureA;
|
||||
weight_stack[stack_size] = weight;
|
||||
closure_stack[stack_size++] = add->closureB;
|
||||
continue;
|
||||
}
|
||||
case OSL_CLOSURE_LAYER_ID: {
|
||||
const ccl_private OSLClosureComponent *comp =
|
||||
static_cast<const ccl_private OSLClosureComponent *>(closure);
|
||||
const ccl_private LayerClosure *layer = reinterpret_cast<const ccl_private LayerClosure *>(
|
||||
comp + 1);
|
||||
|
||||
/* Layer closures may not appear in the top layer subtree of another layer closure. */
|
||||
kernel_assert(layer_stack_level == -1);
|
||||
|
||||
if (layer->top != nullptr) {
|
||||
/* Push base layer onto the stack, will be handled after the top layers */
|
||||
weight_stack[stack_size] = weight;
|
||||
closure_stack[stack_size] = layer->base;
|
||||
/* Start accumulating albedo of the top layers */
|
||||
layer_stack_level = stack_size++;
|
||||
layer_albedo = zero_float3();
|
||||
/* Continue with the top layers */
|
||||
closure = layer->top;
|
||||
}
|
||||
else {
|
||||
/* No top layer, just continue with base. */
|
||||
closure = layer->base;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
#define OSL_CLOSURE_STRUCT_BEGIN(Upper, lower) \
|
||||
case OSL_CLOSURE_##Upper##_ID: { \
|
||||
ccl_private const OSLClosureComponent *comp = \
|
||||
static_cast<ccl_private const OSLClosureComponent *>(closure); \
|
||||
float3 albedo = one_float3(); \
|
||||
osl_closure_##lower##_setup(kg, \
|
||||
sd, \
|
||||
ray_visibility, \
|
||||
path_flag, \
|
||||
weight * comp->weight, \
|
||||
reinterpret_cast<ccl_private const Upper##Closure *>(comp + 1), \
|
||||
(layer_stack_level >= 0) ? &albedo : nullptr); \
|
||||
if (layer_stack_level >= 0) { \
|
||||
layer_albedo += albedo; \
|
||||
} \
|
||||
break; \
|
||||
}
|
||||
#include "closures_template.h"
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/* 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) {
|
||||
/* We just finished processing the top layers of a Layer closure, so adjust the weight to
|
||||
* account for the layering. */
|
||||
weight = closure_layering_weight(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)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
} while (closure == nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef __KERNEL_GPU__
|
||||
|
||||
template<ShaderType type, typename ConstIntegratorGenericState>
|
||||
void osl_eval_nodes(const ThreadKernelGlobalsCPU *kg,
|
||||
ConstIntegratorGenericState state,
|
||||
ShaderData *sd,
|
||||
PathRayVisibility path_visibility,
|
||||
uint32_t path_flag);
|
||||
|
||||
#else
|
||||
|
||||
template<ShaderType type, typename ConstIntegratorGenericState>
|
||||
ccl_device_inline void osl_eval_nodes(KernelGlobals kg,
|
||||
ConstIntegratorGenericState state,
|
||||
ccl_private ShaderData *sd,
|
||||
const PathRayVisibility path_visibility,
|
||||
const uint32_t path_flag)
|
||||
{
|
||||
ShaderGlobals globals;
|
||||
shaderdata_to_shaderglobals(sd, path_visibility, path_flag, &globals);
|
||||
|
||||
const int shader = sd->shader & SHADER_MASK;
|
||||
|
||||
# ifdef __KERNEL_OPTIX__
|
||||
uint8_t closure_pool[1024];
|
||||
globals.closure_pool = closure_pool;
|
||||
if constexpr (std::is_same_v<ConstIntegratorGenericState, ConstIntegratorBakeState>) {
|
||||
globals.shade_index = 0;
|
||||
}
|
||||
else if constexpr (std::is_same_v<ConstIntegratorGenericState, ConstIntegratorShadowState>) {
|
||||
globals.shade_index = -state - 1;
|
||||
}
|
||||
else {
|
||||
globals.shade_index = state + 1;
|
||||
}
|
||||
|
||||
/* For surface shaders, we might have an automatic bump shader that needs to be executed before
|
||||
* the main shader to update globals.N. */
|
||||
if constexpr (type == SHADER_TYPE_SURFACE) {
|
||||
if (sd->flag & SD_HAS_BUMP_FROM_DISPLACEMENT) {
|
||||
/* Save state. */
|
||||
const float3 P = sd->P;
|
||||
const float dP = sd->dP;
|
||||
const packed_float3 dPdx = globals.dPdx;
|
||||
const packed_float3 dPdy = globals.dPdy;
|
||||
|
||||
/* Set position state as if undisplaced. */
|
||||
if (sd->flag & SD_HAS_DISPLACEMENT) {
|
||||
const AttributeDescriptor desc = find_attribute(kg, sd, ATTR_STD_POSITION_UNDISPLACED);
|
||||
kernel_assert(is_attribute_found(desc));
|
||||
|
||||
dual3 P = primitive_surface_attribute<dual3>(kg, sd, desc);
|
||||
|
||||
object_position_transform(kg, sd, &P);
|
||||
|
||||
sd->P = P.val;
|
||||
sd->dP = differential_make_compact(P);
|
||||
|
||||
globals.P = sd->P;
|
||||
globals.dPdx = P.dx;
|
||||
globals.dPdy = P.dy;
|
||||
|
||||
/* Set normal as if undisplaced. */
|
||||
primitive_normal_set_undisplaced(kg, sd, desc.offset);
|
||||
globals.N = sd->N;
|
||||
}
|
||||
|
||||
/* Execute bump shader. */
|
||||
unsigned int optix_dc_index = 2 /* NUM_CALLABLE_PROGRAM_GROUPS */ + 1 /* camera program */ +
|
||||
(shader + SHADER_TYPE_BUMP * kernel_data.max_shaders);
|
||||
optixDirectCall<void>(optix_dc_index,
|
||||
/* shaderglobals_ptr = */ &globals,
|
||||
/* groupdata_ptr = */ (void *)nullptr,
|
||||
/* userdata_base_ptr = */ (void *)nullptr,
|
||||
/* output_base_ptr = */ (void *)nullptr,
|
||||
/* shadeindex = */ 0,
|
||||
/* interactive_params_ptr */ (void *)nullptr);
|
||||
|
||||
/* Reset state. */
|
||||
sd->P = P;
|
||||
sd->dP = dP;
|
||||
|
||||
/* Apply bump output to sd->N since it's used for shadow terminator logic, for example. */
|
||||
sd->N = globals.N;
|
||||
|
||||
globals.P = P;
|
||||
globals.dPdx = dPdx;
|
||||
globals.dPdy = dPdy;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int optix_dc_index = 2 /* NUM_CALLABLE_PROGRAM_GROUPS */ + 1 /* camera program */ +
|
||||
(shader + type * kernel_data.max_shaders);
|
||||
optixDirectCall<void>(optix_dc_index,
|
||||
/* shaderglobals_ptr = */ &globals,
|
||||
/* groupdata_ptr = */ (void *)nullptr,
|
||||
/* userdata_base_ptr = */ (void *)nullptr,
|
||||
/* output_base_ptr = */ (void *)nullptr,
|
||||
/* shadeindex = */ 0,
|
||||
/* interactive_params_ptr */ (void *)nullptr);
|
||||
# endif
|
||||
|
||||
if constexpr (type == SHADER_TYPE_DISPLACEMENT) {
|
||||
sd->P = globals.P;
|
||||
}
|
||||
else if (globals.Ci) {
|
||||
flatten_closure_tree(kg, sd, path_visibility, path_flag, globals.Ci);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
642
blender-5.2.0/intern/cycles/kernel/osl/services.cpp
Normal file
642
blender-5.2.0/intern/cycles/kernel/osl/services.cpp
Normal file
@@ -0,0 +1,642 @@
|
||||
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 */
|
||||
|
||||
/* TODO(sergey): There is a bit of headers dependency hell going on
|
||||
* here, so for now we just put here. In the future it might be better
|
||||
* to have dedicated file for such tweaks.
|
||||
*/
|
||||
#if (defined(__GNUC__) && !defined(__clang__)) && defined(NDEBUG)
|
||||
# pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
|
||||
# pragma GCC diagnostic ignored "-Wuninitialized"
|
||||
#endif
|
||||
|
||||
#include "util/log.h"
|
||||
#include "util/string.h"
|
||||
#include "util/types_image.h"
|
||||
|
||||
#include "kernel/geom/shader_data.h"
|
||||
|
||||
#include "kernel/bvh/bvh.h"
|
||||
|
||||
#include "kernel/osl/globals.h"
|
||||
#include "kernel/osl/services.h"
|
||||
#include "kernel/osl/services_shared.h"
|
||||
#include "kernel/osl/strings.h"
|
||||
#include "kernel/osl/types.h"
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
||||
/* RenderServices implementation */
|
||||
|
||||
ImageManager *OSLRenderServices::image_manager = nullptr;
|
||||
|
||||
OSLRenderServices::OSLRenderServices(const int device_type)
|
||||
/* Dummy texture system pointer so OSL doesn't create its own. Such an opaque texture system
|
||||
* pointer is supported and normally would be done with the OSL_NO_DEFAULT_TEXTURESYSTEM
|
||||
* build option, but we want to work with OSL builds that don't have it. */
|
||||
: OSL::RendererServices(reinterpret_cast<OSL::TextureSystem *>(1)), device_type_(device_type)
|
||||
{
|
||||
}
|
||||
|
||||
OSLRenderServices::~OSLRenderServices() = default;
|
||||
|
||||
int OSLRenderServices::supports(string_view feature) const
|
||||
{
|
||||
#ifdef WITH_OPTIX
|
||||
if (feature == "OptiX") {
|
||||
return device_type_ == DEVICE_OPTIX;
|
||||
}
|
||||
#else
|
||||
(void)feature;
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool OSLRenderServices::get_matrix(OSL::ShaderGlobals *sg,
|
||||
OSL::Matrix44 &result,
|
||||
OSL::TransformationPtr /*xform*/,
|
||||
const float time)
|
||||
{
|
||||
ShaderGlobals *globals = reinterpret_cast<ShaderGlobals *>(sg);
|
||||
if (globals == nullptr || globals->sd == nullptr) {
|
||||
return false;
|
||||
}
|
||||
return osl_shared_get_object_matrix_motion(
|
||||
globals->kg, globals->sd, reinterpret_cast<float *>(&result), time);
|
||||
}
|
||||
|
||||
bool OSLRenderServices::get_inverse_matrix(OSL::ShaderGlobals *sg,
|
||||
OSL::Matrix44 &result,
|
||||
OSL::TransformationPtr /*xform*/,
|
||||
const float time)
|
||||
{
|
||||
ShaderGlobals *globals = reinterpret_cast<ShaderGlobals *>(sg);
|
||||
if (globals == nullptr || globals->sd == nullptr) {
|
||||
return false;
|
||||
}
|
||||
return osl_shared_get_object_inverse_matrix_motion(
|
||||
globals->kg, globals->sd, reinterpret_cast<float *>(&result), time);
|
||||
}
|
||||
|
||||
bool OSLRenderServices::get_matrix(OSL::ShaderGlobals *sg,
|
||||
OSL::Matrix44 &result,
|
||||
OSLUStringHash from,
|
||||
const float /*time*/)
|
||||
{
|
||||
ShaderGlobals *globals = reinterpret_cast<ShaderGlobals *>(sg);
|
||||
return osl_shared_get_named_matrix(globals->kg, from, reinterpret_cast<float *>(&result));
|
||||
}
|
||||
|
||||
bool OSLRenderServices::get_inverse_matrix(OSL::ShaderGlobals *sg,
|
||||
OSL::Matrix44 &result,
|
||||
OSLUStringHash to,
|
||||
const float /*time*/)
|
||||
{
|
||||
ShaderGlobals *globals = reinterpret_cast<ShaderGlobals *>(sg);
|
||||
return osl_shared_get_named_inverse_matrix(globals->kg, to, reinterpret_cast<float *>(&result));
|
||||
}
|
||||
|
||||
bool OSLRenderServices::get_matrix(OSL::ShaderGlobals *sg,
|
||||
OSL::Matrix44 &result,
|
||||
OSL::TransformationPtr /*xform*/)
|
||||
{
|
||||
ShaderGlobals *globals = reinterpret_cast<ShaderGlobals *>(sg);
|
||||
if (globals == nullptr || globals->sd == nullptr) {
|
||||
return false;
|
||||
}
|
||||
return osl_shared_get_object_matrix(
|
||||
globals->kg, globals->sd, reinterpret_cast<float *>(&result));
|
||||
}
|
||||
|
||||
bool OSLRenderServices::get_inverse_matrix(OSL::ShaderGlobals *sg,
|
||||
OSL::Matrix44 &result,
|
||||
OSL::TransformationPtr /*xform*/)
|
||||
{
|
||||
ShaderGlobals *globals = reinterpret_cast<ShaderGlobals *>(sg);
|
||||
if (globals == nullptr || globals->sd == nullptr) {
|
||||
return false;
|
||||
}
|
||||
return osl_shared_get_object_inverse_matrix(
|
||||
globals->kg, globals->sd, reinterpret_cast<float *>(&result));
|
||||
}
|
||||
|
||||
bool OSLRenderServices::get_matrix(OSL::ShaderGlobals *sg,
|
||||
OSL::Matrix44 &result,
|
||||
OSLUStringHash from)
|
||||
{
|
||||
ShaderGlobals *globals = reinterpret_cast<ShaderGlobals *>(sg);
|
||||
return osl_shared_get_named_matrix(globals->kg, from, reinterpret_cast<float *>(&result));
|
||||
}
|
||||
|
||||
bool OSLRenderServices::get_inverse_matrix(OSL::ShaderGlobals *sg,
|
||||
OSL::Matrix44 &result,
|
||||
OSLUStringHash to)
|
||||
{
|
||||
ShaderGlobals *globals = reinterpret_cast<ShaderGlobals *>(sg);
|
||||
return osl_shared_get_named_inverse_matrix(globals->kg, to, reinterpret_cast<float *>(&result));
|
||||
}
|
||||
|
||||
bool OSLRenderServices::get_array_attribute(OSL::ShaderGlobals * /*sg*/,
|
||||
bool /*derivatives*/,
|
||||
OSLUStringHash /*object*/,
|
||||
const TypeDesc /*type*/,
|
||||
OSLUStringHash /*name*/,
|
||||
const int /*index*/,
|
||||
void * /*val*/)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool OSLRenderServices::get_object_standard_attribute(ShaderGlobals *globals,
|
||||
ShaderData *sd,
|
||||
OSLUStringHash name,
|
||||
const TypeDesc type,
|
||||
bool derivatives,
|
||||
void *val)
|
||||
{
|
||||
return osl_shared_get_object_standard_attribute(
|
||||
globals->kg, globals, sd, name, type, derivatives, val);
|
||||
}
|
||||
|
||||
bool OSLRenderServices::get_background_attribute(ShaderGlobals *globals,
|
||||
ShaderData *sd,
|
||||
OSLUStringHash name,
|
||||
const TypeDesc type,
|
||||
bool derivatives,
|
||||
void *val)
|
||||
{
|
||||
return osl_shared_get_background_attribute(
|
||||
globals->kg, globals, sd, name, type, derivatives, val);
|
||||
}
|
||||
|
||||
bool OSLRenderServices::get_camera_attribute(
|
||||
ShaderGlobals *globals, OSLUStringHash name, TypeDesc type, bool derivatives, void *val)
|
||||
{
|
||||
return osl_shared_get_camera_attribute(globals->kg, globals, name, type, derivatives, val);
|
||||
}
|
||||
|
||||
bool OSLRenderServices::get_attribute(OSL::ShaderGlobals *sg,
|
||||
bool derivatives,
|
||||
OSLUStringHash object_name,
|
||||
const TypeDesc type,
|
||||
OSLUStringHash name,
|
||||
void *val)
|
||||
{
|
||||
ShaderGlobals *globals = reinterpret_cast<ShaderGlobals *>(sg);
|
||||
if (globals == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return get_attribute(globals, globals->sd, derivatives, object_name, type, name, val);
|
||||
}
|
||||
|
||||
bool OSLRenderServices::get_attribute(ShaderGlobals *globals,
|
||||
ShaderData *sd,
|
||||
bool derivatives,
|
||||
OSLUStringHash object_name,
|
||||
const TypeDesc type,
|
||||
OSLUStringHash name,
|
||||
void *val)
|
||||
{
|
||||
|
||||
if (globals == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const ThreadKernelGlobalsCPU *kg = globals->kg;
|
||||
if (sd->shader == SHADER_NONE) {
|
||||
/* Camera shader. */
|
||||
return osl_shared_get_camera_attribute(kg, globals, name, type, derivatives, val);
|
||||
}
|
||||
|
||||
/* lookup of attribute on another object */
|
||||
int object;
|
||||
if (object_name != DeviceStrings::u_empty) {
|
||||
const OSLGlobals::ObjectNameMap::iterator it = kg->osl.globals->object_name_map.find(
|
||||
object_name);
|
||||
|
||||
if (it == kg->osl.globals->object_name_map.end()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
object = it->second;
|
||||
}
|
||||
else {
|
||||
object = sd->object;
|
||||
}
|
||||
|
||||
/* find attribute on object */
|
||||
const AttributeDescriptor desc = find_attribute(kg, object, sd->prim, name.hash());
|
||||
if (is_attribute_found(desc)) {
|
||||
return osl_shared_get_object_attribute(kg, sd, desc, type, derivatives, val);
|
||||
}
|
||||
|
||||
/* not found in attribute, check standard object info */
|
||||
return osl_shared_get_object_standard_attribute(kg, globals, sd, name, type, derivatives, val);
|
||||
}
|
||||
|
||||
bool OSLRenderServices::get_userdata(bool /*derivatives*/,
|
||||
OSLUStringHash /*name*/,
|
||||
const TypeDesc /*type*/,
|
||||
OSL::ShaderGlobals * /*sg*/,
|
||||
void * /*val*/)
|
||||
{
|
||||
return false; /* disabled by lockgeom */
|
||||
}
|
||||
|
||||
OSL::TextureSystem::TextureHandle *OSLRenderServices::get_texture_handle(
|
||||
OSLUStringHash filename, OSL::ShadingContext *context, const OSL::TextureOpt *opt)
|
||||
{
|
||||
return get_texture_handle(to_ustring(filename), context, opt);
|
||||
}
|
||||
|
||||
OSL::TextureSystem::TextureHandle *OSLRenderServices::get_texture_handle(
|
||||
OSL::ustring filename, OSL::ShadingContext * /*context*/, const OSL::TextureOpt * /*options*/)
|
||||
{
|
||||
/* Note the mutex lock in find_or_insert() is not so bad for performance because
|
||||
* this function only gets called once per texture handle to create it, not for
|
||||
* every texture access. */
|
||||
auto [it, inserted] = textures.find_or_insert(filename,
|
||||
OSLTextureHandle(OSLTextureHandleType::IMAGE));
|
||||
|
||||
if (inserted) {
|
||||
/* Add new texture to image manager. */
|
||||
const ImageHandle handle = image_manager->add_image(filename.string(), ImageParams());
|
||||
OSLTextureHandle *texture_handle = const_cast<OSLTextureHandle *>(&it->second);
|
||||
*texture_handle = OSLTextureHandle(handle);
|
||||
}
|
||||
|
||||
/* Construct texture handle. We encode this as a packed integer cast to a pointer,
|
||||
* which is also what we use on the GPU. OSL does not dereference these.
|
||||
*
|
||||
* Note that we must keep the OSLTextureHandle in the map alive, as it holds
|
||||
* the ImageHandle that keeps the image loaded in the manager. */
|
||||
return reinterpret_cast<OSL::TextureSystem::TextureHandle *>(
|
||||
OSL_TEXTURE_HANDLE_ENCODE(it->second.type, it->second.id));
|
||||
}
|
||||
|
||||
bool OSLRenderServices::good(OSL::TextureSystem::TextureHandle *texture_handle)
|
||||
{
|
||||
return OSL_TEXTURE_HANDLE_TYPE(texture_handle) != OSLTextureHandleType::IMAGE ||
|
||||
OSL_TEXTURE_HANDLE_ID(texture_handle) != KERNEL_IMAGE_NONE;
|
||||
}
|
||||
|
||||
bool OSLRenderServices::is_udim(OSL::TextureSystem::TextureHandle *texture_handle)
|
||||
{
|
||||
return OSL_TEXTURE_HANDLE_TYPE(texture_handle) == OSLTextureHandleType::IMAGE &&
|
||||
OSL_TEXTURE_HANDLE_ID(texture_handle) <= -1;
|
||||
}
|
||||
|
||||
bool OSLRenderServices::texture(OSLUStringHash filename,
|
||||
TextureHandle *texture_handle,
|
||||
TexturePerthread * /*texture_thread_info*/,
|
||||
OSL::TextureOpt &options,
|
||||
OSL::ShaderGlobals *sg,
|
||||
float s,
|
||||
float t,
|
||||
const float dsdx,
|
||||
const float dtdx,
|
||||
const float dsdy,
|
||||
const float dtdy,
|
||||
const int nchannels,
|
||||
float *result,
|
||||
float * /*dresultds*/,
|
||||
float * /*dresultdt*/,
|
||||
OSLUStringHash * /*errormessage*/)
|
||||
{
|
||||
if (texture_handle == nullptr) {
|
||||
if (texture_filenames_seen_.insert(filename).second) {
|
||||
LOG_WARNING << "Open Shading Language texture call can not resolve " << filename.c_str()
|
||||
<< ", filename must be a compile-time constant";
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
ShaderGlobals *globals = reinterpret_cast<ShaderGlobals *>(sg);
|
||||
|
||||
return osl_shared_texture(globals->kg,
|
||||
globals,
|
||||
texture_handle,
|
||||
static_cast<void *>(&options),
|
||||
s,
|
||||
t,
|
||||
dsdx,
|
||||
dtdx,
|
||||
dsdy,
|
||||
dtdy,
|
||||
nchannels,
|
||||
result);
|
||||
}
|
||||
|
||||
bool OSLRenderServices::texture3d(OSLUStringHash filename,
|
||||
TextureHandle *texture_handle,
|
||||
TexturePerthread * /*texture_thread_info*/,
|
||||
OSL::TextureOpt & /*options*/,
|
||||
OSL::ShaderGlobals *sg,
|
||||
const OSL::Vec3 &P,
|
||||
const OSL::Vec3 &dPdx,
|
||||
const OSL::Vec3 &dPdy,
|
||||
const OSL::Vec3 &dPdz,
|
||||
const int nchannels,
|
||||
float *result,
|
||||
float * /*dresultds*/,
|
||||
float * /*dresultdt*/,
|
||||
float * /*dresultdr*/,
|
||||
OSLUStringHash * /*errormessage*/)
|
||||
{
|
||||
if (texture_handle == nullptr) {
|
||||
if (texture_filenames_seen_.insert(filename).second) {
|
||||
LOG_WARNING << "Open Shading Language texture3d call can not resolve " << filename.c_str()
|
||||
<< ", filename must be a constant";
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
ShaderGlobals *globals = reinterpret_cast<ShaderGlobals *>(sg);
|
||||
|
||||
return osl_shared_texture3d(globals->kg,
|
||||
globals,
|
||||
texture_handle,
|
||||
make_float3(P.x, P.y, P.z),
|
||||
make_float3(dPdx.x, dPdx.y, dPdx.z),
|
||||
make_float3(dPdy.x, dPdy.y, dPdy.z),
|
||||
make_float3(dPdz.x, dPdz.y, dPdz.z),
|
||||
nchannels,
|
||||
result);
|
||||
}
|
||||
|
||||
bool OSLRenderServices::environment(OSLUStringHash filename,
|
||||
TextureHandle *texture_handle,
|
||||
TexturePerthread * /*thread_info*/,
|
||||
OSL::TextureOpt & /*options*/,
|
||||
OSL::ShaderGlobals *sg,
|
||||
const OSL::Vec3 &R,
|
||||
const OSL::Vec3 &dRdx,
|
||||
const OSL::Vec3 &dRdy,
|
||||
const int nchannels,
|
||||
float *result,
|
||||
float * /*dresultds*/,
|
||||
float * /*dresultdt*/,
|
||||
OSLUStringHash * /*errormessage*/)
|
||||
{
|
||||
if (texture_handle == nullptr) {
|
||||
if (texture_filenames_seen_.insert(filename).second) {
|
||||
LOG_WARNING << "Open Shading Language environment call can not resolve " << filename.c_str()
|
||||
<< ", filename must be a constant string after optimization";
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
ShaderGlobals *globals = reinterpret_cast<ShaderGlobals *>(sg);
|
||||
|
||||
return osl_shared_environment(globals->kg,
|
||||
globals,
|
||||
texture_handle,
|
||||
make_float3(R.x, R.y, R.z),
|
||||
make_float3(dRdx.x, dRdx.y, dRdx.z),
|
||||
make_float3(dRdy.x, dRdy.y, dRdy.z),
|
||||
nchannels,
|
||||
result);
|
||||
}
|
||||
|
||||
bool OSLRenderServices::get_texture_info(OSLUStringHash filename,
|
||||
TextureHandle *texture_handle,
|
||||
TexturePerthread * /*texture_thread_info*/,
|
||||
OSL::ShaderGlobals *sg,
|
||||
const int /*subimage*/,
|
||||
OSLUStringHash dataname,
|
||||
const TypeDesc datatype,
|
||||
void *data,
|
||||
OSLUStringHash * /*errormessage*/)
|
||||
{
|
||||
if (texture_handle == nullptr) {
|
||||
if (texture_filenames_seen_.insert(filename).second) {
|
||||
LOG_WARNING << "Open Shading Language gettextureinfo call can not resolve "
|
||||
<< filename.c_str() << ", filename must be a constant";
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
ShaderGlobals *globals = reinterpret_cast<ShaderGlobals *>(sg);
|
||||
const ThreadKernelGlobalsCPU *kg = globals->kg;
|
||||
|
||||
return osl_shared_get_texture_info(
|
||||
kg, texture_handle, make_float2(0.0f, 0.0f), false, dataname, datatype, data);
|
||||
}
|
||||
|
||||
bool OSLRenderServices::get_texture_info(OSLUStringHash filename,
|
||||
TextureHandle *texture_handle,
|
||||
float s,
|
||||
float t,
|
||||
TexturePerthread * /*texture_thread_info*/,
|
||||
OSL::ShaderGlobals *sg,
|
||||
const int /*subimage*/,
|
||||
OSLUStringHash dataname,
|
||||
const TypeDesc datatype,
|
||||
void *data,
|
||||
OSLUStringHash * /*errormessage*/)
|
||||
{
|
||||
if (texture_handle == nullptr) {
|
||||
if (texture_filenames_seen_.insert(filename).second) {
|
||||
LOG_WARNING << "Open Shading Language gettextureinfo call can not resolve "
|
||||
<< filename.c_str() << ", filename must be a constant";
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
ShaderGlobals *globals = reinterpret_cast<ShaderGlobals *>(sg);
|
||||
const ThreadKernelGlobalsCPU *kg = globals->kg;
|
||||
|
||||
return osl_shared_get_texture_info(
|
||||
kg, texture_handle, make_float2(s, t), true, dataname, datatype, data);
|
||||
}
|
||||
|
||||
int OSLRenderServices::pointcloud_search(OSL::ShaderGlobals * /*sg*/,
|
||||
OSLUStringHash /*filename*/,
|
||||
const OSL::Vec3 & /*center*/,
|
||||
const float /*radius*/,
|
||||
const int /*max_points*/,
|
||||
bool /*sort*/,
|
||||
#if OSL_LIBRARY_VERSION_CODE >= 11400
|
||||
int * /*indices*/,
|
||||
#else
|
||||
size_t * /*out_indices*/,
|
||||
#endif
|
||||
float * /*out_distances*/,
|
||||
const int /*derivs_offset*/)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int OSLRenderServices::pointcloud_get(OSL::ShaderGlobals * /*sg*/
|
||||
,
|
||||
OSLUStringHash /*filename*/,
|
||||
#if OSL_LIBRARY_VERSION_CODE >= 11400
|
||||
const int * /*indices*/,
|
||||
#else
|
||||
size_t * /*indices*/,
|
||||
#endif
|
||||
const int /*count*/,
|
||||
OSLUStringHash /*attr_name*/,
|
||||
const TypeDesc /*attr_type*/,
|
||||
void * /*out_data*/)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool OSLRenderServices::pointcloud_write(OSL::ShaderGlobals * /*sg*/,
|
||||
OSLUStringHash /*filename*/,
|
||||
const OSL::Vec3 & /*pos*/,
|
||||
const int /*nattribs*/,
|
||||
const OSLUStringRep * /*names*/,
|
||||
const TypeDesc * /*types*/,
|
||||
const void ** /*data*/)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool OSLRenderServices::trace(TraceOpt &options,
|
||||
OSL::ShaderGlobals *sg,
|
||||
const OSL::Vec3 &P,
|
||||
const OSL::Vec3 &dPdx,
|
||||
const OSL::Vec3 &dPdy,
|
||||
const OSL::Vec3 &R,
|
||||
const OSL::Vec3 &dRdx,
|
||||
const OSL::Vec3 &dRdy)
|
||||
{
|
||||
/* todo: options.shader support, maybe options.traceset */
|
||||
ShaderGlobals *globals = reinterpret_cast<ShaderGlobals *>(sg);
|
||||
ShaderData *sd = globals->sd;
|
||||
const ThreadKernelGlobalsCPU *kg = globals->kg;
|
||||
|
||||
if (sd == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* setup ray */
|
||||
Ray ray;
|
||||
|
||||
ray.P = make_float3(P.x, P.y, P.z);
|
||||
ray.D = make_float3(R.x, R.y, R.z);
|
||||
ray.tmin = options.mindist;
|
||||
ray.tmax = (options.maxdist == 1.0e30f) ? FLT_MAX : options.maxdist;
|
||||
ray.time = sd->time;
|
||||
ray.self.object = OBJECT_NONE;
|
||||
ray.self.prim = PRIM_NONE;
|
||||
ray.self.light_object = OBJECT_NONE;
|
||||
ray.self.light_prim = PRIM_NONE;
|
||||
|
||||
if (ray.tmin == 0.0f) {
|
||||
/* avoid self-intersections */
|
||||
if (ray.P == sd->P) {
|
||||
ray.self.object = sd->object;
|
||||
ray.self.prim = sd->prim;
|
||||
}
|
||||
}
|
||||
|
||||
/* ray differentials */
|
||||
differential3 dP;
|
||||
dP.dx = make_float3(dPdx.x, dPdx.y, dPdx.z);
|
||||
dP.dy = make_float3(dPdy.x, dPdy.y, dPdy.z);
|
||||
ray.dP = differential_make_compact(dP);
|
||||
differential3 dD;
|
||||
dD.dx = make_float3(dRdx.x, dRdx.y, dRdx.z);
|
||||
dD.dy = make_float3(dRdy.x, dRdy.y, dRdy.z);
|
||||
ray.dD = differential_make_compact(dD);
|
||||
|
||||
/* allocate trace data */
|
||||
OSLTraceData *tracedata = globals->tracedata;
|
||||
tracedata->ray = ray;
|
||||
tracedata->setup = false;
|
||||
tracedata->init = true;
|
||||
tracedata->hit = false;
|
||||
tracedata->self_hit = false;
|
||||
|
||||
/* Can't ray-trace from shaders like displacement, before BVH exists. */
|
||||
if (kernel_data.bvh.bvh_layout == BVH_LAYOUT_NONE) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (options.traceset == DeviceStrings::u_traceset_only_local) {
|
||||
LocalIntersection local_isect;
|
||||
scene_intersect_local(kg, &ray, &local_isect, sd->object, nullptr, 1);
|
||||
if (local_isect.num_hits > 0) {
|
||||
tracedata->isect = local_isect.hits[0];
|
||||
tracedata->hit = true;
|
||||
tracedata->self_hit = true;
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* Ray-trace, leaving out shadow opaque to avoid early exit. */
|
||||
const PathRayVisibility visibility = PATH_RAY_VISIBILITY_ALL &
|
||||
~PATH_RAY_VISIBILITY_SHADOW_OPAQUE;
|
||||
tracedata->hit = scene_intersect(kg, &ray, visibility, &tracedata->isect);
|
||||
if (tracedata->hit) {
|
||||
tracedata->self_hit = tracedata->isect.object == sd->object;
|
||||
}
|
||||
}
|
||||
return tracedata->hit;
|
||||
}
|
||||
|
||||
bool OSLRenderServices::getmessage(OSL::ShaderGlobals *sg,
|
||||
OSLUStringHash source,
|
||||
OSLUStringHash name,
|
||||
const TypeDesc type,
|
||||
void *val,
|
||||
bool derivatives)
|
||||
{
|
||||
ShaderGlobals *globals = reinterpret_cast<ShaderGlobals *>(sg);
|
||||
const ThreadKernelGlobalsCPU *kg = globals->kg;
|
||||
OSLTraceData *tracedata = globals->tracedata;
|
||||
|
||||
if (source == DeviceStrings::u_trace && tracedata->init) {
|
||||
if (name == DeviceStrings::u_hit) {
|
||||
return set_attribute<int>(tracedata->hit, type, derivatives, val);
|
||||
}
|
||||
if (tracedata->hit) {
|
||||
if (name == DeviceStrings::u_hitdist) {
|
||||
return set_attribute(tracedata->isect.t, type, derivatives, val);
|
||||
}
|
||||
|
||||
ShaderData *sd = &tracedata->sd;
|
||||
|
||||
if (!tracedata->setup) {
|
||||
/* lazy shader data setup */
|
||||
shader_setup_from_ray(kg, sd, &tracedata->ray, &tracedata->isect);
|
||||
tracedata->setup = true;
|
||||
}
|
||||
|
||||
if (name == DeviceStrings::u_hitself) {
|
||||
return set_attribute(float(tracedata->self_hit), type, derivatives, val);
|
||||
}
|
||||
if (name == DeviceStrings::u_N) {
|
||||
return set_attribute(sd->N, type, derivatives, val);
|
||||
}
|
||||
if (name == DeviceStrings::u_Ng) {
|
||||
return set_attribute(sd->Ng, type, derivatives, val);
|
||||
}
|
||||
if (name == DeviceStrings::u_P) {
|
||||
const differential3 dP = differential_from_compact(sd->Ng, sd->dP);
|
||||
return set_attribute(dual3(sd->P, dP.dx, dP.dy), type, derivatives, val);
|
||||
}
|
||||
if (name == DeviceStrings::u_I) {
|
||||
const differential3 dI = differential_from_compact(sd->wi, sd->dI);
|
||||
return set_attribute(dual3(sd->wi, dI.dx, dI.dy), type, derivatives, val);
|
||||
}
|
||||
if (name == DeviceStrings::u_u) {
|
||||
return set_attribute(dual1(sd->u, sd->du.dx, sd->du.dy), type, derivatives, val);
|
||||
}
|
||||
if (name == DeviceStrings::u_v) {
|
||||
return set_attribute(dual1(sd->v, sd->dv.dx, sd->dv.dy), type, derivatives, val);
|
||||
}
|
||||
|
||||
return get_attribute(globals, sd, derivatives, DeviceStrings::u_empty, type, name, val);
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
298
blender-5.2.0/intern/cycles/kernel/osl/services.h
Normal file
298
blender-5.2.0/intern/cycles/kernel/osl/services.h
Normal file
@@ -0,0 +1,298 @@
|
||||
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 */
|
||||
|
||||
#pragma once
|
||||
|
||||
/* OSL Render Services
|
||||
*
|
||||
* Implementation of OSL render services, to retriever matrices, attributes,
|
||||
* textures and point clouds. In principle this should only be accessing
|
||||
* kernel data, but currently we also reach back into the Scene to retrieve
|
||||
* attributes.
|
||||
*/
|
||||
|
||||
#include <OSL/oslclosure.h>
|
||||
#include <OSL/oslexec.h>
|
||||
#include <OSL/rendererservices.h>
|
||||
|
||||
#include <OpenImageIO/unordered_map_concurrent.h>
|
||||
|
||||
#include "util/concurrent_set.h"
|
||||
|
||||
#include "scene/image.h"
|
||||
|
||||
#include "kernel/osl/compat.h"
|
||||
#include "kernel/osl/types.h"
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
||||
class Scene;
|
||||
struct ShaderData;
|
||||
struct ThreadKernelGlobalsCPU;
|
||||
|
||||
/* OSL Texture Handle
|
||||
*
|
||||
* OSL texture lookups are string based. If those strings are known at compile
|
||||
* time, the OSL compiler can cache a texture handle to use instead of a string.
|
||||
*
|
||||
* By default it uses TextureSystem::TextureHandle. But since we want to support
|
||||
* different kinds of textures and color space conversions, this is our own handle
|
||||
* with additional data.
|
||||
*
|
||||
* These are stored in a concurrent hash map, because OSL can compile multiple
|
||||
* shaders in parallel.
|
||||
*
|
||||
* NOTE: The svm_image_texture_ids array contains a compressed mapping of tile to
|
||||
* svm_image_texture_ids pairs stored as follows: x:tile_a,
|
||||
* y:svm_image_texture_ids_a, z:tile_b, w:svm_image_texture_ids_b etc. */
|
||||
|
||||
struct OSLTextureHandle {
|
||||
OSLTextureHandle(const OSLTextureHandleType type, const int id = -1) : type(type), id(id) {}
|
||||
|
||||
OSLTextureHandle(const ImageHandle &handle) : id(handle.kernel_id()), handle(handle) {}
|
||||
|
||||
OSLTextureHandleType type = OSLTextureHandleType::IMAGE;
|
||||
int id = -1;
|
||||
ImageHandle handle;
|
||||
};
|
||||
|
||||
using OSLTextureHandleMap = OIIO::unordered_map_concurrent<OSLUStringHash, OSLTextureHandle>;
|
||||
using OSLTextureFilenameMap = concurrent_set<OSLUStringHash>;
|
||||
|
||||
/* OSL Render Services
|
||||
*
|
||||
* Interface for OSL to access attributes, textures and other scene data. */
|
||||
|
||||
class OSLRenderServices : public OSL::RendererServices {
|
||||
public:
|
||||
OSLRenderServices(const int device_type);
|
||||
~OSLRenderServices() override;
|
||||
|
||||
static void register_closures(OSL::ShadingSystem *ss);
|
||||
|
||||
int supports(string_view feature) const override;
|
||||
|
||||
bool get_matrix(OSL::ShaderGlobals *sg,
|
||||
OSL::Matrix44 &result,
|
||||
OSL::TransformationPtr xform,
|
||||
float time) override;
|
||||
bool get_inverse_matrix(OSL::ShaderGlobals *sg,
|
||||
OSL::Matrix44 &result,
|
||||
OSL::TransformationPtr xform,
|
||||
float time) override;
|
||||
|
||||
bool get_matrix(OSL::ShaderGlobals *sg,
|
||||
OSL::Matrix44 &result,
|
||||
OSLUStringHash from,
|
||||
float time) override;
|
||||
bool get_inverse_matrix(OSL::ShaderGlobals *sg,
|
||||
OSL::Matrix44 &result,
|
||||
OSLUStringHash to,
|
||||
float time) override;
|
||||
|
||||
bool get_matrix(OSL::ShaderGlobals *sg,
|
||||
OSL::Matrix44 &result,
|
||||
OSL::TransformationPtr xform) override;
|
||||
bool get_inverse_matrix(OSL::ShaderGlobals *sg,
|
||||
OSL::Matrix44 &result,
|
||||
OSL::TransformationPtr xform) override;
|
||||
|
||||
bool get_matrix(OSL::ShaderGlobals *sg, OSL::Matrix44 &result, OSLUStringHash from) override;
|
||||
bool get_inverse_matrix(OSL::ShaderGlobals *sg,
|
||||
OSL::Matrix44 &result,
|
||||
OSLUStringHash to) override;
|
||||
|
||||
bool get_array_attribute(OSL::ShaderGlobals *sg,
|
||||
bool derivatives,
|
||||
OSLUStringHash object,
|
||||
const TypeDesc type,
|
||||
OSLUStringHash name,
|
||||
const int index,
|
||||
void *val) override;
|
||||
bool get_attribute(OSL::ShaderGlobals *sg,
|
||||
bool derivatives,
|
||||
OSLUStringHash object,
|
||||
const TypeDesc type,
|
||||
OSLUStringHash name,
|
||||
void *val) override;
|
||||
|
||||
bool get_userdata(bool derivatives,
|
||||
OSLUStringHash name,
|
||||
const TypeDesc type,
|
||||
OSL::ShaderGlobals *sg,
|
||||
void *val) override;
|
||||
|
||||
int pointcloud_search(OSL::ShaderGlobals *sg,
|
||||
OSLUStringHash filename,
|
||||
const OSL::Vec3 ¢er,
|
||||
const float radius,
|
||||
const int max_points,
|
||||
bool sort,
|
||||
#if OSL_LIBRARY_VERSION_CODE >= 11400
|
||||
int *out_indices,
|
||||
#else
|
||||
size_t *out_indices,
|
||||
#endif
|
||||
float *out_distances,
|
||||
int derivs_offset) override;
|
||||
|
||||
int pointcloud_get(OSL::ShaderGlobals *sg,
|
||||
OSLUStringHash filename,
|
||||
#if OSL_LIBRARY_VERSION_CODE >= 11400
|
||||
const int *indices,
|
||||
#else
|
||||
size_t *indices,
|
||||
#endif
|
||||
|
||||
const int count,
|
||||
OSLUStringHash attr_name,
|
||||
const TypeDesc attr_type,
|
||||
void *out_data) override;
|
||||
|
||||
bool pointcloud_write(OSL::ShaderGlobals *sg,
|
||||
OSLUStringHash filename,
|
||||
const OSL::Vec3 &pos,
|
||||
const int nattribs,
|
||||
const OSLUStringRep *names,
|
||||
const TypeDesc *types,
|
||||
const void **data) override;
|
||||
|
||||
bool trace(TraceOpt &options,
|
||||
OSL::ShaderGlobals *sg,
|
||||
const OSL::Vec3 &P,
|
||||
const OSL::Vec3 &dPdx,
|
||||
const OSL::Vec3 &dPdy,
|
||||
const OSL::Vec3 &R,
|
||||
const OSL::Vec3 &dRdx,
|
||||
const OSL::Vec3 &dRdy) override;
|
||||
|
||||
bool getmessage(OSL::ShaderGlobals *sg,
|
||||
OSLUStringHash source,
|
||||
OSLUStringHash name,
|
||||
const TypeDesc type,
|
||||
void *val,
|
||||
bool derivatives) override;
|
||||
|
||||
OSL::TextureSystem::TextureHandle *get_texture_handle(OSL::ustring filename,
|
||||
OSL::ShadingContext *context,
|
||||
const OSL::TextureOpt *options) override;
|
||||
OSL::TextureSystem::TextureHandle *get_texture_handle(OSLUStringHash filename,
|
||||
OSL::ShadingContext *context,
|
||||
const OSL::TextureOpt *options) override;
|
||||
|
||||
bool good(OSL::TextureSystem::TextureHandle *texture_handle) override;
|
||||
bool is_udim(OSL::TextureSystem::TextureHandle *texture_handle) override;
|
||||
|
||||
bool texture(OSLUStringHash filename,
|
||||
OSL::TextureSystem::TextureHandle *texture_handle,
|
||||
TexturePerthread *texture_thread_info,
|
||||
OSL::TextureOpt &options,
|
||||
OSL::ShaderGlobals *sg,
|
||||
const float s,
|
||||
const float t,
|
||||
const float dsdx,
|
||||
const float dtdx,
|
||||
const float dsdy,
|
||||
const float dtdy,
|
||||
const int nchannels,
|
||||
float *result,
|
||||
float *dresultds,
|
||||
float *dresultdt,
|
||||
OSLUStringHash *errormessage) override;
|
||||
|
||||
bool texture3d(OSLUStringHash filename,
|
||||
TextureHandle *texture_handle,
|
||||
TexturePerthread *texture_thread_info,
|
||||
OSL::TextureOpt &options,
|
||||
OSL::ShaderGlobals *sg,
|
||||
const OSL::Vec3 &P,
|
||||
const OSL::Vec3 &dPdx,
|
||||
const OSL::Vec3 &dPdy,
|
||||
const OSL::Vec3 &dPdz,
|
||||
const int nchannels,
|
||||
float *result,
|
||||
float *dresultds,
|
||||
float *dresultdt,
|
||||
float *dresultdr,
|
||||
OSLUStringHash *errormessage) override;
|
||||
|
||||
bool environment(OSLUStringHash filename,
|
||||
TextureHandle *texture_handle,
|
||||
TexturePerthread *texture_thread_info,
|
||||
OSL::TextureOpt &options,
|
||||
OSL::ShaderGlobals *sg,
|
||||
const OSL::Vec3 &R,
|
||||
const OSL::Vec3 &dRdx,
|
||||
const OSL::Vec3 &dRdy,
|
||||
const int nchannels,
|
||||
float *result,
|
||||
float *dresultds,
|
||||
float *dresultdt,
|
||||
OSLUStringHash *errormessage) override;
|
||||
|
||||
bool get_texture_info(OSLUStringHash filename,
|
||||
TextureHandle *texture_handle,
|
||||
TexturePerthread *texture_thread_info,
|
||||
OSL::ShaderGlobals *sg,
|
||||
const int subimage,
|
||||
OSLUStringHash dataname,
|
||||
const TypeDesc datatype,
|
||||
void *data,
|
||||
OSLUStringHash *errormessage) override;
|
||||
|
||||
bool get_texture_info(OSLUStringHash filename,
|
||||
TextureHandle *texture_handle,
|
||||
float s,
|
||||
float t,
|
||||
TexturePerthread *texture_thread_info,
|
||||
OSL::ShaderGlobals *sg,
|
||||
const int subimage,
|
||||
OSLUStringHash dataname,
|
||||
const TypeDesc datatype,
|
||||
void *data,
|
||||
OSLUStringHash *errormessage) override;
|
||||
|
||||
static bool get_attribute(ShaderGlobals *globals,
|
||||
ShaderData *sd,
|
||||
bool derivatives,
|
||||
OSLUStringHash object_name,
|
||||
TypeDesc type,
|
||||
OSLUStringHash name,
|
||||
void *val);
|
||||
|
||||
static bool get_background_attribute(ShaderGlobals *globals,
|
||||
ShaderData *sd,
|
||||
OSLUStringHash name,
|
||||
TypeDesc type,
|
||||
bool derivatives,
|
||||
void *val);
|
||||
static bool get_camera_attribute(
|
||||
ShaderGlobals *globals, OSLUStringHash name, TypeDesc type, bool derivatives, void *val);
|
||||
static bool get_object_standard_attribute(ShaderGlobals *globals,
|
||||
ShaderData *sd,
|
||||
OSLUStringHash name,
|
||||
TypeDesc type,
|
||||
bool derivatives,
|
||||
void *val);
|
||||
|
||||
/* Texture system and texture handle map are part of the services instead of
|
||||
* globals to be shared between different render sessions. This saves memory,
|
||||
* and is required because texture handles are cached as part of the shared
|
||||
* shading system. */
|
||||
OSLTextureHandleMap textures;
|
||||
|
||||
static ImageManager *image_manager;
|
||||
|
||||
private:
|
||||
int device_type_;
|
||||
|
||||
/* We don't support lookup by filename without a handle, which is required anyway
|
||||
* for GPU, and simplifies the implementation on CPU. This keeps track of the
|
||||
* ones we have seen to emit a warning only once. */
|
||||
OSLTextureFilenameMap texture_filenames_seen_;
|
||||
|
||||
thread_mutex textures_mutex;
|
||||
};
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
582
blender-5.2.0/intern/cycles/kernel/osl/services_gpu.h
Normal file
582
blender-5.2.0/intern/cycles/kernel/osl/services_gpu.h
Normal file
@@ -0,0 +1,582 @@
|
||||
/* SPDX-FileCopyrightText: 2009-2010 Sony Pictures Imageworks Inc., et al. All Rights Reserved.
|
||||
* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*
|
||||
* Adapted code from Open Shading Language. */
|
||||
|
||||
#include "kernel/geom/attribute.h"
|
||||
|
||||
#include "kernel/util/ies.h"
|
||||
#include "kernel/util/image_3d.h"
|
||||
|
||||
#include "kernel/osl/services_shared.h"
|
||||
#include "kernel/osl/strings.h"
|
||||
|
||||
#include "util/types_image.h"
|
||||
|
||||
#ifndef __KERNEL_GPU__
|
||||
CCL_NAMESPACE_BEGIN
|
||||
#endif
|
||||
|
||||
/* Closure */
|
||||
|
||||
#if OSL_LIBRARY_VERSION_CODE >= 11500
|
||||
|
||||
ccl_device_extern void *rs_allocate_closure(ccl_private ShaderGlobals *sg,
|
||||
const size_t size,
|
||||
const size_t alignment)
|
||||
{
|
||||
ccl_private uint8_t *closure_pool = sg->closure_pool;
|
||||
closure_pool = reinterpret_cast<ccl_private uint8_t *>(
|
||||
(reinterpret_cast<size_t>(closure_pool) + alignment - 1) & (-alignment));
|
||||
sg->closure_pool = closure_pool + size;
|
||||
return closure_pool;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
ccl_device_extern ccl_private OSLClosure *osl_mul_closure_color(ccl_private ShaderGlobals *sg,
|
||||
ccl_private OSLClosure *a,
|
||||
const ccl_private float3 *weight)
|
||||
{
|
||||
if (*weight == zero_float3() || !a) {
|
||||
return nullptr;
|
||||
}
|
||||
if (*weight == one_float3()) {
|
||||
return a;
|
||||
}
|
||||
|
||||
ccl_private uint8_t *closure_pool = sg->closure_pool;
|
||||
/* Align pointer to closure struct requirement */
|
||||
closure_pool = reinterpret_cast<uint8_t *>(
|
||||
(reinterpret_cast<size_t>(closure_pool) + alignof(OSLClosureMul) - 1) &
|
||||
(-alignof(OSLClosureMul)));
|
||||
sg->closure_pool = closure_pool + sizeof(OSLClosureMul);
|
||||
|
||||
ccl_private OSLClosureMul *const closure = reinterpret_cast<ccl_private OSLClosureMul *>(
|
||||
closure_pool);
|
||||
closure->id = OSL_CLOSURE_MUL_ID;
|
||||
closure->weight = *weight;
|
||||
closure->closure = a;
|
||||
|
||||
return closure;
|
||||
}
|
||||
|
||||
ccl_device_extern ccl_private OSLClosure *osl_mul_closure_float(ccl_private ShaderGlobals *sg,
|
||||
ccl_private OSLClosure *a,
|
||||
const float weight)
|
||||
{
|
||||
if (weight == 0.0f || !a) {
|
||||
return nullptr;
|
||||
}
|
||||
if (weight == 1.0f) {
|
||||
return a;
|
||||
}
|
||||
|
||||
ccl_private uint8_t *closure_pool = sg->closure_pool;
|
||||
/* Align pointer to closure struct requirement */
|
||||
closure_pool = reinterpret_cast<uint8_t *>(
|
||||
(reinterpret_cast<size_t>(closure_pool) + alignof(OSLClosureMul) - 1) &
|
||||
(-alignof(OSLClosureMul)));
|
||||
sg->closure_pool = closure_pool + sizeof(OSLClosureMul);
|
||||
|
||||
ccl_private OSLClosureMul *const closure = reinterpret_cast<ccl_private OSLClosureMul *>(
|
||||
closure_pool);
|
||||
closure->id = OSL_CLOSURE_MUL_ID;
|
||||
closure->weight = make_float3(weight, weight, weight);
|
||||
closure->closure = a;
|
||||
|
||||
return closure;
|
||||
}
|
||||
|
||||
ccl_device_extern ccl_private OSLClosure *osl_add_closure_closure(ccl_private ShaderGlobals *sg,
|
||||
ccl_private OSLClosure *a,
|
||||
ccl_private OSLClosure *b)
|
||||
{
|
||||
if (!a) {
|
||||
return b;
|
||||
}
|
||||
if (!b) {
|
||||
return a;
|
||||
}
|
||||
|
||||
ccl_private uint8_t *closure_pool = sg->closure_pool;
|
||||
/* Align pointer to closure struct requirement */
|
||||
closure_pool = reinterpret_cast<uint8_t *>(
|
||||
(reinterpret_cast<size_t>(closure_pool) + alignof(OSLClosureAdd) - 1) &
|
||||
(-alignof(OSLClosureAdd)));
|
||||
sg->closure_pool = closure_pool + sizeof(OSLClosureAdd);
|
||||
|
||||
ccl_private OSLClosureAdd *const closure = reinterpret_cast<ccl_private OSLClosureAdd *>(
|
||||
closure_pool);
|
||||
closure->id = OSL_CLOSURE_ADD_ID;
|
||||
closure->closureA = a;
|
||||
closure->closureB = b;
|
||||
|
||||
return closure;
|
||||
}
|
||||
|
||||
ccl_device_extern ccl_private OSLClosure *osl_allocate_closure_component(
|
||||
ccl_private ShaderGlobals *sg, const int id, const int size)
|
||||
{
|
||||
ccl_private uint8_t *closure_pool = sg->closure_pool;
|
||||
/* Align pointer to closure struct requirement */
|
||||
closure_pool = reinterpret_cast<uint8_t *>(
|
||||
(reinterpret_cast<size_t>(closure_pool) + alignof(OSLClosureComponent) - 1) &
|
||||
(-alignof(OSLClosureComponent)));
|
||||
sg->closure_pool = closure_pool + sizeof(OSLClosureComponent) + size;
|
||||
|
||||
ccl_private OSLClosureComponent *const closure =
|
||||
reinterpret_cast<ccl_private OSLClosureComponent *>(closure_pool);
|
||||
closure->id = static_cast<OSLClosureType>(id);
|
||||
closure->weight = one_float3();
|
||||
|
||||
return closure;
|
||||
}
|
||||
|
||||
ccl_device_extern ccl_private OSLClosure *osl_allocate_weighted_closure_component(
|
||||
ccl_private ShaderGlobals *sg, const int id, const int size, const ccl_private float3 *weight)
|
||||
{
|
||||
ccl_private uint8_t *closure_pool = sg->closure_pool;
|
||||
/* Align pointer to closure struct requirement */
|
||||
closure_pool = reinterpret_cast<uint8_t *>(
|
||||
(reinterpret_cast<size_t>(closure_pool) + alignof(OSLClosureComponent) - 1) &
|
||||
(-alignof(OSLClosureComponent)));
|
||||
sg->closure_pool = closure_pool + sizeof(OSLClosureComponent) + size;
|
||||
|
||||
ccl_private OSLClosureComponent *const closure =
|
||||
reinterpret_cast<ccl_private OSLClosureComponent *>(closure_pool);
|
||||
closure->id = static_cast<OSLClosureType>(id);
|
||||
closure->weight = *weight;
|
||||
|
||||
return closure;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* Utilities */
|
||||
|
||||
ccl_device_extern void osl_error(ccl_private ShaderGlobals * /*sg*/,
|
||||
DeviceString /*format*/,
|
||||
void * /*args*/)
|
||||
{
|
||||
}
|
||||
|
||||
ccl_device_extern void osl_printf(ccl_private ShaderGlobals * /*sg*/,
|
||||
DeviceString /*format*/,
|
||||
void * /*args*/)
|
||||
{
|
||||
}
|
||||
|
||||
ccl_device_extern void osl_warning(ccl_private ShaderGlobals * /*sg*/,
|
||||
DeviceString /*format*/,
|
||||
void * /*args*/)
|
||||
{
|
||||
}
|
||||
|
||||
ccl_device_extern void osl_fprintf(ccl_private ShaderGlobals * /*sg*/,
|
||||
DeviceString /*filename*/,
|
||||
DeviceString /*format*/,
|
||||
void * /*args*/)
|
||||
{
|
||||
}
|
||||
|
||||
ccl_device_extern uint osl_range_check_err(const int indexvalue,
|
||||
const int length,
|
||||
DeviceString /*symname*/,
|
||||
ccl_private ShaderGlobals * /*sg*/,
|
||||
DeviceString /*sourcefile*/,
|
||||
const int /*sourceline*/,
|
||||
DeviceString /*groupname*/,
|
||||
const int /*layer*/,
|
||||
DeviceString /*layername*/,
|
||||
DeviceString /*shadername*/)
|
||||
{
|
||||
const int result = indexvalue < 0 ? 0 : indexvalue >= length ? length - 1 : indexvalue;
|
||||
#if 0
|
||||
if (result != indexvalue) {
|
||||
printf("Index [%d] out of range\n", indexvalue);
|
||||
}
|
||||
#endif
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Matrix Utilities */
|
||||
|
||||
ccl_device_extern bool osl_get_matrix(ccl_private ShaderGlobals *sg,
|
||||
ccl_private float *res,
|
||||
DeviceString from)
|
||||
{
|
||||
KernelGlobals kg = nullptr;
|
||||
|
||||
if (from == DeviceStrings::u_common) {
|
||||
copy_matrix(res, projection_identity());
|
||||
return true;
|
||||
}
|
||||
if (from == DeviceStrings::u_shader || from == DeviceStrings::u_object) {
|
||||
return osl_shared_get_object_matrix(kg, sg->sd, res);
|
||||
}
|
||||
return osl_shared_get_named_matrix(kg, from, res);
|
||||
}
|
||||
|
||||
ccl_device_extern bool osl_get_inverse_matrix(ccl_private ShaderGlobals *sg,
|
||||
ccl_private float *res,
|
||||
DeviceString to)
|
||||
{
|
||||
KernelGlobals kg = nullptr;
|
||||
|
||||
if (to == DeviceStrings::u_common) {
|
||||
copy_matrix(res, projection_identity());
|
||||
return true;
|
||||
}
|
||||
if (to == DeviceStrings::u_shader || to == DeviceStrings::u_object) {
|
||||
return osl_shared_get_object_inverse_matrix(kg, sg->sd, res);
|
||||
}
|
||||
return osl_shared_get_named_inverse_matrix(kg, to, res);
|
||||
}
|
||||
|
||||
/* The ABI for these callbacks is different, so DeviceString and TypeDesc don't work here. */
|
||||
using RSTypeDesc = long long;
|
||||
|
||||
struct RSDeviceString {
|
||||
DeviceString val;
|
||||
};
|
||||
|
||||
/* Attributes */
|
||||
|
||||
ccl_device_extern bool osl_get_attribute(ccl_private ShaderGlobals *sg,
|
||||
const int derivatives,
|
||||
DeviceString object_name,
|
||||
DeviceString name,
|
||||
const int /*array_lookup*/,
|
||||
const int /*index*/,
|
||||
const RSTypeDesc type_abi,
|
||||
ccl_private void *res)
|
||||
{
|
||||
const TypeDesc type = *reinterpret_cast<const TypeDesc *>(&type_abi);
|
||||
KernelGlobals kg = nullptr;
|
||||
ccl_private ShaderData *const sd = sg->sd;
|
||||
|
||||
if (sd->shader == SHADER_NONE) {
|
||||
/* Camera shader. */
|
||||
return osl_shared_get_camera_attribute(kg, sg, name, type, derivatives, res);
|
||||
}
|
||||
|
||||
if (object_name != DeviceStrings::u_empty) {
|
||||
/* TODO: Get object index from name */
|
||||
return false;
|
||||
}
|
||||
|
||||
const int object = sd->object;
|
||||
|
||||
const AttributeDescriptor desc = find_attribute(kg, object, sd->prim, name);
|
||||
if (is_attribute_found(desc)) {
|
||||
return osl_shared_get_object_attribute(kg, sd, desc, type, derivatives, res);
|
||||
}
|
||||
return osl_shared_get_object_standard_attribute(kg, sg, sd, name, type, derivatives, res);
|
||||
}
|
||||
|
||||
/* Renderer services */
|
||||
|
||||
ccl_device_extern bool rend_get_userdata(RSDeviceString name,
|
||||
ccl_private void *data,
|
||||
int data_size,
|
||||
const TypeDesc &type,
|
||||
int /*index*/)
|
||||
{
|
||||
if (type.basetype == TypeDesc::PTR) {
|
||||
kernel_assert(data_size == sizeof(void *));
|
||||
(void)data_size;
|
||||
|
||||
ccl_private void **ptr_data = (ccl_private void **)data;
|
||||
|
||||
if (name.val == DeviceStrings::u_colorsystem) {
|
||||
#ifdef __KERNEL_OPTIX__
|
||||
*ptr_data = kernel_params.osl_colorsystem;
|
||||
return true;
|
||||
#else
|
||||
(void)ptr_data;
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
ccl_device_extern bool rs_texture(ccl_private ShaderGlobals *sg,
|
||||
RSDeviceString /*filename*/,
|
||||
ccl_private void *texture_handle,
|
||||
ccl_private void * /*texture_thread_info*/,
|
||||
ccl_private OSLTextureOptions *opt,
|
||||
const float s,
|
||||
const float t,
|
||||
const float dsdx,
|
||||
const float dtdx,
|
||||
const float dsdy,
|
||||
const float dtdy,
|
||||
const int nchannels,
|
||||
ccl_private float *result,
|
||||
ccl_private float * /*dresultds*/,
|
||||
ccl_private float * /*dresultdt*/,
|
||||
ccl_private void * /*errormessage*/)
|
||||
{
|
||||
return osl_shared_texture(
|
||||
nullptr, sg, texture_handle, opt, s, t, dsdx, dtdx, dsdy, dtdy, nchannels, result);
|
||||
}
|
||||
|
||||
ccl_device_extern bool rs_texture3d(ccl_private ShaderGlobals *sg,
|
||||
RSDeviceString /*filename*/,
|
||||
ccl_private void *texture_handle,
|
||||
ccl_private void * /*texture_thread_info*/,
|
||||
ccl_private OSLTextureOptions * /*opt*/,
|
||||
const ccl_private float3 *P,
|
||||
const ccl_private float3 *dPdx,
|
||||
const ccl_private float3 *dPdy,
|
||||
const ccl_private float3 *dPdz,
|
||||
const int nchannels,
|
||||
ccl_private float *result,
|
||||
ccl_private float * /*dresultds*/,
|
||||
ccl_private float * /*dresultdt*/,
|
||||
ccl_private float * /*dresultdr*/,
|
||||
ccl_private void * /*errormessage*/)
|
||||
{
|
||||
return osl_shared_texture3d(
|
||||
nullptr, sg, texture_handle, *P, *dPdx, *dPdy, *dPdz, nchannels, result);
|
||||
}
|
||||
|
||||
ccl_device_extern bool rs_environment(ccl_private ShaderGlobals *sg,
|
||||
RSDeviceString /*filename*/,
|
||||
ccl_private void *texture_handle,
|
||||
ccl_private void * /*texture_thread_info*/,
|
||||
ccl_private OSLTextureOptions * /*opt*/,
|
||||
const ccl_private float3 *R,
|
||||
const ccl_private float3 *dRdx,
|
||||
const ccl_private float3 *dRdy,
|
||||
const int nchannels,
|
||||
ccl_private float *result,
|
||||
ccl_private float * /*dresultds*/,
|
||||
ccl_private float * /*dresultdt*/,
|
||||
ccl_private void * /*errormessage*/)
|
||||
{
|
||||
return osl_shared_environment(nullptr, sg, texture_handle, *R, *dRdx, *dRdy, nchannels, result);
|
||||
}
|
||||
|
||||
ccl_device_extern bool rs_get_texture_info(ccl_private ShaderGlobals * /*sg*/,
|
||||
RSDeviceString /*filename*/,
|
||||
ccl_private void *texture_handle,
|
||||
ccl_private void * /*texture_thread_info*/,
|
||||
int /*subimage*/,
|
||||
RSDeviceString dataname,
|
||||
TypeDesc datatype,
|
||||
ccl_private void *data,
|
||||
ccl_private void * /*errormessage*/)
|
||||
{
|
||||
return osl_shared_get_texture_info(
|
||||
nullptr, texture_handle, zero_float2(), false, dataname.val, datatype, data);
|
||||
}
|
||||
|
||||
ccl_device_extern bool rs_get_texture_info_st(ccl_private ShaderGlobals * /*sg*/,
|
||||
RSDeviceString /*filename*/,
|
||||
ccl_private void *texture_handle,
|
||||
const float s,
|
||||
const float t,
|
||||
ccl_private void * /*texture_thread_info*/,
|
||||
int /*subimage*/,
|
||||
RSDeviceString dataname,
|
||||
TypeDesc datatype,
|
||||
ccl_private void *data,
|
||||
ccl_private void * /*errormessage*/)
|
||||
{
|
||||
return osl_shared_get_texture_info(
|
||||
nullptr, texture_handle, make_float2(s, t), true, dataname.val, datatype, data);
|
||||
}
|
||||
|
||||
ccl_device_extern int rs_pointcloud_search(ccl_private ShaderGlobals * /*sg*/,
|
||||
RSDeviceString /*filename*/,
|
||||
const ccl_private float3 * /*center*/,
|
||||
float /*radius*/,
|
||||
int /*max_points*/,
|
||||
bool /*sort*/,
|
||||
ccl_private int * /*out_indices*/,
|
||||
ccl_private float * /*out_distances*/,
|
||||
int /*derivs_offset*/)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
ccl_device_extern int rs_pointcloud_get(ccl_private ShaderGlobals * /*sg*/,
|
||||
RSDeviceString /*filename*/,
|
||||
const ccl_private int * /*indices*/,
|
||||
int /*count*/,
|
||||
RSDeviceString /*attr_name*/,
|
||||
TypeDesc /*attr_type*/,
|
||||
ccl_private void * /*out_data*/)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
ccl_device_extern bool rs_pointcloud_write(ccl_private ShaderGlobals * /*sg*/,
|
||||
RSDeviceString /*filename*/,
|
||||
const ccl_private float3 * /*pos*/,
|
||||
int /*nattribs*/,
|
||||
const ccl_private DeviceString * /*names*/,
|
||||
const ccl_private TypeDesc * /*types*/,
|
||||
const ccl_private void ** /*data*/)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
ccl_device_extern bool rs_trace(ccl_private ShaderGlobals * /*sg*/,
|
||||
ccl_private void * /*options*/,
|
||||
const ccl_private float3 * /*P*/,
|
||||
const ccl_private float3 * /*dPdx*/,
|
||||
const ccl_private float3 * /*dPdy*/,
|
||||
const ccl_private float3 * /*R*/,
|
||||
const ccl_private float3 * /*dRdx*/,
|
||||
const ccl_private float3 * /*dRdy*/)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
ccl_device_extern bool rs_trace_get(ccl_private ShaderGlobals * /*sg*/,
|
||||
RSDeviceString /*name*/,
|
||||
TypeDesc /*type*/,
|
||||
ccl_private void * /*data*/,
|
||||
bool /*derivatives*/)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/* These osl_ functions are supposed to be implemented by OSL itself, but they are not yet.
|
||||
* See: https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/pull/1951
|
||||
* So we have to keep them around for now.
|
||||
*
|
||||
* The 1.14.4 based beta used for Blender 4.5 does not need them though, so we check the
|
||||
* version for that. */
|
||||
#if (OSL_LIBRARY_VERSION_CODE >= 11405) || (OSL_LIBRARY_VERSION_CODE < 11403)
|
||||
ccl_device_extern void osl_texture_set_firstchannel(ccl_private OSLTextureOptions * /*opt*/,
|
||||
const int /*firstchannel*/)
|
||||
{
|
||||
}
|
||||
|
||||
ccl_device_extern int osl_texture_decode_wrapmode(DeviceString /*name_*/)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
ccl_device_extern void osl_texture_set_swrap_code(ccl_private OSLTextureOptions * /*opt*/,
|
||||
const int /*mode*/)
|
||||
{
|
||||
}
|
||||
|
||||
ccl_device_extern void osl_texture_set_twrap_code(ccl_private OSLTextureOptions * /*opt*/,
|
||||
const int /*mode*/)
|
||||
{
|
||||
}
|
||||
|
||||
ccl_device_extern void osl_texture_set_rwrap_code(ccl_private OSLTextureOptions * /*opt*/,
|
||||
const int /*mode*/)
|
||||
{
|
||||
}
|
||||
|
||||
ccl_device_extern void osl_texture_set_stwrap_code(ccl_private OSLTextureOptions * /*opt*/,
|
||||
const int /*mode*/)
|
||||
{
|
||||
}
|
||||
|
||||
ccl_device_extern void osl_texture_set_sblur(ccl_private OSLTextureOptions * /*opt*/,
|
||||
const float /*blur*/)
|
||||
{
|
||||
}
|
||||
|
||||
ccl_device_extern void osl_texture_set_tblur(ccl_private OSLTextureOptions * /*opt*/,
|
||||
const float /*blur*/)
|
||||
{
|
||||
}
|
||||
|
||||
ccl_device_extern void osl_texture_set_rblur(ccl_private OSLTextureOptions * /*opt*/,
|
||||
const float /*blur*/)
|
||||
{
|
||||
}
|
||||
|
||||
ccl_device_extern void osl_texture_set_stblur(ccl_private OSLTextureOptions * /*opt*/,
|
||||
const float /*blur*/)
|
||||
{
|
||||
}
|
||||
|
||||
ccl_device_extern void osl_texture_set_swidth(ccl_private OSLTextureOptions * /*opt*/,
|
||||
const float /*width*/)
|
||||
{
|
||||
}
|
||||
|
||||
ccl_device_extern void osl_texture_set_twidth(ccl_private OSLTextureOptions * /*opt*/,
|
||||
const float /*width*/)
|
||||
{
|
||||
}
|
||||
|
||||
ccl_device_extern void osl_texture_set_rwidth(ccl_private OSLTextureOptions * /*opt*/,
|
||||
const float /*width*/)
|
||||
{
|
||||
}
|
||||
|
||||
ccl_device_extern void osl_texture_set_stwidth(ccl_private OSLTextureOptions * /*opt*/,
|
||||
const float /*width*/)
|
||||
{
|
||||
}
|
||||
|
||||
ccl_device_extern void osl_texture_set_fill(ccl_private OSLTextureOptions * /*opt*/,
|
||||
const float /*fill*/)
|
||||
{
|
||||
}
|
||||
|
||||
ccl_device_extern void osl_texture_set_time(ccl_private OSLTextureOptions * /*opt*/,
|
||||
const float /*time*/)
|
||||
{
|
||||
}
|
||||
|
||||
ccl_device_extern void osl_texture_set_interp_code(ccl_private OSLTextureOptions * /*opt*/,
|
||||
const int /*mode*/)
|
||||
{
|
||||
}
|
||||
|
||||
ccl_device_extern void osl_texture_set_subimage(ccl_private OSLTextureOptions * /*opt*/,
|
||||
const int /*subimage*/)
|
||||
{
|
||||
}
|
||||
|
||||
ccl_device_extern void osl_texture_set_subimagename(ccl_private OSLTextureOptions * /*opt*/,
|
||||
DeviceString /*subimagename_*/)
|
||||
{
|
||||
}
|
||||
|
||||
ccl_device_extern void osl_texture_set_missingcolor_arena(ccl_private OSLTextureOptions * /*opt*/,
|
||||
ccl_private float3 * /*color*/)
|
||||
{
|
||||
}
|
||||
|
||||
ccl_device_extern void osl_texture_set_missingcolor_alpha(ccl_private OSLTextureOptions * /*opt*/,
|
||||
const int /*nchannels*/,
|
||||
const float /*alpha*/)
|
||||
{
|
||||
}
|
||||
|
||||
ccl_device_extern void osl_init_trace_options(ccl_private void * /*oec*/,
|
||||
ccl_private void * /*opt*/)
|
||||
{
|
||||
}
|
||||
|
||||
ccl_device_extern void osl_trace_set_mindist(ccl_private void * /*opt*/, float /*x*/) {}
|
||||
|
||||
ccl_device_extern void osl_trace_set_maxdist(ccl_private void * /*opt*/, float /*x*/) {}
|
||||
|
||||
ccl_device_extern void osl_trace_set_shade(ccl_private void * /*opt*/, int /*x*/) {}
|
||||
|
||||
ccl_device_extern void osl_trace_set_traceset(ccl_private void * /*opt*/, const DeviceString /*x*/)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef __KERNEL_GPU__
|
||||
CCL_NAMESPACE_END
|
||||
#endif
|
||||
18
blender-5.2.0/intern/cycles/kernel/osl/services_optix.cu
Normal file
18
blender-5.2.0/intern/cycles/kernel/osl/services_optix.cu
Normal file
@@ -0,0 +1,18 @@
|
||||
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 */
|
||||
|
||||
#define WITH_OSL
|
||||
|
||||
// clang-format off
|
||||
#include "kernel/device/optix/compat.h"
|
||||
#include "kernel/device/optix/globals.h"
|
||||
|
||||
#include "kernel/device/gpu/image.h" /* Texture lookup uses normal CUDA intrinsics. */
|
||||
|
||||
#include "kernel/osl/services_gpu.h"
|
||||
// clang-format on
|
||||
|
||||
extern "C" __device__ void __direct_callable__dummy_services()
|
||||
{
|
||||
}
|
||||
1254
blender-5.2.0/intern/cycles/kernel/osl/services_shared.h
Normal file
1254
blender-5.2.0/intern/cycles/kernel/osl/services_shared.h
Normal file
File diff suppressed because it is too large
Load Diff
206
blender-5.2.0/intern/cycles/kernel/osl/shaders/CMakeLists.txt
Normal file
206
blender-5.2.0/intern/cycles/kernel/osl/shaders/CMakeLists.txt
Normal file
@@ -0,0 +1,206 @@
|
||||
# SPDX-FileCopyrightText: 2011-2022 Blender Foundation
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
# OSL node shaders
|
||||
|
||||
set(SRC_OSL
|
||||
node_add_closure.osl
|
||||
node_ambient_occlusion.osl
|
||||
node_attribute.osl
|
||||
node_background.osl
|
||||
node_bevel.osl
|
||||
node_brick_texture.osl
|
||||
node_brightness.osl
|
||||
node_bump.osl
|
||||
node_camera.osl
|
||||
node_checker_texture.osl
|
||||
node_clamp.osl
|
||||
node_combine_color.osl
|
||||
node_combine_xyz.osl
|
||||
node_convert_from_color.osl
|
||||
node_convert_from_float.osl
|
||||
node_convert_from_int.osl
|
||||
node_convert_from_normal.osl
|
||||
node_convert_from_point.osl
|
||||
node_convert_from_vector.osl
|
||||
node_diffuse_bsdf.osl
|
||||
node_displacement.osl
|
||||
node_vector_displacement.osl
|
||||
node_emission.osl
|
||||
node_environment_texture.osl
|
||||
node_float_curve.osl
|
||||
node_fresnel.osl
|
||||
node_gabor_texture.osl
|
||||
node_gamma.osl
|
||||
node_geometry.osl
|
||||
node_glass_bsdf.osl
|
||||
node_glossy_bsdf.osl
|
||||
node_gradient_texture.osl
|
||||
node_hair_info.osl
|
||||
node_point_info.osl
|
||||
node_scatter_volume.osl
|
||||
node_scene_time.osl
|
||||
node_absorption_volume.osl
|
||||
node_volume_coefficients.osl
|
||||
node_principled_volume.osl
|
||||
node_holdout.osl
|
||||
node_hsv.osl
|
||||
node_ies_light.osl
|
||||
node_image_texture.osl
|
||||
node_invert.osl
|
||||
node_layer_weight.osl
|
||||
node_light_falloff.osl
|
||||
node_light_path.osl
|
||||
node_magic_texture.osl
|
||||
node_map_range.osl
|
||||
node_mapping.osl
|
||||
node_math.osl
|
||||
node_metallic_bsdf.osl
|
||||
node_mix.osl
|
||||
node_mix_closure.osl
|
||||
node_mix_color.osl
|
||||
node_mix_float.osl
|
||||
node_mix_vector.osl
|
||||
node_mix_vector_non_uniform.osl
|
||||
node_noise_texture.osl
|
||||
node_normal.osl
|
||||
node_normal_map.osl
|
||||
node_object_info.osl
|
||||
node_output_displacement.osl
|
||||
node_output_surface.osl
|
||||
node_output_volume.osl
|
||||
node_particle_info.osl
|
||||
node_ray_portal_bsdf.osl
|
||||
node_raycast.osl
|
||||
node_raycast_attr_float.osl
|
||||
node_raycast_attr_vector.osl
|
||||
node_refraction_bsdf.osl
|
||||
node_rgb_curves.osl
|
||||
node_rgb_ramp.osl
|
||||
node_radial_tiling.osl
|
||||
node_separate_color.osl
|
||||
node_separate_xyz.osl
|
||||
node_set_normal.osl
|
||||
node_sheen_bsdf.osl
|
||||
node_sky_texture.osl
|
||||
node_subsurface_scattering.osl
|
||||
node_tangent.osl
|
||||
node_texture_coordinate.osl
|
||||
node_toon_bsdf.osl
|
||||
node_translucent_bsdf.osl
|
||||
node_transparent_bsdf.osl
|
||||
node_value.osl
|
||||
node_vector_curves.osl
|
||||
node_vector_math.osl
|
||||
node_vector_map_range.osl
|
||||
node_vector_rotate.osl
|
||||
node_vector_transform.osl
|
||||
node_vertex_color.osl
|
||||
node_voronoi_texture.osl
|
||||
node_wavelength.osl
|
||||
node_blackbody.osl
|
||||
node_wave_texture.osl
|
||||
node_white_noise_texture.osl
|
||||
node_wireframe.osl
|
||||
node_hair_bsdf.osl
|
||||
node_principled_hair_bsdf.osl
|
||||
node_uv_map.osl
|
||||
node_principled_bsdf.osl
|
||||
node_rgb_to_bw.osl
|
||||
)
|
||||
|
||||
get_filename_component(OSL_SHADER_HINT ${OSL_COMPILER} DIRECTORY)
|
||||
|
||||
set(_osl_SEARCH_DIRS
|
||||
${OSL_SHADER_HINT}
|
||||
${OSL_SHADER_HINT}/../
|
||||
/usr/share/OSL/
|
||||
/usr/include/OSL/
|
||||
)
|
||||
|
||||
if(DEFINED OSL_ROOT_DIR)
|
||||
list(APPEND _osl_SEARCH_DIRS ${OSL_ROOT_DIR})
|
||||
endif()
|
||||
|
||||
if(DEFINED OSL_HOME_DIR)
|
||||
list(APPEND _osl_SEARCH_DIRS ${OSL_HOME_DIR})
|
||||
endif()
|
||||
|
||||
find_path(OSL_SHADER_DIR
|
||||
NAMES
|
||||
stdosl.h
|
||||
HINTS
|
||||
${_osl_SEARCH_DIRS}
|
||||
PATH_SUFFIXES
|
||||
share/OSL/shaders
|
||||
share/openshadinglanguage/shaders
|
||||
shaders
|
||||
)
|
||||
mark_as_advanced(OSL_SHADER_DIR)
|
||||
unset(_osl_SEARCH_DIRS)
|
||||
|
||||
if(NOT EXISTS "${OSL_SHADER_DIR}")
|
||||
if(WITH_STRICT_BUILD_OPTIONS)
|
||||
message(SEND_ERROR "Precompiled OSL shader headers are not found, stopping")
|
||||
else()
|
||||
message(STATUS "Precompiled OSL shader headers are not found, continuing without")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# The headers that OSL ships differs per release so we can not
|
||||
# hard-code this.
|
||||
file(GLOB SRC_OSL_HEADER_DIST ${OSL_SHADER_DIR}/*.h)
|
||||
|
||||
set(SRC_OSL_HEADERS
|
||||
int_vector_types.h
|
||||
node_color.h
|
||||
node_color_blend.h
|
||||
node_fractal_voronoi.h
|
||||
node_fresnel.h
|
||||
node_hash.h
|
||||
node_math.h
|
||||
node_noise.h
|
||||
node_ramp_util.h
|
||||
node_radial_tiling_shared.h
|
||||
node_scatter.h
|
||||
node_voronoi.h
|
||||
stdcycles.h
|
||||
${SRC_OSL_HEADER_DIST}
|
||||
)
|
||||
|
||||
set(SRC_OSO
|
||||
|
||||
)
|
||||
|
||||
# TODO, add a module to compile OSL
|
||||
foreach(_file ${SRC_OSL})
|
||||
set(_OSL_FILE ${CMAKE_CURRENT_SOURCE_DIR}/${_file})
|
||||
set_source_files_properties(${_file} PROPERTIES HEADER_FILE_ONLY TRUE)
|
||||
string(REPLACE ".osl" ".oso" _OSO_FILE ${_OSL_FILE})
|
||||
string(REPLACE ${CMAKE_SOURCE_DIR} ${CMAKE_BINARY_DIR} _OSO_FILE ${_OSO_FILE})
|
||||
add_custom_command(
|
||||
OUTPUT ${_OSO_FILE}
|
||||
COMMAND
|
||||
${CMAKE_COMMAND} -E env ${PLATFORM_ENV_BUILD}
|
||||
${OSL_COMPILER} -q -O2
|
||||
-I"${CMAKE_CURRENT_SOURCE_DIR}"
|
||||
-I"${OSL_SHADER_DIR}"
|
||||
-o ${_OSO_FILE}
|
||||
${_OSL_FILE}
|
||||
DEPENDS ${_OSL_FILE} ${SRC_OSL_HEADERS} ${OSL_COMPILER}
|
||||
)
|
||||
list(APPEND SRC_OSO
|
||||
${_OSO_FILE}
|
||||
)
|
||||
|
||||
unset(_OSL_FILE)
|
||||
unset(_OSO_FILE)
|
||||
endforeach()
|
||||
|
||||
add_custom_target(cycles_osl_shaders ALL DEPENDS ${SRC_OSO} ${SRC_OSL_HEADERS} ${OSL_COMPILER} SOURCES ${SRC_OSL})
|
||||
cycles_set_solution_folder(cycles_osl_shaders)
|
||||
|
||||
# CMAKE_CURRENT_SOURCE_DIR is already included in OSO paths
|
||||
delayed_install("" "${SRC_OSO}" ${CYCLES_INSTALL_PATH}/shader)
|
||||
delayed_install("${CMAKE_CURRENT_SOURCE_DIR}" "${SRC_OSL_HEADERS}" ${CYCLES_INSTALL_PATH}/shader)
|
||||
@@ -0,0 +1,159 @@
|
||||
/* SPDX-FileCopyrightText: 2025 Blender Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 */
|
||||
|
||||
#include "vector2.h"
|
||||
#include "vector4.h"
|
||||
|
||||
struct int2 {
|
||||
int x;
|
||||
int y;
|
||||
};
|
||||
|
||||
int2 __operator__add__(int2 a, int2 b)
|
||||
{
|
||||
return int2(a.x + b.x, a.y + b.y);
|
||||
}
|
||||
|
||||
int2 __operator__add__(int2 a, int b)
|
||||
{
|
||||
return int2(a.x + b, a.y + b);
|
||||
}
|
||||
|
||||
int2 __operator__mul__(int2 a, int2 b)
|
||||
{
|
||||
return int2(a.x * b.x, a.y * b.y);
|
||||
}
|
||||
|
||||
int2 __operator__mul__(int2 a, int b)
|
||||
{
|
||||
return int2(a.x * b, a.y * b);
|
||||
}
|
||||
|
||||
int2 __operator__shr__(int2 a, int b)
|
||||
{
|
||||
return int2(a.x >> b, a.y >> b);
|
||||
}
|
||||
|
||||
int2 __operator__xor__(int2 a, int2 b)
|
||||
{
|
||||
return int2(a.x ^ b.x, a.y ^ b.y);
|
||||
}
|
||||
|
||||
int2 __operator__bitand__(int2 a, int b)
|
||||
{
|
||||
return int2(a.x & b, a.y & b);
|
||||
}
|
||||
|
||||
int2 vec2_to_int2(vector2 k)
|
||||
{
|
||||
return int2((int)k.x, (int)k.y);
|
||||
}
|
||||
|
||||
vector2 int2_to_vec2(int2 k)
|
||||
{
|
||||
return vector2((float)k.x, (float)k.y);
|
||||
}
|
||||
|
||||
struct int3 {
|
||||
int x;
|
||||
int y;
|
||||
int z;
|
||||
};
|
||||
|
||||
int3 __operator__add__(int3 a, int3 b)
|
||||
{
|
||||
return int3(a.x + b.x, a.y + b.y, a.z + b.z);
|
||||
}
|
||||
|
||||
int3 __operator__add__(int3 a, int b)
|
||||
{
|
||||
return int3(a.x + b, a.y + b, a.z + b);
|
||||
}
|
||||
|
||||
int3 __operator__mul__(int3 a, int3 b)
|
||||
{
|
||||
return int3(a.x * b.x, a.y * b.y, a.z * b.z);
|
||||
}
|
||||
|
||||
int3 __operator__mul__(int3 a, int b)
|
||||
{
|
||||
return int3(a.x * b, a.y * b, a.z * b);
|
||||
}
|
||||
|
||||
int3 __operator__shr__(int3 a, int b)
|
||||
{
|
||||
return int3(a.x >> b, a.y >> b, a.z >> b);
|
||||
}
|
||||
|
||||
int3 __operator__xor__(int3 a, int3 b)
|
||||
{
|
||||
return int3(a.x ^ b.x, a.y ^ b.y, a.z ^ b.z);
|
||||
}
|
||||
|
||||
int3 __operator__bitand__(int3 a, int b)
|
||||
{
|
||||
return int3(a.x & b, a.y & b, a.z & b);
|
||||
}
|
||||
|
||||
int3 vec3_to_int3(point k)
|
||||
{
|
||||
return int3((int)k.x, (int)k.y, (int)k.z);
|
||||
}
|
||||
|
||||
point int3_to_vec3(int3 k)
|
||||
{
|
||||
return point((float)k.x, (float)k.y, (float)k.z);
|
||||
}
|
||||
|
||||
struct int4 {
|
||||
int x;
|
||||
int y;
|
||||
int z;
|
||||
int w;
|
||||
};
|
||||
|
||||
int4 __operator__add__(int4 a, int4 b)
|
||||
{
|
||||
return int4(a.x + b.x, a.y + b.y, a.z + b.z, a.w + b.w);
|
||||
}
|
||||
|
||||
int4 __operator__add__(int4 a, int b)
|
||||
{
|
||||
return int4(a.x + b, a.y + b, a.z + b, a.w + b);
|
||||
}
|
||||
|
||||
int4 __operator__mul__(int4 a, int4 b)
|
||||
{
|
||||
return int4(a.x * b.x, a.y * b.y, a.z * b.z, a.w * b.w);
|
||||
}
|
||||
|
||||
int4 __operator__mul__(int4 a, int b)
|
||||
{
|
||||
return int4(a.x * b, a.y * b, a.z * b, a.w * b);
|
||||
}
|
||||
|
||||
int4 __operator__shr__(int4 a, int b)
|
||||
{
|
||||
return int4(a.x >> b, a.y >> b, a.z >> b, a.w >> b);
|
||||
}
|
||||
|
||||
int4 __operator__xor__(int4 a, int4 b)
|
||||
{
|
||||
return int4(a.x ^ b.x, a.y ^ b.y, a.z ^ b.z, a.w ^ b.w);
|
||||
}
|
||||
|
||||
int4 __operator__bitand__(int4 a, int b)
|
||||
{
|
||||
return int4(a.x & b, a.y & b, a.z & b, a.w & b);
|
||||
}
|
||||
|
||||
int4 vec4_to_int4(vector4 k)
|
||||
{
|
||||
return int4((int)k.x, (int)k.y, (int)k.z, (int)k.w);
|
||||
}
|
||||
|
||||
vector4 int4_to_vec4(int4 k)
|
||||
{
|
||||
return vector4((float)k.x, (float)k.y, (float)k.z, (float)k.w);
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 */
|
||||
|
||||
#include "stdcycles.h"
|
||||
|
||||
shader node_absorption_volume(color Color = color(0.8, 0.8, 0.8),
|
||||
float Density = 1.0,
|
||||
output closure color Volume = 0)
|
||||
{
|
||||
Volume = ((color(1.0, 1.0, 1.0) - Color) * max(Density, 0.0)) * absorption();
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 */
|
||||
|
||||
#include "stdcycles.h"
|
||||
|
||||
shader node_add_closure(closure color Closure1 = 0,
|
||||
closure color Closure2 = 0,
|
||||
output closure color Closure = 0)
|
||||
{
|
||||
Closure = Closure1 + Closure2;
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 */
|
||||
|
||||
#include "stdcycles.h"
|
||||
|
||||
shader node_ambient_occlusion(color ColorIn = color(1.0, 1.0, 1.0),
|
||||
int samples = 16,
|
||||
float Distance = 1.0,
|
||||
normal Normal = N,
|
||||
int inside = 0,
|
||||
int only_local = 0,
|
||||
output color ColorOut = color(1.0, 1.0, 1.0),
|
||||
output float AO = 1.0)
|
||||
{
|
||||
int global_radius = (Distance == 0.0 && !isconnected(Distance));
|
||||
|
||||
normal normalized_normal = normalize(Normal);
|
||||
|
||||
/* Abuse texture call with special @ao token. */
|
||||
AO = texture("@ao",
|
||||
samples,
|
||||
Distance,
|
||||
normalized_normal[0],
|
||||
normalized_normal[1],
|
||||
normalized_normal[2],
|
||||
inside,
|
||||
"sblur",
|
||||
only_local,
|
||||
"tblur",
|
||||
global_radius);
|
||||
ColorOut = ColorIn * AO;
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 */
|
||||
|
||||
#include "node_math.h"
|
||||
#include "stdcycles.h"
|
||||
|
||||
shader node_attribute(string bump_offset = "center",
|
||||
float bump_filter_width = BUMP_FILTER_WIDTH,
|
||||
string name = "",
|
||||
output point Vector = point(0.0, 0.0, 0.0),
|
||||
output color Color = 0.0,
|
||||
output float Fac = 0.0,
|
||||
output float Alpha = 0.0)
|
||||
{
|
||||
float data[4] = {0.0, 0.0, 0.0, 0.0};
|
||||
int success = getattribute(name, data);
|
||||
if (!success && (name == "geom:generated")) {
|
||||
/* No generated attribute, fall back to object coordinates. */
|
||||
Color = transform("object", P);
|
||||
data[3] = 1.0;
|
||||
}
|
||||
else {
|
||||
Color = color(data[0], data[1], data[2]);
|
||||
}
|
||||
|
||||
Vector = point(Color);
|
||||
Fac = average(Color);
|
||||
Alpha = data[3];
|
||||
|
||||
if (bump_offset == "dx") {
|
||||
Color += Dx(Color) * bump_filter_width;
|
||||
Vector += Dx(Vector) * bump_filter_width;
|
||||
Fac += Dx(Fac) * bump_filter_width;
|
||||
Alpha += Dx(Alpha) * bump_filter_width;
|
||||
}
|
||||
else if (bump_offset == "dy") {
|
||||
Color += Dy(Color) * bump_filter_width;
|
||||
Vector += Dy(Vector) * bump_filter_width;
|
||||
Fac += Dy(Fac) * bump_filter_width;
|
||||
Alpha += Dy(Alpha) * bump_filter_width;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 */
|
||||
|
||||
#include "stdcycles.h"
|
||||
|
||||
shader node_background(color Color = 0.8,
|
||||
float Strength = 1.0,
|
||||
output closure color Background = 0)
|
||||
{
|
||||
Background = Color * Strength * background();
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 */
|
||||
|
||||
#include "stdcycles.h"
|
||||
|
||||
shader node_bevel(int samples = 4,
|
||||
float Radius = 0.05,
|
||||
normal NormalIn = N,
|
||||
output normal NormalOut = N)
|
||||
{
|
||||
/* Abuse texture call with special @bevel token. */
|
||||
vector bevel_N = (normal)(color)texture("@bevel", samples, Radius);
|
||||
|
||||
/* Preserve input normal. */
|
||||
NormalOut = normalize(NormalIn + (bevel_N - N));
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 */
|
||||
|
||||
#include "stdcycles.h"
|
||||
|
||||
shader node_blackbody(float Temperature = 1200.0, output color Color = 0.0)
|
||||
{
|
||||
color rgb = blackbody(Temperature);
|
||||
|
||||
/* Scale by luminance */
|
||||
float l = luminance(rgb);
|
||||
if (l != 0.0)
|
||||
rgb /= l;
|
||||
Color = rgb;
|
||||
}
|
||||
@@ -0,0 +1,107 @@
|
||||
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 */
|
||||
|
||||
#include "stdcycles.h"
|
||||
|
||||
/* Brick */
|
||||
|
||||
float brick_noise(int ns) /* fast integer noise */
|
||||
{
|
||||
int nn;
|
||||
int n = (ns + 1013) & 2147483647;
|
||||
n = (n >> 13) ^ n;
|
||||
nn = (n * (n * n * 60493 + 19990303) + 1376312589) & 2147483647;
|
||||
return 0.5 * ((float)nn / 1073741824.0);
|
||||
}
|
||||
|
||||
float brick(point p,
|
||||
float mortar_size,
|
||||
float mortar_smooth,
|
||||
float bias,
|
||||
float BrickWidth,
|
||||
float row_height,
|
||||
float offset_amount,
|
||||
int offset_frequency,
|
||||
float squash_amount,
|
||||
int squash_frequency,
|
||||
output float tint)
|
||||
{
|
||||
int bricknum, rownum;
|
||||
float offset = 0.0;
|
||||
float brick_width = BrickWidth;
|
||||
float x, y;
|
||||
|
||||
rownum = (int)floor(p[1] / row_height);
|
||||
|
||||
if (offset_frequency && squash_frequency) {
|
||||
brick_width *= (rownum % squash_frequency) ? 1.0 : squash_amount; /* squash */
|
||||
offset = (rownum % offset_frequency) ? 0.0 : (brick_width * offset_amount); /* offset */
|
||||
}
|
||||
|
||||
bricknum = (int)floor((p[0] + offset) / brick_width);
|
||||
|
||||
x = (p[0] + offset) - brick_width * bricknum;
|
||||
y = p[1] - row_height * rownum;
|
||||
|
||||
tint = clamp((brick_noise((rownum << 16) + (bricknum & 65535)) + bias), 0.0, 1.0);
|
||||
|
||||
float min_dist = min(min(x, y), min(brick_width - x, row_height - y));
|
||||
if (min_dist >= mortar_size) {
|
||||
return 0.0;
|
||||
}
|
||||
else if (mortar_smooth == 0.0) {
|
||||
return 1.0;
|
||||
}
|
||||
else {
|
||||
min_dist = 1.0 - min_dist / mortar_size;
|
||||
return smoothstep(0.0, mortar_smooth, min_dist);
|
||||
}
|
||||
}
|
||||
|
||||
shader node_brick_texture(int use_mapping = 0,
|
||||
matrix mapping = matrix(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
|
||||
float offset = 0.5,
|
||||
int offset_frequency = 2,
|
||||
float squash = 1.0,
|
||||
int squash_frequency = 1,
|
||||
point Vector = P,
|
||||
color Color1 = 0.2,
|
||||
color Color2 = 0.8,
|
||||
color Mortar = 0.0,
|
||||
float Scale = 5.0,
|
||||
float MortarSize = 0.02,
|
||||
float MortarSmooth = 0.0,
|
||||
float Bias = 0.0,
|
||||
float BrickWidth = 0.5,
|
||||
float RowHeight = 0.25,
|
||||
output float Fac = 0.0,
|
||||
output color Color = 0.2)
|
||||
{
|
||||
point p = Vector;
|
||||
|
||||
if (use_mapping)
|
||||
p = transform(mapping, p);
|
||||
|
||||
float tint = 0.0;
|
||||
color Col = Color1;
|
||||
|
||||
Fac = brick(p * Scale,
|
||||
MortarSize,
|
||||
MortarSmooth,
|
||||
Bias,
|
||||
BrickWidth,
|
||||
RowHeight,
|
||||
offset,
|
||||
offset_frequency,
|
||||
squash,
|
||||
squash_frequency,
|
||||
tint);
|
||||
|
||||
if (Fac != 1.0) {
|
||||
float facm = 1.0 - tint;
|
||||
Col = facm * Color1 + tint * Color2;
|
||||
}
|
||||
|
||||
Color = mix(Col, Mortar, Fac);
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 */
|
||||
|
||||
#include "stdcycles.h"
|
||||
|
||||
shader node_brightness(color ColorIn = 0.8,
|
||||
float Bright = 0.0,
|
||||
float Contrast = 0.0,
|
||||
output color ColorOut = 0.8)
|
||||
{
|
||||
float a = 1.0 + Contrast;
|
||||
float b = Bright - Contrast * 0.5;
|
||||
|
||||
ColorOut[0] = max(a * ColorIn[0] + b, 0.0);
|
||||
ColorOut[1] = max(a * ColorIn[1] + b, 0.0);
|
||||
ColorOut[2] = max(a * ColorIn[2] + b, 0.0);
|
||||
}
|
||||
55
blender-5.2.0/intern/cycles/kernel/osl/shaders/node_bump.osl
Normal file
55
blender-5.2.0/intern/cycles/kernel/osl/shaders/node_bump.osl
Normal file
@@ -0,0 +1,55 @@
|
||||
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 */
|
||||
|
||||
#include "stdcycles.h"
|
||||
|
||||
/* "Bump Mapping Unparameterized Surfaces on the GPU"
|
||||
* Morten S. Mikkelsen, 2010 */
|
||||
|
||||
surface node_bump(int invert = 0,
|
||||
int use_object_space = 0,
|
||||
normal NormalIn = N,
|
||||
float Strength = 0.1,
|
||||
float Distance = 1.0,
|
||||
float FilterWidth = BUMP_FILTER_WIDTH,
|
||||
float SampleCenter = 0.0,
|
||||
float SampleX = 0.0,
|
||||
float SampleY = 0.0,
|
||||
output normal NormalOut = N)
|
||||
{
|
||||
point Ptmp = P;
|
||||
normal Normal = NormalIn;
|
||||
|
||||
if (use_object_space) {
|
||||
Ptmp = transform("object", Ptmp);
|
||||
Normal = normalize(transform("object", Normal));
|
||||
}
|
||||
|
||||
/* get surface tangents from normal */
|
||||
vector dPdx = Dx(Ptmp);
|
||||
vector dPdy = Dy(Ptmp);
|
||||
|
||||
vector Rx = cross(dPdy, Normal);
|
||||
vector Ry = cross(Normal, dPdx);
|
||||
|
||||
/* compute surface gradient and determinant */
|
||||
float det = dot(dPdx, Rx);
|
||||
vector surfgrad = (SampleX - SampleCenter) * Rx + (SampleY - SampleCenter) * Ry;
|
||||
|
||||
float absdet = fabs(det);
|
||||
|
||||
float strength = max(Strength, 0.0);
|
||||
float dist = Distance;
|
||||
|
||||
if (invert)
|
||||
dist *= -1.0;
|
||||
|
||||
/* compute and output perturbed normal */
|
||||
NormalOut = normalize(FilterWidth * absdet * Normal - dist * sign(det) * surfgrad);
|
||||
NormalOut = normalize(strength * NormalOut + (1.0 - strength) * Normal);
|
||||
|
||||
if (use_object_space) {
|
||||
NormalOut = normalize(transform("object", "world", NormalOut));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 */
|
||||
|
||||
#include "stdcycles.h"
|
||||
|
||||
shader node_camera(output vector ViewVector = vector(0.0, 0.0, 0.0),
|
||||
output float ViewZDepth = 0.0,
|
||||
output float ViewDistance = 0.0)
|
||||
{
|
||||
ViewVector = (vector)transform("world", "camera", P);
|
||||
|
||||
ViewZDepth = ViewVector[2];
|
||||
ViewDistance = length(ViewVector);
|
||||
|
||||
ViewVector = normalize(ViewVector);
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 */
|
||||
|
||||
#include "stdcycles.h"
|
||||
|
||||
/* Checker */
|
||||
|
||||
float checker(point ip)
|
||||
{
|
||||
point p;
|
||||
p[0] = (ip[0] + 0.000001) * 0.999999;
|
||||
p[1] = (ip[1] + 0.000001) * 0.999999;
|
||||
p[2] = (ip[2] + 0.000001) * 0.999999;
|
||||
|
||||
int xi = (int)fabs(floor(p[0]));
|
||||
int yi = (int)fabs(floor(p[1]));
|
||||
int zi = (int)fabs(floor(p[2]));
|
||||
|
||||
if ((xi % 2 == yi % 2) == (zi % 2)) {
|
||||
return 1.0;
|
||||
}
|
||||
else {
|
||||
return 0.0;
|
||||
}
|
||||
}
|
||||
|
||||
shader node_checker_texture(
|
||||
int use_mapping = 0,
|
||||
matrix mapping = matrix(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
|
||||
float Scale = 5.0,
|
||||
point Vector = P,
|
||||
color Color1 = 0.8,
|
||||
color Color2 = 0.2,
|
||||
output float Fac = 0.0,
|
||||
output color Color = 0.0)
|
||||
{
|
||||
point p = Vector;
|
||||
|
||||
if (use_mapping)
|
||||
p = transform(mapping, p);
|
||||
|
||||
Fac = checker(p * Scale);
|
||||
if (Fac == 1.0) {
|
||||
Color = Color1;
|
||||
}
|
||||
else {
|
||||
Color = Color2;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 */
|
||||
|
||||
#include "stdcycles.h"
|
||||
|
||||
shader node_clamp(string clamp_type = "minmax",
|
||||
float Value = 1.0,
|
||||
float Min = 0.0,
|
||||
float Max = 1.0,
|
||||
output float Result = 0.0)
|
||||
{
|
||||
Result = (clamp_type == "range" && (Min > Max)) ? clamp(Value, Max, Min) :
|
||||
clamp(Value, Min, Max);
|
||||
}
|
||||
221
blender-5.2.0/intern/cycles/kernel/osl/shaders/node_color.h
Normal file
221
blender-5.2.0/intern/cycles/kernel/osl/shaders/node_color.h
Normal file
@@ -0,0 +1,221 @@
|
||||
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 */
|
||||
|
||||
/* TODO(lukas): Fix colors in OSL. */
|
||||
|
||||
float color_srgb_to_scene_linear(float c)
|
||||
{
|
||||
if (c < 0.04045) {
|
||||
return (c < 0.0) ? 0.0 : c * (1.0 / 12.92);
|
||||
}
|
||||
else {
|
||||
return pow((c + 0.055) * (1.0 / 1.055), 2.4);
|
||||
}
|
||||
}
|
||||
|
||||
float color_scene_linear_to_srgb(float c)
|
||||
{
|
||||
if (c < 0.0031308) {
|
||||
return (c < 0.0) ? 0.0 : c * 12.92;
|
||||
}
|
||||
else {
|
||||
return 1.055 * pow(c, 1.0 / 2.4) - 0.055;
|
||||
}
|
||||
}
|
||||
|
||||
color color_srgb_to_scene_linear(color c)
|
||||
{
|
||||
return color(color_srgb_to_scene_linear(c[0]),
|
||||
color_srgb_to_scene_linear(c[1]),
|
||||
color_srgb_to_scene_linear(c[2]));
|
||||
}
|
||||
|
||||
color color_scene_linear_to_srgb(color c)
|
||||
{
|
||||
return color(color_scene_linear_to_srgb(c[0]),
|
||||
color_scene_linear_to_srgb(c[1]),
|
||||
color_scene_linear_to_srgb(c[2]));
|
||||
}
|
||||
|
||||
color color_unpremultiply(color c, float alpha)
|
||||
{
|
||||
if (alpha != 1.0 && alpha != 0.0) {
|
||||
return c / alpha;
|
||||
}
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
/* Color Operations */
|
||||
|
||||
color xyY_to_xyz(float x, float y, float Y)
|
||||
{
|
||||
float X, Z;
|
||||
|
||||
if (y != 0.0) {
|
||||
X = (x / y) * Y;
|
||||
}
|
||||
else {
|
||||
X = 0.0;
|
||||
}
|
||||
|
||||
if (y != 0.0 && Y != 0.0) {
|
||||
Z = ((1.0 - x - y) / y) * Y;
|
||||
}
|
||||
else {
|
||||
Z = 0.0;
|
||||
}
|
||||
|
||||
return color(X, Y, Z);
|
||||
}
|
||||
|
||||
color xyz_to_rgb(float x, float y, float z)
|
||||
{
|
||||
return color(3.240479 * x + -1.537150 * y + -0.498535 * z,
|
||||
-0.969256 * x + 1.875991 * y + 0.041556 * z,
|
||||
0.055648 * x + -0.204043 * y + 1.057311 * z);
|
||||
}
|
||||
|
||||
color rgb_to_hsv(color rgb)
|
||||
{
|
||||
float cmax, cmin, h, s, v, cdelta;
|
||||
color c;
|
||||
|
||||
cmax = max(rgb[0], max(rgb[1], rgb[2]));
|
||||
cmin = min(rgb[0], min(rgb[1], rgb[2]));
|
||||
cdelta = cmax - cmin;
|
||||
|
||||
v = cmax;
|
||||
|
||||
if (cmax != 0.0) {
|
||||
s = cdelta / cmax;
|
||||
}
|
||||
else {
|
||||
s = 0.0;
|
||||
h = 0.0;
|
||||
}
|
||||
|
||||
if (s == 0.0) {
|
||||
h = 0.0;
|
||||
}
|
||||
else {
|
||||
c = (color(cmax, cmax, cmax) - rgb) / cdelta;
|
||||
|
||||
if (rgb[0] == cmax) {
|
||||
h = c[2] - c[1];
|
||||
}
|
||||
else if (rgb[1] == cmax) {
|
||||
h = 2.0 + c[0] - c[2];
|
||||
}
|
||||
else {
|
||||
h = 4.0 + c[1] - c[0];
|
||||
}
|
||||
|
||||
h /= 6.0;
|
||||
|
||||
if (h < 0.0) {
|
||||
h += 1.0;
|
||||
}
|
||||
}
|
||||
|
||||
return color(h, s, v);
|
||||
}
|
||||
|
||||
color hsv_to_rgb(color hsv)
|
||||
{
|
||||
float i, f, p, q, t, h, s, v;
|
||||
color rgb;
|
||||
|
||||
h = hsv[0];
|
||||
s = hsv[1];
|
||||
v = hsv[2];
|
||||
|
||||
if (s == 0.0) {
|
||||
rgb = color(v, v, v);
|
||||
}
|
||||
else {
|
||||
if (h == 1.0) {
|
||||
h = 0.0;
|
||||
}
|
||||
|
||||
h *= 6.0;
|
||||
i = floor(h);
|
||||
f = h - i;
|
||||
rgb = color(f, f, f);
|
||||
p = v * (1.0 - s);
|
||||
q = v * (1.0 - (s * f));
|
||||
t = v * (1.0 - (s * (1.0 - f)));
|
||||
|
||||
if (i == 0.0) {
|
||||
rgb = color(v, t, p);
|
||||
}
|
||||
else if (i == 1.0) {
|
||||
rgb = color(q, v, p);
|
||||
}
|
||||
else if (i == 2.0) {
|
||||
rgb = color(p, v, t);
|
||||
}
|
||||
else if (i == 3.0) {
|
||||
rgb = color(p, q, v);
|
||||
}
|
||||
else if (i == 4.0) {
|
||||
rgb = color(t, p, v);
|
||||
}
|
||||
else {
|
||||
rgb = color(v, p, q);
|
||||
}
|
||||
}
|
||||
|
||||
return rgb;
|
||||
}
|
||||
|
||||
color rgb_to_hsl(color rgb)
|
||||
{
|
||||
float cmax, cmin, h, s, l;
|
||||
|
||||
cmax = max(rgb[0], max(rgb[1], rgb[2]));
|
||||
cmin = min(rgb[0], min(rgb[1], rgb[2]));
|
||||
l = min(1.0, (cmax + cmin) / 2.0);
|
||||
|
||||
if (cmax == cmin) {
|
||||
h = s = 0.0; /* achromatic */
|
||||
}
|
||||
else {
|
||||
float cdelta = cmax - cmin;
|
||||
s = l > 0.5 ? cdelta / (2.0 - cmax - cmin) : cdelta / (cmax + cmin);
|
||||
if (cmax == rgb[0]) {
|
||||
h = (rgb[1] - rgb[2]) / cdelta + (rgb[1] < rgb[2] ? 6.0 : 0.0);
|
||||
}
|
||||
else if (cmax == rgb[1]) {
|
||||
h = (rgb[2] - rgb[0]) / cdelta + 2.0;
|
||||
}
|
||||
else {
|
||||
h = (rgb[0] - rgb[1]) / cdelta + 4.0;
|
||||
}
|
||||
}
|
||||
h /= 6.0;
|
||||
|
||||
return color(h, s, l);
|
||||
}
|
||||
|
||||
color hsl_to_rgb(color hsl)
|
||||
{
|
||||
float nr, ng, nb, chroma, h, s, l;
|
||||
|
||||
h = hsl[0];
|
||||
s = hsl[1];
|
||||
l = hsl[2];
|
||||
|
||||
nr = abs(h * 6.0 - 3.0) - 1.0;
|
||||
ng = 2.0 - abs(h * 6.0 - 2.0);
|
||||
nb = 2.0 - abs(h * 6.0 - 4.0);
|
||||
|
||||
nr = clamp(nr, 0.0, 1.0);
|
||||
nb = clamp(nb, 0.0, 1.0);
|
||||
ng = clamp(ng, 0.0, 1.0);
|
||||
|
||||
chroma = (1.0 - abs(2.0 * l - 1.0)) * s;
|
||||
|
||||
return color((nr - 0.5) * chroma + l, (ng - 0.5) * chroma + l, (nb - 0.5) * chroma + l);
|
||||
}
|
||||
@@ -0,0 +1,306 @@
|
||||
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 */
|
||||
|
||||
color node_mix_blend(float t, color col1, color col2)
|
||||
{
|
||||
return mix(col1, col2, t);
|
||||
}
|
||||
|
||||
color node_mix_add(float t, color col1, color col2)
|
||||
{
|
||||
return mix(col1, col1 + col2, t);
|
||||
}
|
||||
|
||||
color node_mix_mul(float t, color col1, color col2)
|
||||
{
|
||||
return mix(col1, col1 * col2, t);
|
||||
}
|
||||
|
||||
color node_mix_screen(float t, color col1, color col2)
|
||||
{
|
||||
float tm = 1.0 - t;
|
||||
|
||||
return color(1.0) - (color(tm) + t * (color(1.0) - col2)) * (color(1.0) - col1);
|
||||
}
|
||||
|
||||
color node_mix_overlay(float t, color col1, color col2)
|
||||
{
|
||||
float tm = 1.0 - t;
|
||||
|
||||
color outcol = col1;
|
||||
|
||||
if (outcol[0] < 0.5) {
|
||||
outcol[0] *= tm + 2.0 * t * col2[0];
|
||||
}
|
||||
else {
|
||||
outcol[0] = 1.0 - (tm + 2.0 * t * (1.0 - col2[0])) * (1.0 - outcol[0]);
|
||||
}
|
||||
|
||||
if (outcol[1] < 0.5) {
|
||||
outcol[1] *= tm + 2.0 * t * col2[1];
|
||||
}
|
||||
else {
|
||||
outcol[1] = 1.0 - (tm + 2.0 * t * (1.0 - col2[1])) * (1.0 - outcol[1]);
|
||||
}
|
||||
|
||||
if (outcol[2] < 0.5) {
|
||||
outcol[2] *= tm + 2.0 * t * col2[2];
|
||||
}
|
||||
else {
|
||||
outcol[2] = 1.0 - (tm + 2.0 * t * (1.0 - col2[2])) * (1.0 - outcol[2]);
|
||||
}
|
||||
|
||||
return outcol;
|
||||
}
|
||||
|
||||
color node_mix_sub(float t, color col1, color col2)
|
||||
{
|
||||
return mix(col1, col1 - col2, t);
|
||||
}
|
||||
|
||||
color node_mix_div(float t, color col1, color col2)
|
||||
{
|
||||
float tm = 1.0 - t;
|
||||
|
||||
color outcol = col1;
|
||||
|
||||
if (col2[0] != 0.0) {
|
||||
outcol[0] = tm * outcol[0] + t * outcol[0] / col2[0];
|
||||
}
|
||||
if (col2[1] != 0.0) {
|
||||
outcol[1] = tm * outcol[1] + t * outcol[1] / col2[1];
|
||||
}
|
||||
if (col2[2] != 0.0) {
|
||||
outcol[2] = tm * outcol[2] + t * outcol[2] / col2[2];
|
||||
}
|
||||
|
||||
return outcol;
|
||||
}
|
||||
|
||||
color node_mix_diff(float t, color col1, color col2)
|
||||
{
|
||||
return mix(col1, abs(col1 - col2), t);
|
||||
}
|
||||
|
||||
color node_mix_exclusion(float t, color col1, color col2)
|
||||
{
|
||||
return max(mix(col1, col1 + col2 - 2.0 * col1 * col2, t), 0.0);
|
||||
}
|
||||
|
||||
color node_mix_dark(float t, color col1, color col2)
|
||||
{
|
||||
return mix(col1, min(col1, col2), t);
|
||||
}
|
||||
|
||||
color node_mix_light(float t, color col1, color col2)
|
||||
{
|
||||
return mix(col1, max(col1, col2), t);
|
||||
}
|
||||
|
||||
color node_mix_dodge(float t, color col1, color col2)
|
||||
{
|
||||
color outcol = col1;
|
||||
|
||||
if (outcol[0] != 0.0) {
|
||||
float tmp = 1.0 - t * col2[0];
|
||||
if (tmp <= 0.0) {
|
||||
outcol[0] = 1.0;
|
||||
}
|
||||
else if ((tmp = outcol[0] / tmp) > 1.0) {
|
||||
outcol[0] = 1.0;
|
||||
}
|
||||
else {
|
||||
outcol[0] = tmp;
|
||||
}
|
||||
}
|
||||
if (outcol[1] != 0.0) {
|
||||
float tmp = 1.0 - t * col2[1];
|
||||
if (tmp <= 0.0) {
|
||||
outcol[1] = 1.0;
|
||||
}
|
||||
else if ((tmp = outcol[1] / tmp) > 1.0) {
|
||||
outcol[1] = 1.0;
|
||||
}
|
||||
else {
|
||||
outcol[1] = tmp;
|
||||
}
|
||||
}
|
||||
if (outcol[2] != 0.0) {
|
||||
float tmp = 1.0 - t * col2[2];
|
||||
if (tmp <= 0.0) {
|
||||
outcol[2] = 1.0;
|
||||
}
|
||||
else if ((tmp = outcol[2] / tmp) > 1.0) {
|
||||
outcol[2] = 1.0;
|
||||
}
|
||||
else {
|
||||
outcol[2] = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
return outcol;
|
||||
}
|
||||
|
||||
color node_mix_burn(float t, color col1, color col2)
|
||||
{
|
||||
float tmp, tm = 1.0 - t;
|
||||
|
||||
color outcol = col1;
|
||||
|
||||
tmp = tm + t * col2[0];
|
||||
if (tmp <= 0.0) {
|
||||
outcol[0] = 0.0;
|
||||
}
|
||||
else if ((tmp = (1.0 - (1.0 - outcol[0]) / tmp)) < 0.0) {
|
||||
outcol[0] = 0.0;
|
||||
}
|
||||
else if (tmp > 1.0) {
|
||||
outcol[0] = 1.0;
|
||||
}
|
||||
else {
|
||||
outcol[0] = tmp;
|
||||
}
|
||||
|
||||
tmp = tm + t * col2[1];
|
||||
if (tmp <= 0.0) {
|
||||
outcol[1] = 0.0;
|
||||
}
|
||||
else if ((tmp = (1.0 - (1.0 - outcol[1]) / tmp)) < 0.0) {
|
||||
outcol[1] = 0.0;
|
||||
}
|
||||
else if (tmp > 1.0) {
|
||||
outcol[1] = 1.0;
|
||||
}
|
||||
else {
|
||||
outcol[1] = tmp;
|
||||
}
|
||||
|
||||
tmp = tm + t * col2[2];
|
||||
if (tmp <= 0.0) {
|
||||
outcol[2] = 0.0;
|
||||
}
|
||||
else if ((tmp = (1.0 - (1.0 - outcol[2]) / tmp)) < 0.0) {
|
||||
outcol[2] = 0.0;
|
||||
}
|
||||
else if (tmp > 1.0) {
|
||||
outcol[2] = 1.0;
|
||||
}
|
||||
else {
|
||||
outcol[2] = tmp;
|
||||
}
|
||||
|
||||
return outcol;
|
||||
}
|
||||
|
||||
color node_mix_hue(float t, color col1, color col2)
|
||||
{
|
||||
color outcol = col1;
|
||||
color hsv2 = rgb_to_hsv(col2);
|
||||
|
||||
if (hsv2[1] != 0.0) {
|
||||
color hsv = rgb_to_hsv(outcol);
|
||||
hsv[0] = hsv2[0];
|
||||
color tmp = hsv_to_rgb(hsv);
|
||||
|
||||
outcol = mix(outcol, tmp, t);
|
||||
}
|
||||
|
||||
return outcol;
|
||||
}
|
||||
|
||||
color node_mix_sat(float t, color col1, color col2)
|
||||
{
|
||||
float tm = 1.0 - t;
|
||||
|
||||
color outcol = col1;
|
||||
|
||||
color hsv = rgb_to_hsv(outcol);
|
||||
|
||||
if (hsv[1] != 0.0) {
|
||||
color hsv2 = rgb_to_hsv(col2);
|
||||
|
||||
hsv[1] = tm * hsv[1] + t * hsv2[1];
|
||||
outcol = hsv_to_rgb(hsv);
|
||||
}
|
||||
|
||||
return outcol;
|
||||
}
|
||||
|
||||
color node_mix_val(float t, color col1, color col2)
|
||||
{
|
||||
float tm = 1.0 - t;
|
||||
|
||||
color hsv = rgb_to_hsv(col1);
|
||||
color hsv2 = rgb_to_hsv(col2);
|
||||
|
||||
hsv[2] = tm * hsv[2] + t * hsv2[2];
|
||||
|
||||
return hsv_to_rgb(hsv);
|
||||
}
|
||||
|
||||
color node_mix_color(float t, color col1, color col2)
|
||||
{
|
||||
color outcol = col1;
|
||||
color hsv2 = rgb_to_hsv(col2);
|
||||
|
||||
if (hsv2[1] != 0.0) {
|
||||
color hsv = rgb_to_hsv(outcol);
|
||||
hsv[0] = hsv2[0];
|
||||
hsv[1] = hsv2[1];
|
||||
color tmp = hsv_to_rgb(hsv);
|
||||
|
||||
outcol = mix(outcol, tmp, t);
|
||||
}
|
||||
|
||||
return outcol;
|
||||
}
|
||||
|
||||
color node_mix_soft(float t, color col1, color col2)
|
||||
{
|
||||
float tm = 1.0 - t;
|
||||
|
||||
color one = color(1.0);
|
||||
color scr = one - (one - col2) * (one - col1);
|
||||
|
||||
return tm * col1 + t * ((one - col1) * col2 * col1 + col1 * scr);
|
||||
}
|
||||
|
||||
color node_mix_linear(float t, color col1, color col2)
|
||||
{
|
||||
color outcol = col1;
|
||||
|
||||
if (col2[0] > 0.5) {
|
||||
outcol[0] = col1[0] + t * (2.0 * (col2[0] - 0.5));
|
||||
}
|
||||
else {
|
||||
outcol[0] = col1[0] + t * (2.0 * (col2[0]) - 1.0);
|
||||
}
|
||||
|
||||
if (col2[1] > 0.5) {
|
||||
outcol[1] = col1[1] + t * (2.0 * (col2[1] - 0.5));
|
||||
}
|
||||
else {
|
||||
outcol[1] = col1[1] + t * (2.0 * (col2[1]) - 1.0);
|
||||
}
|
||||
|
||||
if (col2[2] > 0.5) {
|
||||
outcol[2] = col1[2] + t * (2.0 * (col2[2] - 0.5));
|
||||
}
|
||||
else {
|
||||
outcol[2] = col1[2] + t * (2.0 * (col2[2]) - 1.0);
|
||||
}
|
||||
|
||||
return outcol;
|
||||
}
|
||||
|
||||
color node_mix_clamp(color col)
|
||||
{
|
||||
color outcol = col;
|
||||
|
||||
outcol[0] = clamp(col[0], 0.0, 1.0);
|
||||
outcol[1] = clamp(col[1], 0.0, 1.0);
|
||||
outcol[2] = clamp(col[2], 0.0, 1.0);
|
||||
|
||||
return outcol;
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 */
|
||||
|
||||
#include "stdcycles.h"
|
||||
|
||||
shader node_combine_color(string color_type = "rgb",
|
||||
float Red = 0.0,
|
||||
float Green = 0.0,
|
||||
float Blue = 0.0,
|
||||
output color Color = 0.8)
|
||||
{
|
||||
if (color_type == "rgb" || color_type == "hsv" || color_type == "hsl")
|
||||
Color = color(color_type, Red, Green, Blue);
|
||||
else
|
||||
warning("%s", "Unknown color space!");
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 */
|
||||
|
||||
#include "stdcycles.h"
|
||||
|
||||
shader node_combine_xyz(float X = 0.0, float Y = 0.0, float Z = 0.0, output vector Vector = 0.8)
|
||||
{
|
||||
Vector = vector(X, Y, Z);
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 */
|
||||
|
||||
#include "stdcycles.h"
|
||||
|
||||
shader node_convert_from_color(color value_color = 0.0,
|
||||
output string value_string = "",
|
||||
output float value_float = 0.0,
|
||||
output int value_int = 0,
|
||||
output vector value_vector = vector(0.0, 0.0, 0.0),
|
||||
output point value_point = point(0.0, 0.0, 0.0),
|
||||
output normal value_normal = normal(0.0, 0.0, 0.0))
|
||||
{
|
||||
value_float = value_color[0] * 0.2126 + value_color[1] * 0.7152 + value_color[2] * 0.0722;
|
||||
value_int = (int)(value_color[0] * 0.2126 + value_color[1] * 0.7152 + value_color[2] * 0.0722);
|
||||
value_vector = vector(value_color[0], value_color[1], value_color[2]);
|
||||
value_point = point(value_color[0], value_color[1], value_color[2]);
|
||||
value_normal = normal(value_color[0], value_color[1], value_color[2]);
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 */
|
||||
|
||||
#include "stdcycles.h"
|
||||
|
||||
shader node_convert_from_float(float value_float = 0.0,
|
||||
output string value_string = "",
|
||||
output int value_int = 0,
|
||||
output color value_color = 0.0,
|
||||
output vector value_vector = vector(0.0, 0.0, 0.0),
|
||||
output point value_point = point(0.0, 0.0, 0.0),
|
||||
output normal value_normal = normal(0.0, 0.0, 0.0))
|
||||
{
|
||||
value_int = (int)value_float;
|
||||
value_color = color(value_float, value_float, value_float);
|
||||
value_vector = vector(value_float, value_float, value_float);
|
||||
value_point = point(value_float, value_float, value_float);
|
||||
value_normal = normal(value_float, value_float, value_float);
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 */
|
||||
|
||||
#include "stdcycles.h"
|
||||
|
||||
shader node_convert_from_int(int value_int = 0,
|
||||
output string value_string = "",
|
||||
output float value_float = 0.0,
|
||||
output color value_color = 0.0,
|
||||
output vector value_vector = vector(0.0, 0.0, 0.0),
|
||||
output point value_point = point(0.0, 0.0, 0.0),
|
||||
output normal value_normal = normal(0.0, 0.0, 0.0))
|
||||
{
|
||||
float f = (float)value_int;
|
||||
value_float = f;
|
||||
value_color = color(f, f, f);
|
||||
value_vector = vector(f, f, f);
|
||||
value_point = point(f, f, f);
|
||||
value_normal = normal(f, f, f);
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 */
|
||||
|
||||
#include "stdcycles.h"
|
||||
|
||||
shader node_convert_from_normal(normal value_normal = normal(0.0, 0.0, 0.0),
|
||||
output string value_string = "",
|
||||
output float value_float = 0.0,
|
||||
output int value_int = 0,
|
||||
output vector value_vector = vector(0.0, 0.0, 0.0),
|
||||
output color value_color = 0.0,
|
||||
output point value_point = point(0.0, 0.0, 0.0))
|
||||
{
|
||||
value_float = (value_normal[0] + value_normal[1] + value_normal[2]) * (1.0 / 3.0);
|
||||
value_int = (int)((value_normal[0] + value_normal[1] + value_normal[2]) * (1.0 / 3.0));
|
||||
value_vector = vector(value_normal[0], value_normal[1], value_normal[2]);
|
||||
value_color = color(value_normal[0], value_normal[1], value_normal[2]);
|
||||
value_point = point(value_normal[0], value_normal[1], value_normal[2]);
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 */
|
||||
|
||||
#include "stdcycles.h"
|
||||
|
||||
shader node_convert_from_point(point value_point = point(0.0, 0.0, 0.0),
|
||||
output string value_string = "",
|
||||
output float value_float = 0.0,
|
||||
output int value_int = 0,
|
||||
output vector value_vector = vector(0.0, 0.0, 0.0),
|
||||
output color value_color = 0.0,
|
||||
output normal value_normal = normal(0.0, 0.0, 0.0))
|
||||
{
|
||||
value_float = (value_point[0] + value_point[1] + value_point[2]) * (1.0 / 3.0);
|
||||
value_int = (int)((value_normal[0] + value_normal[1] + value_normal[2]) * (1.0 / 3.0));
|
||||
value_vector = vector(value_point[0], value_point[1], value_point[2]);
|
||||
value_color = color(value_point[0], value_point[1], value_point[2]);
|
||||
value_normal = normal(value_point[0], value_point[1], value_point[2]);
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 */
|
||||
|
||||
#include "stdcycles.h"
|
||||
|
||||
shader node_convert_from_string(string value_string = "",
|
||||
output color value_color = color(0.0, 0.0, 0.0),
|
||||
output float value_float = 0.0,
|
||||
output int value_int = 0,
|
||||
output vector value_vector = vector(0.0, 0.0, 0.0),
|
||||
output point value_point = point(0.0, 0.0, 0.0),
|
||||
output normal value_normal = normal(0.0, 0.0, 0.0))
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 */
|
||||
|
||||
#include "stdcycles.h"
|
||||
|
||||
shader node_convert_from_vector(vector value_vector = vector(0.0, 0.0, 0.0),
|
||||
output string value_string = "",
|
||||
output float value_float = 0.0,
|
||||
output int value_int = 0,
|
||||
output color value_color = color(0.0, 0.0, 0.0),
|
||||
output point value_point = point(0.0, 0.0, 0.0),
|
||||
output normal value_normal = normal(0.0, 0.0, 0.0))
|
||||
{
|
||||
value_float = (value_vector[0] + value_vector[1] + value_vector[2]) * (1.0 / 3.0);
|
||||
value_int = (int)((value_normal[0] + value_normal[1] + value_normal[2]) * (1.0 / 3.0));
|
||||
value_color = color(value_vector[0], value_vector[1], value_vector[2]);
|
||||
value_point = point(value_vector[0], value_vector[1], value_vector[2]);
|
||||
value_normal = normal(value_vector[0], value_vector[1], value_vector[2]);
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 */
|
||||
|
||||
#include "stdcycles.h"
|
||||
|
||||
shader node_diffuse_bsdf(color Color = 0.8,
|
||||
float Roughness = 0.0,
|
||||
normal Normal = N,
|
||||
output closure color BSDF = 0)
|
||||
{
|
||||
if (Roughness < 1e-5)
|
||||
BSDF = Color * diffuse(Normal);
|
||||
else
|
||||
BSDF = oren_nayar_diffuse_bsdf(Normal, clamp(Color, 0.0, 1.0), Roughness);
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 */
|
||||
|
||||
#include "stdcycles.h"
|
||||
|
||||
shader node_displacement(string space = "object",
|
||||
float Height = 0.0,
|
||||
float Midlevel = 0.5,
|
||||
float Scale = 1.0,
|
||||
normal Normal = N,
|
||||
output vector Displacement = vector(0.0, 0.0, 0.0))
|
||||
{
|
||||
Displacement = Normal;
|
||||
if (space == "object") {
|
||||
Displacement = transform("object", Displacement);
|
||||
}
|
||||
|
||||
Displacement = normalize(Displacement) * (Height - Midlevel) * Scale;
|
||||
|
||||
if (space == "object") {
|
||||
Displacement = transform("object", "world", Displacement);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 */
|
||||
|
||||
#include "stdcycles.h"
|
||||
|
||||
shader node_emission(color Color = 0.8, float Strength = 1.0, output closure color Emission = 0)
|
||||
{
|
||||
Emission = (Strength * Color) * emission();
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 */
|
||||
|
||||
#include "node_color.h"
|
||||
#include "stdcycles.h"
|
||||
|
||||
vector environment_texture_direction_to_equirectangular(vector dir)
|
||||
{
|
||||
float u = -atan2(dir[1], dir[0]) / (M_2PI) + 0.5;
|
||||
float v = atan2(dir[2], hypot(dir[0], dir[1])) / M_PI + 0.5;
|
||||
|
||||
return vector(u, v, 0.0);
|
||||
}
|
||||
|
||||
vector environment_texture_direction_to_mirrorball(vector idir)
|
||||
{
|
||||
vector dir = idir;
|
||||
dir[1] -= 1.0;
|
||||
|
||||
float div = 2.0 * sqrt(max(-0.5 * dir[1], 0.0));
|
||||
if (div > 0.0)
|
||||
dir /= div;
|
||||
|
||||
float u = 0.5 * (dir[0] + 1.0);
|
||||
float v = 0.5 * (dir[2] + 1.0);
|
||||
|
||||
return vector(u, v, 0.0);
|
||||
}
|
||||
|
||||
shader node_environment_texture(
|
||||
int use_mapping = 0,
|
||||
matrix mapping = matrix(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
|
||||
vector Vector = P,
|
||||
string filename = "",
|
||||
string projection = "equirectangular",
|
||||
string interpolation = "linear",
|
||||
int compress_as_srgb = 0,
|
||||
int ignore_alpha = 0,
|
||||
int unassociate_alpha = 0,
|
||||
int is_float = 1,
|
||||
output color Color = 0.0,
|
||||
output float Alpha = 1.0)
|
||||
{
|
||||
vector p = Vector;
|
||||
|
||||
if (use_mapping)
|
||||
p = transform(mapping, p);
|
||||
|
||||
p = normalize(p);
|
||||
|
||||
if (projection == "equirectangular")
|
||||
p = environment_texture_direction_to_equirectangular(p);
|
||||
else
|
||||
p = environment_texture_direction_to_mirrorball(p);
|
||||
|
||||
/* todo: use environment for better texture filtering of equirectangular */
|
||||
Color = (color)texture(
|
||||
filename, p[0], p[1], "wrap", "periodic", "interp", interpolation, "alpha", Alpha);
|
||||
|
||||
if (ignore_alpha) {
|
||||
Alpha = 1.0;
|
||||
}
|
||||
else if (unassociate_alpha) {
|
||||
Color = color_unpremultiply(Color, Alpha);
|
||||
|
||||
if (!is_float)
|
||||
Color = min(Color, 1.0);
|
||||
}
|
||||
|
||||
if (compress_as_srgb)
|
||||
Color = color_srgb_to_scene_linear(Color);
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 */
|
||||
|
||||
#include "node_ramp_util.h"
|
||||
#include "stdcycles.h"
|
||||
|
||||
shader node_float_curve(float ramp[] = {0.0},
|
||||
float min_x = 0.0,
|
||||
float max_x = 1.0,
|
||||
int extrapolate = 1,
|
||||
|
||||
float ValueIn = 0.0,
|
||||
float Factor = 0.0,
|
||||
output float ValueOut = 0.0)
|
||||
{
|
||||
float c = (ValueIn - min_x) / (max_x - min_x);
|
||||
|
||||
ValueOut = rgb_ramp_lookup(ramp, c, 1, extrapolate);
|
||||
|
||||
ValueOut = mix(ValueIn, ValueOut, Factor);
|
||||
}
|
||||
@@ -0,0 +1,141 @@
|
||||
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 */
|
||||
|
||||
#include "node_voronoi.h"
|
||||
#include "stdcycles.h"
|
||||
#include "vector2.h"
|
||||
#include "vector4.h"
|
||||
|
||||
#define vector3 point
|
||||
|
||||
/* The fractalization logic is the same as for fBM Noise, except that some additions are replaced
|
||||
* by lerps. */
|
||||
#define FRACTAL_VORONOI_X_FX(T) \
|
||||
VoronoiOutput fractal_voronoi_x_fx(VoronoiParams params, T coord) \
|
||||
{ \
|
||||
float amplitude = 1.0; \
|
||||
float max_amplitude = 0.0; \
|
||||
float scale = 1.0; \
|
||||
\
|
||||
VoronoiOutput Output; \
|
||||
Output.Distance = 0.0; \
|
||||
Output.Color = color(0.0, 0.0, 0.0); \
|
||||
Output.Position = vector4(0.0, 0.0, 0.0, 0.0); \
|
||||
int zero_input = params.detail == 0.0 || params.roughness == 0.0; \
|
||||
\
|
||||
for (int i = 0; i <= ceil(params.detail); ++i) { \
|
||||
VoronoiOutput octave; \
|
||||
if (params.feature == "f2") { \
|
||||
octave = voronoi_f2(params, coord * scale); \
|
||||
} \
|
||||
else if (params.feature == "smooth_f1" && params.smoothness != 0.0) { \
|
||||
octave = voronoi_smooth_f1(params, coord * scale); \
|
||||
} \
|
||||
else { \
|
||||
octave = voronoi_f1(params, coord * scale); \
|
||||
} \
|
||||
\
|
||||
if (zero_input) { \
|
||||
max_amplitude = 1.0; \
|
||||
Output = octave; \
|
||||
break; \
|
||||
} \
|
||||
else if (i <= params.detail) { \
|
||||
max_amplitude += amplitude; \
|
||||
Output.Distance += octave.Distance * amplitude; \
|
||||
Output.Color += octave.Color * amplitude; \
|
||||
Output.Position = mix(Output.Position, octave.Position / scale, amplitude); \
|
||||
scale *= params.lacunarity; \
|
||||
amplitude *= params.roughness; \
|
||||
} \
|
||||
else { \
|
||||
float remainder = params.detail - floor(params.detail); \
|
||||
if (remainder != 0.0) { \
|
||||
max_amplitude = mix(max_amplitude, max_amplitude + amplitude, remainder); \
|
||||
Output.Distance = mix( \
|
||||
Output.Distance, Output.Distance + octave.Distance * amplitude, remainder); \
|
||||
Output.Color = mix(Output.Color, Output.Color + octave.Color * amplitude, remainder); \
|
||||
Output.Position = mix(Output.Position, \
|
||||
mix(Output.Position, octave.Position / scale, amplitude), \
|
||||
remainder); \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
if (params.normalize) { \
|
||||
Output.Distance /= max_amplitude * params.max_distance; \
|
||||
Output.Color /= max_amplitude; \
|
||||
} \
|
||||
\
|
||||
Output.Position = safe_divide(Output.Position, params.scale); \
|
||||
\
|
||||
return Output; \
|
||||
}
|
||||
|
||||
/* The fractalization logic is the same as for fBM Noise, except that some additions are replaced
|
||||
* by lerps. */
|
||||
#define FRACTAL_VORONOI_DISTANCE_TO_EDGE_FUNCTION(T) \
|
||||
float fractal_voronoi_distance_to_edge(VoronoiParams params, T coord) \
|
||||
{ \
|
||||
float amplitude = 1.0; \
|
||||
float max_amplitude = params.max_distance; \
|
||||
float scale = 1.0; \
|
||||
float distance = 8.0; \
|
||||
\
|
||||
int zero_input = params.detail == 0.0 || params.roughness == 0.0; \
|
||||
\
|
||||
for (int i = 0; i <= ceil(params.detail); ++i) { \
|
||||
float octave_distance = voronoi_distance_to_edge(params, coord * scale); \
|
||||
\
|
||||
if (zero_input) { \
|
||||
distance = octave_distance; \
|
||||
break; \
|
||||
} \
|
||||
else if (i <= params.detail) { \
|
||||
max_amplitude = mix(max_amplitude, params.max_distance / scale, amplitude); \
|
||||
distance = mix(distance, min(distance, octave_distance / scale), amplitude); \
|
||||
scale *= params.lacunarity; \
|
||||
amplitude *= params.roughness; \
|
||||
} \
|
||||
else { \
|
||||
float remainder = params.detail - floor(params.detail); \
|
||||
if (remainder != 0.0) { \
|
||||
float lerp_amplitude = mix(max_amplitude, params.max_distance / scale, amplitude); \
|
||||
max_amplitude = mix(max_amplitude, lerp_amplitude, remainder); \
|
||||
float lerp_distance = mix(distance, min(distance, octave_distance / scale), amplitude); \
|
||||
distance = mix(distance, min(distance, lerp_distance), remainder); \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
if (params.normalize) { \
|
||||
distance /= max_amplitude; \
|
||||
} \
|
||||
\
|
||||
return distance; \
|
||||
}
|
||||
|
||||
/* **** 1D Fractal Voronoi **** */
|
||||
|
||||
FRACTAL_VORONOI_X_FX(float)
|
||||
|
||||
FRACTAL_VORONOI_DISTANCE_TO_EDGE_FUNCTION(float)
|
||||
|
||||
/* **** 2D Fractal Voronoi **** */
|
||||
|
||||
FRACTAL_VORONOI_X_FX(vector2)
|
||||
|
||||
FRACTAL_VORONOI_DISTANCE_TO_EDGE_FUNCTION(vector2)
|
||||
|
||||
/* **** 3D Fractal Voronoi **** */
|
||||
|
||||
FRACTAL_VORONOI_X_FX(vector3)
|
||||
|
||||
FRACTAL_VORONOI_DISTANCE_TO_EDGE_FUNCTION(vector3)
|
||||
|
||||
/* **** 4D Fractal Voronoi **** */
|
||||
|
||||
FRACTAL_VORONOI_X_FX(vector4)
|
||||
|
||||
FRACTAL_VORONOI_DISTANCE_TO_EDGE_FUNCTION(vector4)
|
||||
@@ -0,0 +1,50 @@
|
||||
/* SPDX-FileCopyrightText: 2009-2010 Sony Pictures Imageworks Inc., et al. All Rights Reserved.
|
||||
* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*
|
||||
* Adapted code from Open Shading Language. */
|
||||
|
||||
float fresnel_dielectric_cos(float cosi, float eta)
|
||||
{
|
||||
/* compute fresnel reflectance without explicitly computing
|
||||
* the refracted direction */
|
||||
float c = fabs(cosi);
|
||||
float g = eta * eta - 1 + c * c;
|
||||
float result;
|
||||
|
||||
if (g > 0) {
|
||||
g = sqrt(g);
|
||||
float A = (g - c) / (g + c);
|
||||
float B = (c * (g + c) - 1) / (c * (g - c) + 1);
|
||||
result = 0.5 * A * A * (1 + B * B);
|
||||
}
|
||||
else {
|
||||
result = 1.0; /* TIR (no refracted component) */
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
color fresnel_conductor(float cosi, color eta, color k)
|
||||
{
|
||||
color cosi2 = color(cosi * cosi);
|
||||
color one = color(1, 1, 1);
|
||||
color tmp_f = eta * eta + k * k;
|
||||
color tmp = tmp_f * cosi2;
|
||||
color Rparl2 = (tmp - (2.0 * eta * cosi) + one) / (tmp + (2.0 * eta * cosi) + one);
|
||||
color Rperp2 = (tmp_f - (2.0 * eta * cosi) + cosi2) / (tmp_f + (2.0 * eta * cosi) + cosi2);
|
||||
return (Rparl2 + Rperp2) * 0.5;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 */
|
||||
|
||||
#include "node_fresnel.h"
|
||||
#include "stdcycles.h"
|
||||
|
||||
shader node_fresnel(float IOR = 1.45, normal Normal = N, output float Fac = 0.0)
|
||||
{
|
||||
float f = max(IOR, 1e-5);
|
||||
float eta = backfacing() ? 1.0 / f : f;
|
||||
float cosi = dot(I, Normal);
|
||||
Fac = fresnel_dielectric_cos(cosi, eta);
|
||||
}
|
||||
@@ -0,0 +1,340 @@
|
||||
/* SPDX-FileCopyrightText: 2024 Blender Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 */
|
||||
|
||||
/* Implements Gabor noise based on the paper:
|
||||
*
|
||||
* Lagae, Ares, et al. "Procedural noise using sparse Gabor convolution." ACM Transactions on
|
||||
* Graphics (TOG) 28.3 (2009): 1-10.
|
||||
*
|
||||
* But with the improvements from the paper:
|
||||
*
|
||||
* Tavernier, Vincent, et al. "Making gabor noise fast and normalized." Eurographics 2019-40th
|
||||
* Annual Conference of the European Association for Computer Graphics. 2019.
|
||||
*
|
||||
* And compute the Phase and Intensity of the Gabor based on the paper:
|
||||
*
|
||||
* Tricard, Thibault, et al. "Procedural phasor noise." ACM Transactions on Graphics (TOG) 38.4
|
||||
* (2019): 1-13.
|
||||
*/
|
||||
|
||||
#include "node_hash.h"
|
||||
#include "stdcycles.h"
|
||||
#include "vector2.h"
|
||||
#include "vector4.h"
|
||||
|
||||
#define vector3 point
|
||||
|
||||
/* The original Gabor noise paper specifies that the impulses count for each cell should be
|
||||
* computed by sampling a Poisson distribution whose mean is the impulse density. However,
|
||||
* Tavernier's paper showed that stratified Poisson point sampling is better assuming the weights
|
||||
* are sampled using a Bernoulli distribution, as shown in Figure (3). By stratified sampling, they
|
||||
* mean a constant number of impulses per cell, so the stratification is the grid itself in that
|
||||
* sense, as described in the supplementary material of the paper. */
|
||||
#define IMPULSES_COUNT 8
|
||||
|
||||
/* Computes a 2D Gabor kernel based on Equation (6) in the original Gabor noise paper. Where the
|
||||
* frequency argument is the F_0 parameter and the orientation argument is the w_0 parameter. We
|
||||
* assume the Gaussian envelope has a unit magnitude, that is, K = 1. That is because we will
|
||||
* eventually normalize the final noise value to the unit range, so the multiplication by the
|
||||
* magnitude will be canceled by the normalization. Further, we also assume a unit Gaussian width,
|
||||
* that is, a = 1. That is because it does not provide much artistic control. It follows that the
|
||||
* Gaussian will be truncated at pi.
|
||||
*
|
||||
* To avoid the discontinuities caused by the aforementioned truncation, the Gaussian is windowed
|
||||
* using a Hann window, that is because contrary to the claim made in the original Gabor paper,
|
||||
* truncating the Gaussian produces significant artifacts especially when differentiated for bump
|
||||
* mapping. The Hann window is C1 continuous and has limited effect on the shape of the Gaussian,
|
||||
* so it felt like an appropriate choice.
|
||||
*
|
||||
* Finally, instead of computing the Gabor value directly, we instead use the complex phasor
|
||||
* formulation described in section 3.1.1 in Tricard's paper. That's done to be able to compute the
|
||||
* phase and intensity of the Gabor noise after summation based on equations (8) and (9). The
|
||||
* return value of the Gabor kernel function is then a complex number whose real value is the
|
||||
* value computed in the original Gabor noise paper, and whose imaginary part is the sine
|
||||
* counterpart of the real part, which is the only extra computation in the new formulation.
|
||||
*
|
||||
* Note that while the original Gabor noise paper uses the cosine part of the phasor, that is, the
|
||||
* real part of the phasor, we use the sine part instead, that is, the imaginary part of the
|
||||
* phasor, as suggested by Tavernier's paper in "Section 3.3. Instance stationarity and
|
||||
* normalization", to ensure a zero mean, which should help with normalization. */
|
||||
vector2 compute_2d_gabor_kernel(vector2 position, float frequency, float orientation)
|
||||
{
|
||||
float distance_squared = dot(position, position);
|
||||
float hann_window = 0.5 + 0.5 * cos(M_PI * distance_squared);
|
||||
float gaussian_envelop = exp(-M_PI * distance_squared);
|
||||
float windowed_gaussian_envelope = gaussian_envelop * hann_window;
|
||||
|
||||
vector2 frequency_vector = frequency * vector2(cos(orientation), sin(orientation));
|
||||
float angle = 2.0 * M_PI * dot(position, frequency_vector);
|
||||
vector2 phasor = vector2(cos(angle), sin(angle));
|
||||
|
||||
return windowed_gaussian_envelope * phasor;
|
||||
}
|
||||
|
||||
/* Computes the approximate standard deviation of the zero mean normal distribution representing
|
||||
* the amplitude distribution of the noise based on Equation (9) in the original Gabor noise paper.
|
||||
* For simplicity, the Hann window is ignored and the orientation is fixed since the variance is
|
||||
* orientation invariant. We start integrating the squared Gabor kernel with respect to x:
|
||||
*
|
||||
* \int_{-\infty}^{-\infty} (e^{- \pi (x^2 + y^2)} cos(2 \pi f_0 x))^2 dx
|
||||
*
|
||||
* Which gives:
|
||||
*
|
||||
* \frac{(e^{2 \pi f_0^2}-1) e^{-2 \pi y^2 - 2 pi f_0^2}}{2^\frac{3}{2}}
|
||||
*
|
||||
* Then we similarly integrate with respect to y to get:
|
||||
*
|
||||
* \frac{1 - e^{-2 \pi f_0^2}}{4}
|
||||
*
|
||||
* Secondly, we note that the second moment of the weights distribution is 0.5 since it is a
|
||||
* fair Bernoulli distribution. So the final standard deviation expression is square root the
|
||||
* integral multiplied by the impulse density multiplied by the second moment.
|
||||
*
|
||||
* Note however that the integral is almost constant for all frequencies larger than one, and
|
||||
* converges to an upper limit as the frequency approaches infinity, so we replace the expression
|
||||
* with the following limit:
|
||||
*
|
||||
* \lim_{x \to \infty} \frac{1 - e^{-2 \pi f_0^2}}{4}
|
||||
*
|
||||
* To get an approximation of 0.25. */
|
||||
float compute_2d_gabor_standard_deviation()
|
||||
{
|
||||
float integral_of_gabor_squared = 0.25;
|
||||
float second_moment = 0.5;
|
||||
return sqrt(IMPULSES_COUNT * second_moment * integral_of_gabor_squared);
|
||||
}
|
||||
|
||||
/* Computes the Gabor noise value at the given position for the given cell. This is essentially the
|
||||
* sum in Equation (8) in the original Gabor noise paper, where we sum Gabor kernels sampled at a
|
||||
* random position with a random weight. The orientation of the kernel is constant for anisotropic
|
||||
* noise while it is random for isotropic noise. The original Gabor noise paper mentions that the
|
||||
* weights should be uniformly distributed in the [-1, 1] range, however, Tavernier's paper showed
|
||||
* that using a Bernoulli distribution yields better results, so that is what we do. */
|
||||
vector2 compute_2d_gabor_noise_cell(
|
||||
vector2 cell, vector2 position, float frequency, float isotropy, float base_orientation)
|
||||
|
||||
{
|
||||
vector2 noise = vector2(0.0, 0.0);
|
||||
for (int i = 0; i < IMPULSES_COUNT; ++i) {
|
||||
/* Compute unique seeds for each of the needed random variables. */
|
||||
vector3 seed_for_orientation = vector3(cell.x, cell.y, i * 3);
|
||||
vector3 seed_for_kernel_center = vector3(cell.x, cell.y, i * 3 + 1);
|
||||
vector3 seed_for_weight = vector3(cell.x, cell.y, i * 3 + 2);
|
||||
|
||||
/* For isotropic noise, add a random orientation amount, while for anisotropic noise, use the
|
||||
* base orientation. Linearly interpolate between the two cases using the isotropy factor. Note
|
||||
* that the random orientation range spans pi as opposed to two pi, that's because the Gabor
|
||||
* kernel is symmetric around pi. */
|
||||
float random_orientation = (hash_vector3_to_float(seed_for_orientation) - 0.5) * M_PI;
|
||||
float orientation = base_orientation + random_orientation * isotropy;
|
||||
|
||||
vector2 kernel_center = hash_vector3_to_vector2(seed_for_kernel_center);
|
||||
vector2 position_in_kernel_space = position - kernel_center;
|
||||
|
||||
/* The kernel is windowed beyond the unit distance, so early exit with a zero for points that
|
||||
* are further than a unit radius. */
|
||||
if (dot(position_in_kernel_space, position_in_kernel_space) >= 1.0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* We either add or subtract the Gabor kernel based on a Bernoulli distribution of equal
|
||||
* probability. */
|
||||
float weight = hash_vector3_to_float(seed_for_weight) < 0.5 ? -1.0 : 1.0;
|
||||
|
||||
noise += weight * compute_2d_gabor_kernel(position_in_kernel_space, frequency, orientation);
|
||||
}
|
||||
return noise;
|
||||
}
|
||||
|
||||
/* Computes the Gabor noise value by dividing the space into a grid and evaluating the Gabor noise
|
||||
* in the space of each cell of the 3x3 cell neighborhood. */
|
||||
vector2 compute_2d_gabor_noise(vector2 coordinates,
|
||||
float frequency,
|
||||
float isotropy,
|
||||
float base_orientation)
|
||||
{
|
||||
vector2 cell_position = floor(coordinates);
|
||||
vector2 local_position = coordinates - cell_position;
|
||||
|
||||
vector2 sum = vector2(0.0, 0.0);
|
||||
for (int j = -1; j <= 1; j++) {
|
||||
for (int i = -1; i <= 1; i++) {
|
||||
vector2 cell_offset = vector2(i, j);
|
||||
vector2 current_cell_position = cell_position + cell_offset;
|
||||
vector2 position_in_cell_space = local_position - cell_offset;
|
||||
sum += compute_2d_gabor_noise_cell(
|
||||
current_cell_position, position_in_cell_space, frequency, isotropy, base_orientation);
|
||||
}
|
||||
}
|
||||
|
||||
return sum;
|
||||
}
|
||||
|
||||
/* Identical to compute_2d_gabor_kernel, except it is evaluated in 3D space. Notice that Equation
|
||||
* (6) in the original Gabor noise paper computes the frequency vector using (cos(w_0), sin(w_0)),
|
||||
* which we also do in the 2D variant, however, for 3D, the orientation is already a unit frequency
|
||||
* vector, so we just need to scale it by the frequency value. */
|
||||
vector2 compute_3d_gabor_kernel(vector3 position, float frequency, vector3 orientation)
|
||||
{
|
||||
float distance_squared = dot(position, position);
|
||||
float hann_window = 0.5 + 0.5 * cos(M_PI * distance_squared);
|
||||
float gaussian_envelop = exp(-M_PI * distance_squared);
|
||||
float windowed_gaussian_envelope = gaussian_envelop * hann_window;
|
||||
|
||||
vector3 frequency_vector = frequency * orientation;
|
||||
float angle = 2.0 * M_PI * dot(position, frequency_vector);
|
||||
vector2 phasor = vector2(cos(angle), sin(angle));
|
||||
|
||||
return windowed_gaussian_envelope * phasor;
|
||||
}
|
||||
|
||||
/* Identical to compute_2d_gabor_standard_deviation except we do triple integration in 3D. The only
|
||||
* difference is the denominator in the integral expression, which is 2^{5 / 2} for the 3D case
|
||||
* instead of 4 for the 2D case. Similarly, the limit evaluates to 1 / (4 * sqrt(2)). */
|
||||
float compute_3d_gabor_standard_deviation()
|
||||
{
|
||||
float integral_of_gabor_squared = 1.0 / (4.0 * M_SQRT2);
|
||||
float second_moment = 0.5;
|
||||
return sqrt(IMPULSES_COUNT * second_moment * integral_of_gabor_squared);
|
||||
}
|
||||
|
||||
/* Computes the orientation of the Gabor kernel such that it is constant for anisotropic
|
||||
* noise while it is random for isotropic noise. We randomize in spherical coordinates for a
|
||||
* uniform distribution. */
|
||||
vector3 compute_3d_orientation(vector3 orientation, float isotropy, vector4 seed)
|
||||
{
|
||||
/* Return the base orientation in case we are completely anisotropic. */
|
||||
if (isotropy == 0.0) {
|
||||
return orientation;
|
||||
}
|
||||
|
||||
/* Compute the orientation in spherical coordinates. */
|
||||
float inclination = acos(orientation.z);
|
||||
float azimuth = sign(orientation.y) *
|
||||
acos(orientation.x / length(vector2(orientation.x, orientation.y)));
|
||||
|
||||
/* For isotropic noise, add a random orientation amount, while for anisotropic noise, use the
|
||||
* base orientation. Linearly interpolate between the two cases using the isotropy factor. Note
|
||||
* that the random orientation range is to pi as opposed to two pi, that's because the Gabor
|
||||
* kernel is symmetric around pi. */
|
||||
vector2 random_angles = hash_vector4_to_vector2(seed) * M_PI;
|
||||
inclination += random_angles.x * isotropy;
|
||||
azimuth += random_angles.y * isotropy;
|
||||
|
||||
/* Convert back to Cartesian coordinates, */
|
||||
return vector3(
|
||||
sin(inclination) * cos(azimuth), sin(inclination) * sin(azimuth), cos(inclination));
|
||||
}
|
||||
|
||||
vector2 compute_3d_gabor_noise_cell(
|
||||
vector3 cell, vector3 position, float frequency, float isotropy, vector3 base_orientation)
|
||||
|
||||
{
|
||||
vector2 noise = vector2(0.0, 0.0);
|
||||
for (int i = 0; i < IMPULSES_COUNT; ++i) {
|
||||
/* Compute unique seeds for each of the needed random variables. */
|
||||
vector4 seed_for_orientation = vector4(cell.x, cell.y, cell.z, i * 3);
|
||||
vector4 seed_for_kernel_center = vector4(cell.x, cell.y, cell.z, i * 3 + 1);
|
||||
vector4 seed_for_weight = vector4(cell.x, cell.y, cell.z, i * 3 + 2);
|
||||
|
||||
vector3 orientation = compute_3d_orientation(base_orientation, isotropy, seed_for_orientation);
|
||||
|
||||
vector3 kernel_center = hash_vector4_to_vector3(seed_for_kernel_center);
|
||||
vector3 position_in_kernel_space = position - kernel_center;
|
||||
|
||||
/* The kernel is windowed beyond the unit distance, so early exit with a zero for points that
|
||||
* are further than a unit radius. */
|
||||
if (dot(position_in_kernel_space, position_in_kernel_space) >= 1.0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* We either add or subtract the Gabor kernel based on a Bernoulli distribution of equal
|
||||
* probability. */
|
||||
float weight = hash_vector4_to_float(seed_for_weight) < 0.5 ? -1.0 : 1.0;
|
||||
|
||||
noise += weight * compute_3d_gabor_kernel(position_in_kernel_space, frequency, orientation);
|
||||
}
|
||||
return noise;
|
||||
}
|
||||
|
||||
/* Identical to compute_2d_gabor_noise but works in the 3D neighborhood of the noise. */
|
||||
vector2 compute_3d_gabor_noise(vector3 coordinates,
|
||||
float frequency,
|
||||
float isotropy,
|
||||
vector3 base_orientation)
|
||||
{
|
||||
vector3 cell_position = floor(coordinates);
|
||||
vector3 local_position = coordinates - cell_position;
|
||||
|
||||
vector2 sum = vector2(0.0, 0.0);
|
||||
for (int k = -1; k <= 1; k++) {
|
||||
for (int j = -1; j <= 1; j++) {
|
||||
for (int i = -1; i <= 1; i++) {
|
||||
vector3 cell_offset = vector3(i, j, k);
|
||||
vector3 current_cell_position = cell_position + cell_offset;
|
||||
vector3 position_in_cell_space = local_position - cell_offset;
|
||||
sum += compute_3d_gabor_noise_cell(
|
||||
current_cell_position, position_in_cell_space, frequency, isotropy, base_orientation);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return sum;
|
||||
}
|
||||
|
||||
shader node_gabor_texture(int use_mapping = 0,
|
||||
matrix mapping = matrix(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
|
||||
string type = "2D",
|
||||
vector3 Vector = P,
|
||||
float Scale = 5.0,
|
||||
float Frequency = 2.0,
|
||||
float Anisotropy = 1.0,
|
||||
float Orientation2D = M_PI / 4.0,
|
||||
vector3 Orientation3D = vector3(M_SQRT2, M_SQRT2, 0.0),
|
||||
output float Value = 0.0,
|
||||
output float Phase = 0.0,
|
||||
output float Intensity = 0.0)
|
||||
{
|
||||
vector3 coordinates = Vector;
|
||||
if (use_mapping) {
|
||||
coordinates = transform(mapping, coordinates);
|
||||
}
|
||||
|
||||
vector3 scaled_coordinates = coordinates * Scale;
|
||||
float isotropy = 1.0 - clamp(Anisotropy, 0.0, 1.0);
|
||||
float frequency = max(0.001, Frequency);
|
||||
|
||||
vector2 phasor = vector2(0.0, 0.0);
|
||||
float standard_deviation = 1.0;
|
||||
if (type == "2D") {
|
||||
phasor = compute_2d_gabor_noise(
|
||||
vector2(scaled_coordinates.x, scaled_coordinates.y), frequency, isotropy, Orientation2D);
|
||||
standard_deviation = compute_2d_gabor_standard_deviation();
|
||||
}
|
||||
else if (type == "3D") {
|
||||
vector3 orientation = normalize(vector(Orientation3D));
|
||||
phasor = compute_3d_gabor_noise(scaled_coordinates, frequency, isotropy, orientation);
|
||||
standard_deviation = compute_3d_gabor_standard_deviation();
|
||||
}
|
||||
else {
|
||||
error("Unknown type!");
|
||||
}
|
||||
|
||||
/* Normalize the noise by dividing by six times the standard deviation, which was determined
|
||||
* empirically. */
|
||||
float normalization_factor = 6.0 * standard_deviation;
|
||||
|
||||
/* As discussed in compute_2d_gabor_kernel, we use the imaginary part of the phasor as the Gabor
|
||||
* value. But remap to [0, 1] from [-1, 1]. */
|
||||
Value = (phasor.y / normalization_factor) * 0.5 + 0.5;
|
||||
|
||||
/* Compute the phase based on equation (9) in Tricard's paper. But remap the phase into the
|
||||
* [0, 1] range. */
|
||||
Phase = (atan2(phasor.y, phasor.x) + M_PI) / (2.0 * M_PI);
|
||||
|
||||
/* Compute the intensity based on equation (8) in Tricard's paper. */
|
||||
Intensity = length(phasor) / normalization_factor;
|
||||
}
|
||||
|
||||
#undef vector3
|
||||
@@ -0,0 +1,10 @@
|
||||
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 */
|
||||
|
||||
#include "stdcycles.h"
|
||||
|
||||
shader node_gamma(color ColorIn = 0.8, float Gamma = 1.0, output color ColorOut = 0.0)
|
||||
{
|
||||
ColorOut = pow(ColorIn, Gamma);
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 */
|
||||
|
||||
#include "stdcycles.h"
|
||||
|
||||
shader node_geometry(string bump_offset = "center",
|
||||
float bump_filter_width = BUMP_FILTER_WIDTH,
|
||||
|
||||
output point Position = point(0.0, 0.0, 0.0),
|
||||
output normal Normal = normal(0.0, 0.0, 0.0),
|
||||
output normal Tangent = normal(0.0, 0.0, 0.0),
|
||||
output normal TrueNormal = normal(0.0, 0.0, 0.0),
|
||||
output vector Incoming = vector(0.0, 0.0, 0.0),
|
||||
output point Parametric = point(0.0, 0.0, 0.0),
|
||||
output float Backfacing = 0.0,
|
||||
output float Pointiness = 0.0,
|
||||
output float RandomPerIsland = 0.0)
|
||||
{
|
||||
Position = P;
|
||||
Normal = N;
|
||||
TrueNormal = Ng;
|
||||
Incoming = I;
|
||||
Parametric = point(1.0 - u - v, u, 0.0);
|
||||
Backfacing = backfacing();
|
||||
|
||||
if (bump_offset == "dx") {
|
||||
Position += Dx(Position) * bump_filter_width;
|
||||
Parametric += Dx(Parametric) * bump_filter_width;
|
||||
}
|
||||
else if (bump_offset == "dy") {
|
||||
Position += Dy(Position) * bump_filter_width;
|
||||
Parametric += Dy(Parametric) * bump_filter_width;
|
||||
}
|
||||
|
||||
point generated;
|
||||
float IsCurve = 0;
|
||||
float IsPoint = 0;
|
||||
getattribute("geom:is_curve", IsCurve);
|
||||
getattribute("geom:is_point", IsPoint);
|
||||
|
||||
/* create spherical tangent from generated coordinates if they're available,
|
||||
* unless we're on a curve or point. */
|
||||
if (!(IsCurve || IsPoint) && getattribute("geom:generated", generated)) {
|
||||
normal data = normal(-(generated[1] - 0.5), (generated[0] - 0.5), 0.0);
|
||||
vector T = transform("object", "world", data);
|
||||
Tangent = cross(Normal, normalize(cross(T, Normal)));
|
||||
}
|
||||
else {
|
||||
/* otherwise use surface derivatives */
|
||||
Tangent = normalize(dPdu);
|
||||
}
|
||||
|
||||
getattribute("geom:pointiness", Pointiness);
|
||||
if (bump_offset == "dx") {
|
||||
Pointiness += Dx(Pointiness) * bump_filter_width;
|
||||
}
|
||||
else if (bump_offset == "dy") {
|
||||
Pointiness += Dy(Pointiness) * bump_filter_width;
|
||||
}
|
||||
|
||||
getattribute("geom:random_per_island", RandomPerIsland);
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 */
|
||||
|
||||
#include "node_fresnel.h"
|
||||
#include "stdcycles.h"
|
||||
|
||||
shader node_glass_bsdf(color Color = 0.8,
|
||||
string distribution = "ggx",
|
||||
float Roughness = 0.2,
|
||||
float IOR = 1.45,
|
||||
float ThinFilmThickness = 0.0,
|
||||
float ThinFilmIOR = 1.33,
|
||||
normal Normal = N,
|
||||
output closure color BSDF = 0)
|
||||
{
|
||||
color base_color = max(Color, color(0.0));
|
||||
float r2 = clamp(Roughness, 0.0, 1.0);
|
||||
r2 = r2 * r2;
|
||||
float eta = max(IOR, 1e-5);
|
||||
float thinfilm_ior = backfacing() ? ThinFilmIOR / eta : ThinFilmIOR;
|
||||
eta = backfacing() ? 1.0 / eta : eta;
|
||||
color F0 = F0_from_ior(eta);
|
||||
color F90 = color(1.0);
|
||||
|
||||
BSDF = generalized_schlick_bsdf(Normal,
|
||||
vector(0.0),
|
||||
base_color,
|
||||
base_color,
|
||||
r2,
|
||||
r2,
|
||||
F0,
|
||||
F90,
|
||||
-eta,
|
||||
distribution,
|
||||
"thinfilm_thickness",
|
||||
ThinFilmThickness,
|
||||
"thinfilm_ior",
|
||||
thinfilm_ior);
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 */
|
||||
|
||||
#include "node_fresnel.h"
|
||||
#include "stdcycles.h"
|
||||
|
||||
shader node_glossy_bsdf(color Color = 0.8,
|
||||
string distribution = "ggx",
|
||||
float Roughness = 0.2,
|
||||
float Anisotropy = 0.0,
|
||||
float Rotation = 0.0,
|
||||
normal Normal = N,
|
||||
normal Tangent = 0.0,
|
||||
output closure color BSDF = 0)
|
||||
{
|
||||
/* compute roughness */
|
||||
color base_color = max(Color, color(0.0));
|
||||
float roughness = clamp(Roughness, 0.0, 1.0);
|
||||
roughness = roughness * roughness;
|
||||
float roughness_u, roughness_v;
|
||||
float aniso = clamp(Anisotropy, -0.99, 0.99);
|
||||
|
||||
/* rotate tangent around normal */
|
||||
vector T = Tangent;
|
||||
|
||||
if (abs(aniso) <= 1e-4) {
|
||||
roughness_u = roughness;
|
||||
roughness_v = roughness;
|
||||
}
|
||||
else {
|
||||
if (Rotation != 0.0)
|
||||
T = rotate(T, Rotation * M_2PI, point(0.0, 0.0, 0.0), Normal);
|
||||
|
||||
if (aniso < 0.0) {
|
||||
roughness_u = roughness / (1.0 + aniso);
|
||||
roughness_v = roughness * (1.0 + aniso);
|
||||
}
|
||||
else {
|
||||
roughness_u = roughness * (1.0 - aniso);
|
||||
roughness_v = roughness / (1.0 - aniso);
|
||||
}
|
||||
}
|
||||
|
||||
if (distribution == "Multiscatter GGX")
|
||||
BSDF = base_color *
|
||||
microfacet_multi_ggx_aniso(Normal, T, roughness_u, roughness_v, base_color);
|
||||
else
|
||||
BSDF = base_color * microfacet(distribution, Normal, T, roughness_u, roughness_v, 0.0, 0);
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 */
|
||||
|
||||
#include "stdcycles.h"
|
||||
|
||||
/* Gradient */
|
||||
|
||||
float gradient(point p, string type)
|
||||
{
|
||||
float x, y, z;
|
||||
|
||||
x = p[0];
|
||||
y = p[1];
|
||||
z = p[2];
|
||||
|
||||
float result = 0.0;
|
||||
|
||||
if (type == "linear") {
|
||||
result = x;
|
||||
}
|
||||
else if (type == "quadratic") {
|
||||
float r = max(x, 0.0);
|
||||
result = r * r;
|
||||
}
|
||||
else if (type == "easing") {
|
||||
float r = min(max(x, 0.0), 1.0);
|
||||
float t = r * r;
|
||||
|
||||
result = (3.0 * t - 2.0 * t * r);
|
||||
}
|
||||
else if (type == "diagonal") {
|
||||
result = (x + y) * 0.5;
|
||||
}
|
||||
else if (type == "radial") {
|
||||
result = atan2(y, x) / M_2PI + 0.5;
|
||||
}
|
||||
else {
|
||||
float r = max(1.0 - sqrt(x * x + y * y + z * z), 0.0);
|
||||
|
||||
if (type == "quadratic_sphere")
|
||||
result = r * r;
|
||||
else if (type == "spherical")
|
||||
result = r;
|
||||
}
|
||||
|
||||
return clamp(result, 0.0, 1.0);
|
||||
}
|
||||
|
||||
shader node_gradient_texture(
|
||||
int use_mapping = 0,
|
||||
matrix mapping = matrix(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
|
||||
string gradient_type = "linear",
|
||||
point Vector = P,
|
||||
output float Fac = 0.0,
|
||||
output color Color = 0.0)
|
||||
{
|
||||
point p = Vector;
|
||||
|
||||
if (use_mapping)
|
||||
p = transform(mapping, p);
|
||||
|
||||
Fac = gradient(p, gradient_type);
|
||||
Color = color(Fac, Fac, Fac);
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 */
|
||||
|
||||
#include "stdcycles.h"
|
||||
|
||||
shader node_hair_bsdf(color Color = 0.8,
|
||||
string component = "reflection",
|
||||
float Offset = 0.0,
|
||||
float RoughnessU = 0.1,
|
||||
float RoughnessV = 1.0,
|
||||
normal Tangent = normal(0, 0, 0),
|
||||
output closure color BSDF = 0)
|
||||
{
|
||||
float roughnessh = clamp(RoughnessU, 0.001, 1.0);
|
||||
float roughnessv = clamp(RoughnessV, 0.001, 1.0);
|
||||
float offset = -Offset;
|
||||
|
||||
normal T;
|
||||
float IsCurve = 0;
|
||||
getattribute("geom:is_curve", IsCurve);
|
||||
|
||||
if (isconnected(Tangent)) {
|
||||
T = Tangent;
|
||||
}
|
||||
else if (!IsCurve) {
|
||||
T = normalize(dPdv);
|
||||
offset = 0.0;
|
||||
}
|
||||
else {
|
||||
T = normalize(dPdu);
|
||||
}
|
||||
|
||||
if (backfacing() && IsCurve) {
|
||||
BSDF = transparent();
|
||||
}
|
||||
else {
|
||||
if (component == "reflection")
|
||||
BSDF = Color * hair_reflection(N, roughnessh, roughnessv, T, offset);
|
||||
else
|
||||
BSDF = Color * hair_transmission(N, roughnessh, roughnessv, T, offset);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 */
|
||||
|
||||
#include "stdcycles.h"
|
||||
|
||||
shader node_hair_info(output float IsStrand = 0.0,
|
||||
output float Intercept = 0.0,
|
||||
output float Length = 0.0,
|
||||
output float Thickness = 0.0,
|
||||
output normal TangentNormal = N,
|
||||
output float Random = 0)
|
||||
{
|
||||
getattribute("geom:is_curve", IsStrand);
|
||||
getattribute("geom:curve_intercept", Intercept);
|
||||
getattribute("geom:curve_length", Length);
|
||||
getattribute("geom:curve_thickness", Thickness);
|
||||
getattribute("geom:curve_tangent_normal", TangentNormal);
|
||||
getattribute("geom:curve_random", Random);
|
||||
}
|
||||
184
blender-5.2.0/intern/cycles/kernel/osl/shaders/node_hash.h
Normal file
184
blender-5.2.0/intern/cycles/kernel/osl/shaders/node_hash.h
Normal file
@@ -0,0 +1,184 @@
|
||||
/* SPDX-FileCopyrightText: 2011-2025 Blender Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 */
|
||||
|
||||
#include "int_vector_types.h"
|
||||
#include "stdcycles.h"
|
||||
#include "vector2.h"
|
||||
#include "vector4.h"
|
||||
|
||||
#define vector3 point
|
||||
|
||||
/* Hashing `uint` or `uint[234]` into a float in the range [0, 1].
|
||||
* Based on PCG 2D/3D/4D hash, but with signed integers. */
|
||||
|
||||
vector2 hash_int2_to_vector2(int2 k)
|
||||
{
|
||||
int2 v = k * 1664525 + 1013904223;
|
||||
v.x += v.y * 1664525;
|
||||
v.y += v.x * 1664525;
|
||||
v = v ^ (v >> 16);
|
||||
v.x += v.y * 1664525;
|
||||
v.y += v.x * 1664525;
|
||||
vector2 f = int2_to_vec2(v & 0x7FFFFFFF);
|
||||
return f * (1.0 / (float)0x7FFFFFFF);
|
||||
}
|
||||
|
||||
vector3 hash_int3_to_vector3(int3 k)
|
||||
{
|
||||
int3 v = k * 1664525 + 1013904223;
|
||||
v.x += v.y * v.z;
|
||||
v.y += v.z * v.x;
|
||||
v.z += v.x * v.y;
|
||||
v = v ^ (v >> 16);
|
||||
v.x += v.y * v.z;
|
||||
v.y += v.z * v.x;
|
||||
v.z += v.x * v.y;
|
||||
vector3 f = int3_to_vec3(v & 0x7FFFFFFF);
|
||||
return f * (1.0 / (float)0x7FFFFFFF);
|
||||
}
|
||||
|
||||
vector4 hash_int4_to_vector4(int4 k)
|
||||
{
|
||||
int4 v = k * 1664525 + 1013904223;
|
||||
v.x += v.y * v.w;
|
||||
v.y += v.z * v.x;
|
||||
v.z += v.x * v.y;
|
||||
v.w += v.y * v.z;
|
||||
v = v ^ (v >> 16);
|
||||
v.x += v.y * v.w;
|
||||
v.y += v.z * v.x;
|
||||
v.z += v.x * v.y;
|
||||
v.w += v.y * v.z;
|
||||
vector4 f = int4_to_vec4(v & 0x7FFFFFFF);
|
||||
return f * (1.0 / (float)0x7FFFFFFF);
|
||||
}
|
||||
|
||||
color hash_int2_to_color(int2 k)
|
||||
{
|
||||
return hash_int3_to_vector3(int3(k.x, k.y, 0));
|
||||
}
|
||||
|
||||
color hash_int4_to_color(int4 k)
|
||||
{
|
||||
vector4 v = hash_int4_to_vector4(k);
|
||||
return color(v.x, v.y, v.z);
|
||||
}
|
||||
|
||||
/* **** Hash a float or vector[234] into a float [0, 1] **** */
|
||||
|
||||
float hash_float_to_float(float k)
|
||||
{
|
||||
return hashnoise(k);
|
||||
}
|
||||
|
||||
float hash_vector2_to_float(vector2 k)
|
||||
{
|
||||
return hashnoise(k.x, k.y);
|
||||
}
|
||||
|
||||
float hash_vector3_to_float(vector3 k)
|
||||
{
|
||||
return hashnoise(k);
|
||||
}
|
||||
|
||||
float hash_vector4_to_float(vector4 k)
|
||||
{
|
||||
return hashnoise(vector3(k.x, k.y, k.z), k.w);
|
||||
}
|
||||
|
||||
/* **** Hash a vector[234] into a vector[234] [0, 1] **** */
|
||||
|
||||
vector2 hash_vector2_to_vector2(vector2 k)
|
||||
{
|
||||
return vector2(hash_vector2_to_float(k), hash_vector3_to_float(vector3(k.x, k.y, 1.0)));
|
||||
}
|
||||
|
||||
vector3 hash_vector3_to_vector3(vector3 k)
|
||||
{
|
||||
return vector3(hash_vector3_to_float(k),
|
||||
hash_vector4_to_float(vector4(k[0], k[1], k[2], 1.0)),
|
||||
hash_vector4_to_float(vector4(k[0], k[1], k[2], 2.0)));
|
||||
}
|
||||
|
||||
vector4 hash_vector4_to_vector4(vector4 k)
|
||||
{
|
||||
return vector4(hash_vector4_to_float(k),
|
||||
hash_vector4_to_float(vector4(k.w, k.x, k.y, k.z)),
|
||||
hash_vector4_to_float(vector4(k.z, k.w, k.x, k.y)),
|
||||
hash_vector4_to_float(vector4(k.y, k.z, k.w, k.x)));
|
||||
}
|
||||
|
||||
/* **** Hash a float or a vec[234] into a color [0, 1] **** */
|
||||
|
||||
color hash_float_to_color(float k)
|
||||
{
|
||||
return color(hash_float_to_float(k),
|
||||
hash_vector2_to_float(vector2(k, 1.0)),
|
||||
hash_vector2_to_float(vector2(k, 2.0)));
|
||||
}
|
||||
|
||||
color hash_vector2_to_color(vector2 k)
|
||||
{
|
||||
return color(hash_vector2_to_float(k),
|
||||
hash_vector3_to_float(vector3(k.x, k.y, 1.0)),
|
||||
hash_vector3_to_float(vector3(k.x, k.y, 2.0)));
|
||||
}
|
||||
|
||||
color hash_vector3_to_color(vector3 k)
|
||||
{
|
||||
return color(hash_vector3_to_float(k),
|
||||
hash_vector4_to_float(vector4(k[0], k[1], k[2], 1.0)),
|
||||
hash_vector4_to_float(vector4(k[0], k[1], k[2], 2.0)));
|
||||
}
|
||||
|
||||
color hash_vector4_to_color(vector4 k)
|
||||
{
|
||||
return color(hash_vector4_to_float(k),
|
||||
hash_vector4_to_float(vector4(k.z, k.x, k.w, k.y)),
|
||||
hash_vector4_to_float(vector4(k.w, k.z, k.y, k.x)));
|
||||
}
|
||||
|
||||
/* **** Hash a float or a vec[234] into a vector3 [0, 1] **** */
|
||||
|
||||
vector3 hash_float_to_vector3(float k)
|
||||
{
|
||||
return vector3(hash_float_to_float(k),
|
||||
hash_vector2_to_float(vector2(k, 1.0)),
|
||||
hash_vector2_to_float(vector2(k, 2.0)));
|
||||
}
|
||||
|
||||
vector3 hash_vector2_to_vector3(vector2 k)
|
||||
{
|
||||
return vector3(hash_vector2_to_float(k),
|
||||
hash_vector3_to_float(vector3(k.x, k.y, 1.0)),
|
||||
hash_vector3_to_float(vector3(k.x, k.y, 2.0)));
|
||||
}
|
||||
|
||||
vector3 hash_vector4_to_vector3(vector4 k)
|
||||
{
|
||||
return vector3(hash_vector4_to_float(k),
|
||||
hash_vector4_to_float(vector4(k.z, k.x, k.w, k.y)),
|
||||
hash_vector4_to_float(vector4(k.w, k.z, k.y, k.x)));
|
||||
}
|
||||
|
||||
/* Hashing float or vector[234] into vector2 of components in range [0, 1]. */
|
||||
|
||||
vector2 hash_float_to_vector2(float k)
|
||||
{
|
||||
return vector2(hash_float_to_float(k), hash_vector2_to_float(vector2(k, 1.0)));
|
||||
}
|
||||
|
||||
vector2 hash_vector3_to_vector2(vector3 k)
|
||||
{
|
||||
return vector2(hash_vector3_to_float(vector3(k.x, k.y, k.z)),
|
||||
hash_vector3_to_float(vector3(k.z, k.x, k.y)));
|
||||
}
|
||||
|
||||
vector2 hash_vector4_to_vector2(vector4 k)
|
||||
{
|
||||
return vector2(hash_vector4_to_float(vector4(k.x, k.y, k.z, k.w)),
|
||||
hash_vector4_to_float(vector4(k.z, k.x, k.w, k.y)));
|
||||
}
|
||||
|
||||
#undef vector3
|
||||
@@ -0,0 +1,7 @@
|
||||
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 */
|
||||
|
||||
#include "stdcycles.h"
|
||||
|
||||
shader node_holdout(output closure color Holdout = holdout()) {}
|
||||
30
blender-5.2.0/intern/cycles/kernel/osl/shaders/node_hsv.osl
Normal file
30
blender-5.2.0/intern/cycles/kernel/osl/shaders/node_hsv.osl
Normal file
@@ -0,0 +1,30 @@
|
||||
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 */
|
||||
|
||||
#include "node_color.h"
|
||||
#include "node_math.h"
|
||||
#include "stdcycles.h"
|
||||
|
||||
shader node_hsv(float Hue = 0.5,
|
||||
float Saturation = 1.0,
|
||||
float Value = 1.0,
|
||||
float Fac = 0.5,
|
||||
color ColorIn = 0.0,
|
||||
output color ColorOut = 0.0)
|
||||
{
|
||||
color Color = rgb_to_hsv(ColorIn);
|
||||
|
||||
Color[0] = fract(Color[0] + Hue + 0.5);
|
||||
Color[1] = clamp(Color[1] * Saturation, 0.0, 1.0);
|
||||
Color[2] *= Value;
|
||||
|
||||
Color = hsv_to_rgb(Color);
|
||||
|
||||
// Clamp color to prevent negative values cauzed by oversaturation.
|
||||
Color[0] = max(Color[0], 0.0);
|
||||
Color[1] = max(Color[1], 0.0);
|
||||
Color[2] = max(Color[2], 0.0);
|
||||
|
||||
ColorOut = mix(ColorIn, Color, Fac);
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 */
|
||||
|
||||
#include "stdcycles.h"
|
||||
|
||||
/* IES Light */
|
||||
|
||||
shader node_ies_light(int use_mapping = 0,
|
||||
matrix mapping = matrix(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
|
||||
string filename = "",
|
||||
float Strength = 1.0,
|
||||
point Vector = I,
|
||||
output float Fac = 0.0)
|
||||
{
|
||||
point p = Vector;
|
||||
|
||||
if (use_mapping) {
|
||||
p = transform(mapping, p);
|
||||
}
|
||||
|
||||
p = normalize((vector)p);
|
||||
|
||||
float v_angle = acos(-p[2]);
|
||||
float h_angle = atan2(p[0], p[1]) + M_PI;
|
||||
|
||||
Fac = Strength * texture(filename, h_angle, v_angle);
|
||||
}
|
||||
@@ -0,0 +1,245 @@
|
||||
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 */
|
||||
|
||||
#include "node_color.h"
|
||||
#include "stdcycles.h"
|
||||
|
||||
point texco_remap_square(point co)
|
||||
{
|
||||
return (co - point(0.5, 0.5, 0.5)) * 2.0;
|
||||
}
|
||||
|
||||
point map_to_tube(vector dir)
|
||||
{
|
||||
float u, v;
|
||||
v = (dir[2] + 1.0) * 0.5;
|
||||
float len = sqrt(dir[0] * dir[0] + dir[1] * dir[1]);
|
||||
if (len > 0.0) {
|
||||
u = (1.0 - (atan2(dir[0] / len, dir[1] / len) / M_PI)) * 0.5;
|
||||
}
|
||||
else {
|
||||
v = u = 0.0; /* To avoid un-initialized variables. */
|
||||
}
|
||||
return point(u, v, 0.0);
|
||||
}
|
||||
|
||||
point map_to_sphere(vector dir)
|
||||
{
|
||||
float len = length(dir);
|
||||
float v, u;
|
||||
if (len > 0.0) {
|
||||
if (dir[0] == 0.0 && dir[1] == 0.0) {
|
||||
u = 0.0; /* Otherwise domain error. */
|
||||
}
|
||||
else {
|
||||
u = (1.0 - atan2(dir[0], dir[1]) / M_PI) / 2.0;
|
||||
}
|
||||
v = 1.0 - acos(dir[2] / len) / M_PI;
|
||||
}
|
||||
else {
|
||||
v = u = 0.0; /* To avoid un-initialized variables. */
|
||||
}
|
||||
return point(u, v, 0.0);
|
||||
}
|
||||
|
||||
color image_texture_lookup(string filename,
|
||||
float u,
|
||||
float v,
|
||||
output float Alpha,
|
||||
int compress_as_srgb,
|
||||
int ignore_alpha,
|
||||
int unassociate_alpha,
|
||||
int is_float,
|
||||
string interpolation,
|
||||
string extension)
|
||||
{
|
||||
color rgb = (color)texture(
|
||||
filename, u, v, "wrap", extension, "interp", interpolation, "alpha", Alpha);
|
||||
|
||||
if (ignore_alpha) {
|
||||
Alpha = 1.0;
|
||||
}
|
||||
else if (unassociate_alpha) {
|
||||
rgb = color_unpremultiply(rgb, Alpha);
|
||||
|
||||
if (!is_float)
|
||||
rgb = min(rgb, 1.0);
|
||||
}
|
||||
|
||||
if (compress_as_srgb) {
|
||||
rgb = color_srgb_to_scene_linear(rgb);
|
||||
}
|
||||
|
||||
return rgb;
|
||||
}
|
||||
|
||||
shader node_image_texture(int use_mapping = 0,
|
||||
matrix mapping = matrix(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
|
||||
point Vector = P,
|
||||
string filename = "",
|
||||
string projection = "flat",
|
||||
string interpolation = "smartcubic",
|
||||
string extension = "periodic",
|
||||
float projection_blend = 0.0,
|
||||
int compress_as_srgb = 0,
|
||||
int ignore_alpha = 0,
|
||||
int unassociate_alpha = 0,
|
||||
int is_float = 1,
|
||||
output color Color = 0.0,
|
||||
output float Alpha = 1.0)
|
||||
{
|
||||
point p = Vector;
|
||||
|
||||
if (use_mapping)
|
||||
p = transform(mapping, p);
|
||||
|
||||
if (projection == "flat") {
|
||||
Color = image_texture_lookup(filename,
|
||||
p[0],
|
||||
p[1],
|
||||
Alpha,
|
||||
compress_as_srgb,
|
||||
ignore_alpha,
|
||||
unassociate_alpha,
|
||||
is_float,
|
||||
interpolation,
|
||||
extension);
|
||||
}
|
||||
else if (projection == "box") {
|
||||
/* object space normal */
|
||||
vector Nob = transform("world", "object", N);
|
||||
|
||||
/* project from direction vector to barycentric coordinates in triangles */
|
||||
vector signed_Nob = Nob;
|
||||
Nob = vector(fabs(Nob[0]), fabs(Nob[1]), fabs(Nob[2]));
|
||||
Nob /= (Nob[0] + Nob[1] + Nob[2]);
|
||||
|
||||
/* basic idea is to think of this as a triangle, each corner representing
|
||||
* one of the 3 faces of the cube. in the corners we have single textures,
|
||||
* in between we blend between two textures, and in the middle we a blend
|
||||
* between three textures.
|
||||
*
|
||||
* the `Nxyz` values are the barycentric coordinates in an equilateral
|
||||
* triangle, which in case of blending, in the middle has a smaller
|
||||
* equilateral triangle where 3 textures blend. this divides things into
|
||||
* 7 zones, with an if () test for each zone. */
|
||||
|
||||
vector weight = vector(0.0, 0.0, 0.0);
|
||||
float blend = projection_blend;
|
||||
float limit = 0.5 * (1.0 + blend);
|
||||
|
||||
/* first test for corners with single texture */
|
||||
if (Nob[0] > limit * (Nob[0] + Nob[1]) && Nob[0] > limit * (Nob[0] + Nob[2])) {
|
||||
weight[0] = 1.0;
|
||||
}
|
||||
else if (Nob[1] > limit * (Nob[0] + Nob[1]) && Nob[1] > limit * (Nob[1] + Nob[2])) {
|
||||
weight[1] = 1.0;
|
||||
}
|
||||
else if (Nob[2] > limit * (Nob[0] + Nob[2]) && Nob[2] > limit * (Nob[1] + Nob[2])) {
|
||||
weight[2] = 1.0;
|
||||
}
|
||||
else if (blend > 0.0) {
|
||||
/* in case of blending, test for mixes between two textures */
|
||||
if (Nob[2] < (1.0 - limit) * (Nob[1] + Nob[0])) {
|
||||
weight[0] = Nob[0] / (Nob[0] + Nob[1]);
|
||||
weight[0] = clamp((weight[0] - 0.5 * (1.0 - blend)) / blend, 0.0, 1.0);
|
||||
weight[1] = 1.0 - weight[0];
|
||||
}
|
||||
else if (Nob[0] < (1.0 - limit) * (Nob[1] + Nob[2])) {
|
||||
weight[1] = Nob[1] / (Nob[1] + Nob[2]);
|
||||
weight[1] = clamp((weight[1] - 0.5 * (1.0 - blend)) / blend, 0.0, 1.0);
|
||||
weight[2] = 1.0 - weight[1];
|
||||
}
|
||||
else if (Nob[1] < (1.0 - limit) * (Nob[0] + Nob[2])) {
|
||||
weight[0] = Nob[0] / (Nob[0] + Nob[2]);
|
||||
weight[0] = clamp((weight[0] - 0.5 * (1.0 - blend)) / blend, 0.0, 1.0);
|
||||
weight[2] = 1.0 - weight[0];
|
||||
}
|
||||
else {
|
||||
/* last case, we have a mix between three */
|
||||
weight[0] = ((2.0 - limit) * Nob[0] + (limit - 1.0)) / (2.0 * limit - 1.0);
|
||||
weight[1] = ((2.0 - limit) * Nob[1] + (limit - 1.0)) / (2.0 * limit - 1.0);
|
||||
weight[2] = ((2.0 - limit) * Nob[2] + (limit - 1.0)) / (2.0 * limit - 1.0);
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* Desperate mode, no valid choice anyway, fall back to one side. */
|
||||
weight[0] = 1.0;
|
||||
}
|
||||
|
||||
Color = color(0.0, 0.0, 0.0);
|
||||
Alpha = 0.0;
|
||||
|
||||
float tmp_alpha;
|
||||
|
||||
if (weight[0] > 0.0) {
|
||||
point UV = point((signed_Nob[0] < 0.0) ? 1.0 - p[1] : p[1], p[2], 0.0);
|
||||
Color += weight[0] * image_texture_lookup(filename,
|
||||
UV[0],
|
||||
UV[1],
|
||||
tmp_alpha,
|
||||
compress_as_srgb,
|
||||
ignore_alpha,
|
||||
unassociate_alpha,
|
||||
is_float,
|
||||
interpolation,
|
||||
extension);
|
||||
Alpha += weight[0] * tmp_alpha;
|
||||
}
|
||||
if (weight[1] > 0.0) {
|
||||
point UV = point((signed_Nob[1] > 0.0) ? 1.0 - p[0] : p[0], p[2], 0.0);
|
||||
Color += weight[1] * image_texture_lookup(filename,
|
||||
UV[0],
|
||||
UV[1],
|
||||
tmp_alpha,
|
||||
compress_as_srgb,
|
||||
ignore_alpha,
|
||||
unassociate_alpha,
|
||||
is_float,
|
||||
interpolation,
|
||||
extension);
|
||||
Alpha += weight[1] * tmp_alpha;
|
||||
}
|
||||
if (weight[2] > 0.0) {
|
||||
point UV = point((signed_Nob[2] > 0.0) ? 1.0 - p[1] : p[1], p[0], 0.0);
|
||||
Color += weight[2] * image_texture_lookup(filename,
|
||||
UV[0],
|
||||
UV[1],
|
||||
tmp_alpha,
|
||||
compress_as_srgb,
|
||||
ignore_alpha,
|
||||
unassociate_alpha,
|
||||
is_float,
|
||||
interpolation,
|
||||
extension);
|
||||
Alpha += weight[2] * tmp_alpha;
|
||||
}
|
||||
}
|
||||
else if (projection == "sphere") {
|
||||
point projected = map_to_sphere(texco_remap_square(p));
|
||||
Color = image_texture_lookup(filename,
|
||||
projected[0],
|
||||
projected[1],
|
||||
Alpha,
|
||||
compress_as_srgb,
|
||||
ignore_alpha,
|
||||
unassociate_alpha,
|
||||
is_float,
|
||||
interpolation,
|
||||
extension);
|
||||
}
|
||||
else if (projection == "tube") {
|
||||
point projected = map_to_tube(texco_remap_square(p));
|
||||
Color = image_texture_lookup(filename,
|
||||
projected[0],
|
||||
projected[1],
|
||||
Alpha,
|
||||
compress_as_srgb,
|
||||
ignore_alpha,
|
||||
unassociate_alpha,
|
||||
is_float,
|
||||
interpolation,
|
||||
extension);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 */
|
||||
|
||||
#include "stdcycles.h"
|
||||
|
||||
shader node_invert(float Fac = 1.0, color ColorIn = 0.8, output color ColorOut = 0.8)
|
||||
{
|
||||
color ColorInv = color(1.0) - ColorIn;
|
||||
ColorOut = mix(ColorIn, ColorInv, Fac);
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 */
|
||||
|
||||
#include "node_fresnel.h"
|
||||
#include "stdcycles.h"
|
||||
|
||||
shader node_layer_weight(float Blend = 0.5,
|
||||
normal Normal = N,
|
||||
output float Fresnel = 0.0,
|
||||
output float Facing = 0.0)
|
||||
{
|
||||
float blend = Blend;
|
||||
float cosi = dot(I, Normal);
|
||||
|
||||
/* Fresnel */
|
||||
float eta = max(1.0 - Blend, 1e-5);
|
||||
eta = backfacing() ? eta : 1.0 / eta;
|
||||
Fresnel = fresnel_dielectric_cos(cosi, eta);
|
||||
|
||||
/* Facing */
|
||||
Facing = fabs(cosi);
|
||||
|
||||
if (blend != 0.5) {
|
||||
blend = clamp(blend, 0.0, 1.0 - 1e-5);
|
||||
blend = (blend < 0.5) ? 2.0 * blend : 0.5 / (1.0 - blend);
|
||||
|
||||
Facing = pow(Facing, blend);
|
||||
}
|
||||
|
||||
Facing = 1.0 - Facing;
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 */
|
||||
|
||||
#include "stdcycles.h"
|
||||
|
||||
shader node_light_falloff(float Strength = 0.0,
|
||||
float Smooth = 0.0,
|
||||
output float Quadratic = 0.0,
|
||||
output float Linear = 0.0,
|
||||
output float Constant = 0.0)
|
||||
{
|
||||
float ray_length = 0.0;
|
||||
float strength = Strength;
|
||||
getattribute("path:ray_length", ray_length);
|
||||
|
||||
if (ray_length == FLT_MAX) {
|
||||
/* Distant lights (which have a ray_length of FLT_MAX) overflow when using most outputs of
|
||||
* the light falloff node. So just ignore the node in that case. */
|
||||
Quadratic = strength;
|
||||
Linear = strength;
|
||||
Constant = strength;
|
||||
}
|
||||
else {
|
||||
if (Smooth > 0.0) {
|
||||
float squared = ray_length * ray_length;
|
||||
strength *= squared / (Smooth + squared);
|
||||
}
|
||||
|
||||
Quadratic = strength;
|
||||
Linear = (strength * ray_length);
|
||||
Constant = (strength * ray_length * ray_length);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 */
|
||||
|
||||
#include "stdcycles.h"
|
||||
|
||||
shader node_light_path(output float IsCameraRay = 0.0,
|
||||
output float IsShadowRay = 0.0,
|
||||
output float IsDiffuseRay = 0.0,
|
||||
output float IsGlossyRay = 0.0,
|
||||
output float IsSingularRay = 0.0,
|
||||
output float IsReflectionRay = 0.0,
|
||||
output float IsTransmissionRay = 0.0,
|
||||
output float IsVolumeScatterRay = 0.0,
|
||||
output float RayLength = 0.0,
|
||||
output float RayDepth = 0.0,
|
||||
output float DiffuseDepth = 0.0,
|
||||
output float GlossyDepth = 0.0,
|
||||
output float TransparentDepth = 0.0,
|
||||
output float TransmissionDepth = 0.0,
|
||||
output float PortalDepth = 0.0)
|
||||
{
|
||||
IsCameraRay = raytype("camera");
|
||||
IsShadowRay = raytype("shadow");
|
||||
IsDiffuseRay = raytype("diffuse");
|
||||
IsGlossyRay = raytype("glossy");
|
||||
IsSingularRay = raytype("singular");
|
||||
IsReflectionRay = raytype("reflection");
|
||||
IsTransmissionRay = raytype("refraction");
|
||||
IsVolumeScatterRay = raytype("volume_scatter");
|
||||
|
||||
getattribute("path:ray_length", RayLength);
|
||||
|
||||
int ray_depth = 0;
|
||||
getattribute("path:ray_depth", ray_depth);
|
||||
RayDepth = (float)ray_depth;
|
||||
|
||||
int diffuse_depth = 0;
|
||||
getattribute("path:diffuse_depth", diffuse_depth);
|
||||
DiffuseDepth = (float)diffuse_depth;
|
||||
|
||||
int glossy_depth = 0;
|
||||
getattribute("path:glossy_depth", glossy_depth);
|
||||
GlossyDepth = (float)glossy_depth;
|
||||
|
||||
int transparent_depth = 0;
|
||||
getattribute("path:transparent_depth", transparent_depth);
|
||||
TransparentDepth = (float)transparent_depth;
|
||||
|
||||
int transmission_depth = 0;
|
||||
getattribute("path:transmission_depth", transmission_depth);
|
||||
TransmissionDepth = (float)transmission_depth;
|
||||
|
||||
int portal_depth = 0;
|
||||
getattribute("path:portal_depth", portal_depth);
|
||||
PortalDepth = (float)portal_depth;
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 */
|
||||
|
||||
#include "stdcycles.h"
|
||||
|
||||
/* Magic */
|
||||
color magic(point p, float scale, int n, float distortion)
|
||||
{
|
||||
float dist = distortion;
|
||||
|
||||
float a = mod(p.x * scale, M_2PI);
|
||||
float b = mod(p.y * scale, M_2PI);
|
||||
float c = mod(p.z * scale, M_2PI);
|
||||
|
||||
float x = sin((a + b + c) * 5.0);
|
||||
float y = cos((-a + b - c) * 5.0);
|
||||
float z = -cos((-a - b + c) * 5.0);
|
||||
|
||||
if (n > 0) {
|
||||
x *= dist;
|
||||
y *= dist;
|
||||
z *= dist;
|
||||
y = -cos(x - y + z);
|
||||
y *= dist;
|
||||
|
||||
if (n > 1) {
|
||||
x = cos(x - y - z);
|
||||
x *= dist;
|
||||
|
||||
if (n > 2) {
|
||||
z = sin(-x - y - z);
|
||||
z *= dist;
|
||||
|
||||
if (n > 3) {
|
||||
x = -cos(-x + y - z);
|
||||
x *= dist;
|
||||
|
||||
if (n > 4) {
|
||||
y = -sin(-x + y + z);
|
||||
y *= dist;
|
||||
|
||||
if (n > 5) {
|
||||
y = -cos(-x + y + z);
|
||||
y *= dist;
|
||||
|
||||
if (n > 6) {
|
||||
x = cos(x + y + z);
|
||||
x *= dist;
|
||||
|
||||
if (n > 7) {
|
||||
z = sin(x + y - z);
|
||||
z *= dist;
|
||||
|
||||
if (n > 8) {
|
||||
x = -cos(-x - y + z);
|
||||
x *= dist;
|
||||
|
||||
if (n > 9) {
|
||||
y = -sin(x - y + z);
|
||||
y *= dist;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (dist != 0.0) {
|
||||
dist *= 2.0;
|
||||
x /= dist;
|
||||
y /= dist;
|
||||
z /= dist;
|
||||
}
|
||||
|
||||
return color(0.5 - x, 0.5 - y, 0.5 - z);
|
||||
}
|
||||
|
||||
shader node_magic_texture(int use_mapping = 0,
|
||||
matrix mapping = matrix(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
|
||||
int depth = 2,
|
||||
float Distortion = 5.0,
|
||||
float Scale = 5.0,
|
||||
point Vector = P,
|
||||
output float Fac = 0.0,
|
||||
output color Color = 0.0)
|
||||
{
|
||||
point p = Vector;
|
||||
|
||||
if (use_mapping)
|
||||
p = transform(mapping, p);
|
||||
|
||||
Color = magic(p, Scale, depth, Distortion);
|
||||
Fac = (Color[0] + Color[1] + Color[2]) * (1.0 / 3.0);
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 */
|
||||
|
||||
#include "stdcycles.h"
|
||||
|
||||
float safe_divide(float a, float b)
|
||||
{
|
||||
return (b != 0.0) ? a / b : 0.0;
|
||||
}
|
||||
|
||||
float smootherstep(float edge0, float edge1, float x)
|
||||
{
|
||||
float t = clamp(safe_divide((x - edge0), (edge1 - edge0)), 0.0, 1.0);
|
||||
return t * t * t * (t * (t * 6.0 - 15.0) + 10.0);
|
||||
}
|
||||
|
||||
shader node_map_range(string range_type = "linear",
|
||||
float Value = 1.0,
|
||||
float FromMin = 0.0,
|
||||
float FromMax = 1.0,
|
||||
float ToMin = 0.0,
|
||||
float ToMax = 1.0,
|
||||
float Steps = 4.0,
|
||||
output float Result = 0.0)
|
||||
{
|
||||
if (FromMax != FromMin) {
|
||||
float Factor = Value;
|
||||
if (range_type == "stepped") {
|
||||
Factor = (Value - FromMin) / (FromMax - FromMin);
|
||||
Factor = (Steps > 0) ? floor(Factor * (Steps + 1.0)) / Steps : 0.0;
|
||||
}
|
||||
else if (range_type == "smoothstep") {
|
||||
Factor = (FromMin > FromMax) ? 1.0 - smoothstep(FromMax, FromMin, Value) :
|
||||
smoothstep(FromMin, FromMax, Value);
|
||||
}
|
||||
else if (range_type == "smootherstep") {
|
||||
Factor = (FromMin > FromMax) ? 1.0 - smootherstep(FromMax, FromMin, Value) :
|
||||
smootherstep(FromMin, FromMax, Value);
|
||||
}
|
||||
else {
|
||||
Factor = (Value - FromMin) / (FromMax - FromMin);
|
||||
}
|
||||
Result = ToMin + Factor * (ToMax - ToMin);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 */
|
||||
|
||||
#include "stdcycles.h"
|
||||
|
||||
point safe_divide(point a, point b)
|
||||
{
|
||||
return point((b[0] != 0.0) ? a[0] / b[0] : 0.0,
|
||||
(b[1] != 0.0) ? a[1] / b[1] : 0.0,
|
||||
(b[2] != 0.0) ? a[2] / b[2] : 0.0);
|
||||
}
|
||||
|
||||
matrix euler_to_mat(point euler)
|
||||
{
|
||||
float cx = cos(euler[0]);
|
||||
float cy = cos(euler[1]);
|
||||
float cz = cos(euler[2]);
|
||||
float sx = sin(euler[0]);
|
||||
float sy = sin(euler[1]);
|
||||
float sz = sin(euler[2]);
|
||||
|
||||
matrix mat = matrix(1.0);
|
||||
mat[0][0] = cy * cz;
|
||||
mat[0][1] = cy * sz;
|
||||
mat[0][2] = -sy;
|
||||
|
||||
mat[1][0] = sy * sx * cz - cx * sz;
|
||||
mat[1][1] = sy * sx * sz + cx * cz;
|
||||
mat[1][2] = cy * sx;
|
||||
|
||||
mat[2][0] = sy * cx * cz + sx * sz;
|
||||
mat[2][1] = sy * cx * sz - sx * cz;
|
||||
mat[2][2] = cy * cx;
|
||||
return mat;
|
||||
}
|
||||
|
||||
shader node_mapping(string mapping_type = "point",
|
||||
point VectorIn = point(0.0, 0.0, 0.0),
|
||||
point Location = point(0.0, 0.0, 0.0),
|
||||
point Rotation = point(0.0, 0.0, 0.0),
|
||||
point Scale = point(1.0, 1.0, 1.0),
|
||||
output point VectorOut = point(0.0, 0.0, 0.0))
|
||||
{
|
||||
if (mapping_type == "point") {
|
||||
VectorOut = transform(euler_to_mat(Rotation), (VectorIn * Scale)) + Location;
|
||||
}
|
||||
else if (mapping_type == "texture") {
|
||||
VectorOut = safe_divide(transform(transpose(euler_to_mat(Rotation)), (VectorIn - Location)),
|
||||
Scale);
|
||||
}
|
||||
else if (mapping_type == "vector") {
|
||||
VectorOut = transform(euler_to_mat(Rotation), (VectorIn * Scale));
|
||||
}
|
||||
else if (mapping_type == "normal") {
|
||||
VectorOut = normalize((vector)transform(euler_to_mat(Rotation), safe_divide(VectorIn, Scale)));
|
||||
}
|
||||
else {
|
||||
warning("%s", "Unknown Mapping vector type!");
|
||||
}
|
||||
}
|
||||
147
blender-5.2.0/intern/cycles/kernel/osl/shaders/node_math.h
Normal file
147
blender-5.2.0/intern/cycles/kernel/osl/shaders/node_math.h
Normal file
@@ -0,0 +1,147 @@
|
||||
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 */
|
||||
|
||||
#include "vector2.h"
|
||||
#include "vector4.h"
|
||||
|
||||
#define vector3 point
|
||||
|
||||
float safe_divide(float a, float b)
|
||||
{
|
||||
return (b != 0.0) ? a / b : 0.0;
|
||||
}
|
||||
|
||||
vector safe_divide(vector a, vector b)
|
||||
{
|
||||
return vector((b[0] != 0.0) ? a[0] / b[0] : 0.0,
|
||||
(b[1] != 0.0) ? a[1] / b[1] : 0.0,
|
||||
(b[2] != 0.0) ? a[2] / b[2] : 0.0);
|
||||
}
|
||||
|
||||
float safe_modulo(float a, float b)
|
||||
{
|
||||
return (b != 0.0) ? fmod(a, b) : 0.0;
|
||||
}
|
||||
|
||||
float safe_floored_modulo(float a, float b)
|
||||
{
|
||||
return (b != 0.0) ? a - floor(a / b) * b : 0.0;
|
||||
}
|
||||
|
||||
float sqr(float a)
|
||||
{
|
||||
return a * a;
|
||||
}
|
||||
|
||||
/* The float and vector3 overloads are already defined in stdosl.h.
|
||||
*
|
||||
* float round(float a)
|
||||
* {
|
||||
* return floor(a + 0.5);
|
||||
* }
|
||||
*
|
||||
* vector3 round(vector3 a)
|
||||
* {
|
||||
* return vector3(floor(a.x + 0.5), floor(a.y + 0.5), floor(a.z + 0.5));
|
||||
* } */
|
||||
|
||||
vector2 round(vector2 a)
|
||||
{
|
||||
return vector2(floor(a.x + 0.5), floor(a.y + 0.5));
|
||||
}
|
||||
|
||||
vector4 round(vector4 a)
|
||||
{
|
||||
return vector4(floor(a.x + 0.5), floor(a.y + 0.5), floor(a.z + 0.5), floor(a.w + 0.5));
|
||||
}
|
||||
|
||||
float fract(float a)
|
||||
{
|
||||
return a - floor(a);
|
||||
}
|
||||
|
||||
/* See: https://www.iquilezles.org/www/articles/smin/smin.htm. */
|
||||
float smoothmin(float a, float b, float c)
|
||||
{
|
||||
if (c != 0.0) {
|
||||
float h = max(c - abs(a - b), 0.0) / c;
|
||||
return min(a, b) - h * h * h * c * (1.0 / 6.0);
|
||||
}
|
||||
else {
|
||||
return min(a, b);
|
||||
}
|
||||
}
|
||||
|
||||
float pingpong(float a, float b)
|
||||
{
|
||||
return (b != 0.0) ? abs(fract((a - b) / (b * 2.0)) * b * 2.0 - b) : 0.0;
|
||||
}
|
||||
|
||||
float safe_sqrt(float a)
|
||||
{
|
||||
return (a > 0.0) ? sqrt(a) : 0.0;
|
||||
}
|
||||
|
||||
float safe_log(float a, float b)
|
||||
{
|
||||
return (a > 0.0 && b > 0.0) ? log(a) / log(b) : 0.0;
|
||||
}
|
||||
|
||||
vector project(vector v, vector v_proj)
|
||||
{
|
||||
float lenSquared = dot(v_proj, v_proj);
|
||||
return (lenSquared != 0.0) ? (dot(v, v_proj) / lenSquared) * v_proj : vector(0.0);
|
||||
}
|
||||
|
||||
vector snap(vector a, vector b)
|
||||
{
|
||||
return floor(safe_divide(a, b)) * b;
|
||||
}
|
||||
|
||||
/* Adapted from GODOT-engine math_funcs.h. */
|
||||
float wrap(float value, float max, float min)
|
||||
{
|
||||
float range = max - min;
|
||||
return (range != 0.0) ? value - (range * floor((value - min) / range)) : min;
|
||||
}
|
||||
|
||||
point wrap(point value, point max, point min)
|
||||
{
|
||||
return point(wrap(value[0], max[0], min[0]),
|
||||
wrap(value[1], max[1], min[1]),
|
||||
wrap(value[2], max[2], min[2]));
|
||||
}
|
||||
|
||||
/* Built in OSL faceforward is `(dot(I, Nref) > 0) ? -N : N;` which is different to
|
||||
* GLSL `dot(Nref, I) < 0 ? N : -N` for zero values. */
|
||||
point compatible_faceforward(point vec, point incident, point reference)
|
||||
{
|
||||
return dot(reference, incident) < 0.0 ? vec : -vec;
|
||||
}
|
||||
|
||||
matrix euler_to_mat(point euler)
|
||||
{
|
||||
float cx = cos(euler[0]);
|
||||
float cy = cos(euler[1]);
|
||||
float cz = cos(euler[2]);
|
||||
float sx = sin(euler[0]);
|
||||
float sy = sin(euler[1]);
|
||||
float sz = sin(euler[2]);
|
||||
matrix mat = matrix(1.0);
|
||||
mat[0][0] = cy * cz;
|
||||
mat[0][1] = cy * sz;
|
||||
mat[0][2] = -sy;
|
||||
mat[1][0] = sy * sx * cz - cx * sz;
|
||||
mat[1][1] = sy * sx * sz + cx * cz;
|
||||
mat[1][2] = cy * sx;
|
||||
+mat[2][0] = sy * cx * cz + sx * sz;
|
||||
mat[2][1] = sy * cx * sz - sx * cz;
|
||||
mat[2][2] = cy * cx;
|
||||
return mat;
|
||||
}
|
||||
|
||||
float average(point a)
|
||||
{
|
||||
return (a[0] + a[1] + a[2]) * (1.0 / 3.0);
|
||||
}
|
||||
99
blender-5.2.0/intern/cycles/kernel/osl/shaders/node_math.osl
Normal file
99
blender-5.2.0/intern/cycles/kernel/osl/shaders/node_math.osl
Normal file
@@ -0,0 +1,99 @@
|
||||
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 */
|
||||
|
||||
#include "node_math.h"
|
||||
#include "stdcycles.h"
|
||||
|
||||
/* OSL asin, acos, and pow functions are safe by default. */
|
||||
shader node_math(string math_type = "add",
|
||||
float Value1 = 0.5,
|
||||
float Value2 = 0.5,
|
||||
float Value3 = 0.5,
|
||||
output float Value = 0.0)
|
||||
{
|
||||
if (math_type == "add")
|
||||
Value = Value1 + Value2;
|
||||
else if (math_type == "subtract")
|
||||
Value = Value1 - Value2;
|
||||
else if (math_type == "multiply")
|
||||
Value = Value1 * Value2;
|
||||
else if (math_type == "divide")
|
||||
Value = safe_divide(Value1, Value2);
|
||||
else if (math_type == "power")
|
||||
Value = pow(Value1, Value2);
|
||||
else if (math_type == "logarithm")
|
||||
Value = safe_log(Value1, Value2);
|
||||
else if (math_type == "sqrt")
|
||||
Value = safe_sqrt(Value1);
|
||||
else if (math_type == "inversesqrt")
|
||||
Value = inversesqrt(Value1);
|
||||
else if (math_type == "absolute")
|
||||
Value = fabs(Value1);
|
||||
else if (math_type == "radians")
|
||||
Value = radians(Value1);
|
||||
else if (math_type == "degrees")
|
||||
Value = degrees(Value1);
|
||||
else if (math_type == "minimum")
|
||||
Value = min(Value1, Value2);
|
||||
else if (math_type == "maximum")
|
||||
Value = max(Value1, Value2);
|
||||
else if (math_type == "less_than")
|
||||
Value = Value1 < Value2;
|
||||
else if (math_type == "greater_than")
|
||||
Value = Value1 > Value2;
|
||||
else if (math_type == "round")
|
||||
Value = floor(Value1 + 0.5);
|
||||
else if (math_type == "floor")
|
||||
Value = floor(Value1);
|
||||
else if (math_type == "ceil")
|
||||
Value = ceil(Value1);
|
||||
else if (math_type == "fraction")
|
||||
Value = Value1 - floor(Value1);
|
||||
else if (math_type == "modulo")
|
||||
Value = safe_modulo(Value1, Value2);
|
||||
else if (math_type == "floored_modulo")
|
||||
Value = safe_floored_modulo(Value1, Value2);
|
||||
else if (math_type == "trunc")
|
||||
Value = trunc(Value1);
|
||||
else if (math_type == "snap")
|
||||
Value = floor(safe_divide(Value1, Value2)) * Value2;
|
||||
else if (math_type == "wrap")
|
||||
Value = wrap(Value1, Value2, Value3);
|
||||
else if (math_type == "pingpong")
|
||||
Value = pingpong(Value1, Value2);
|
||||
else if (math_type == "sine")
|
||||
Value = sin(Value1);
|
||||
else if (math_type == "cosine")
|
||||
Value = cos(Value1);
|
||||
else if (math_type == "tangent")
|
||||
Value = tan(Value1);
|
||||
else if (math_type == "sinh")
|
||||
Value = sinh(Value1);
|
||||
else if (math_type == "cosh")
|
||||
Value = cosh(Value1);
|
||||
else if (math_type == "tanh")
|
||||
Value = tanh(Value1);
|
||||
else if (math_type == "arcsine")
|
||||
Value = asin(Value1);
|
||||
else if (math_type == "arccosine")
|
||||
Value = acos(Value1);
|
||||
else if (math_type == "arctangent")
|
||||
Value = atan(Value1);
|
||||
else if (math_type == "arctan2")
|
||||
Value = atan2(Value1, Value2);
|
||||
else if (math_type == "sign")
|
||||
Value = sign(Value1);
|
||||
else if (math_type == "exponent")
|
||||
Value = exp(Value1);
|
||||
else if (math_type == "compare")
|
||||
Value = ((Value1 == Value2) || (abs(Value1 - Value2) <= max(Value3, 1e-5))) ? 1.0 : 0.0;
|
||||
else if (math_type == "multiply_add")
|
||||
Value = Value1 * Value2 + Value3;
|
||||
else if (math_type == "smoothmin")
|
||||
Value = smoothmin(Value1, Value2, Value3);
|
||||
else if (math_type == "smoothmax")
|
||||
Value = -(smoothmin(-Value1, -Value2, Value3));
|
||||
else
|
||||
warning("%s", "Unknown math operator!");
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
/* SPDX-FileCopyrightText: 2024 Blender Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 */
|
||||
|
||||
#include "node_fresnel.h"
|
||||
#include "stdcycles.h"
|
||||
|
||||
shader node_metallic_bsdf(color BaseColor = color(0.617, 0.577, 0.540),
|
||||
color EdgeTint = color(0.695, 0.726, 0.770),
|
||||
vector IOR = vector(2.757, 2.513, 2.231),
|
||||
vector Extinction = vector(3.867, 3.404, 3.009),
|
||||
string distribution = "multi_ggx",
|
||||
string fresnel_type = "f82",
|
||||
float Roughness = 0.5,
|
||||
float Anisotropy = 0.0,
|
||||
float Rotation = 0.0,
|
||||
float ThinFilmThickness = 0.0,
|
||||
float ThinFilmIOR = 1.33,
|
||||
normal Normal = N,
|
||||
normal Tangent = 0.0,
|
||||
output closure color BSDF = 0)
|
||||
{
|
||||
float r2 = clamp(Roughness, 0.0, 1.0);
|
||||
r2 *= r2;
|
||||
float alpha_x = r2, alpha_y = r2;
|
||||
|
||||
/* Handle anisotropy. */
|
||||
vector T = Tangent;
|
||||
if (Anisotropy > 0.0) {
|
||||
float aspect = sqrt(1.0 - clamp(Anisotropy, 0.0, 1.0) * 0.9);
|
||||
alpha_x /= aspect;
|
||||
alpha_y *= aspect;
|
||||
if (Rotation != 0.0)
|
||||
T = rotate(T, Rotation * M_2PI, point(0.0, 0.0, 0.0), Normal);
|
||||
}
|
||||
|
||||
if (fresnel_type == "f82") {
|
||||
color F0 = clamp(BaseColor, color(0.0), color(1.0));
|
||||
color F82 = clamp(EdgeTint, color(0.0), color(1.0));
|
||||
BSDF = microfacet_f82_tint(distribution,
|
||||
Normal,
|
||||
T,
|
||||
alpha_x,
|
||||
alpha_y,
|
||||
F0,
|
||||
F82,
|
||||
"thinfilm_thickness",
|
||||
ThinFilmThickness,
|
||||
"thinfilm_ior",
|
||||
ThinFilmIOR);
|
||||
}
|
||||
else {
|
||||
BSDF = conductor_bsdf(Normal,
|
||||
T,
|
||||
alpha_x,
|
||||
alpha_y,
|
||||
max(IOR, 0.0),
|
||||
max(Extinction, 0.0),
|
||||
distribution,
|
||||
"thinfilm_thickness",
|
||||
ThinFilmThickness,
|
||||
"thinfilm_ior",
|
||||
ThinFilmIOR);
|
||||
}
|
||||
}
|
||||
325
blender-5.2.0/intern/cycles/kernel/osl/shaders/node_mix.osl
Normal file
325
blender-5.2.0/intern/cycles/kernel/osl/shaders/node_mix.osl
Normal file
@@ -0,0 +1,325 @@
|
||||
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 */
|
||||
|
||||
#include "node_color.h"
|
||||
#include "stdcycles.h"
|
||||
|
||||
color node_mix_blend(float t, color col1, color col2)
|
||||
{
|
||||
return mix(col1, col2, t);
|
||||
}
|
||||
|
||||
color node_mix_add(float t, color col1, color col2)
|
||||
{
|
||||
return mix(col1, col1 + col2, t);
|
||||
}
|
||||
|
||||
color node_mix_mul(float t, color col1, color col2)
|
||||
{
|
||||
return mix(col1, col1 * col2, t);
|
||||
}
|
||||
|
||||
color node_mix_screen(float t, color col1, color col2)
|
||||
{
|
||||
float tm = 1.0 - t;
|
||||
|
||||
return color(1.0) - (color(tm) + t * (color(1.0) - col2)) * (color(1.0) - col1);
|
||||
}
|
||||
|
||||
color node_mix_overlay(float t, color col1, color col2)
|
||||
{
|
||||
float tm = 1.0 - t;
|
||||
|
||||
color outcol = col1;
|
||||
|
||||
if (outcol[0] < 0.5)
|
||||
outcol[0] *= tm + 2.0 * t * col2[0];
|
||||
else
|
||||
outcol[0] = 1.0 - (tm + 2.0 * t * (1.0 - col2[0])) * (1.0 - outcol[0]);
|
||||
|
||||
if (outcol[1] < 0.5)
|
||||
outcol[1] *= tm + 2.0 * t * col2[1];
|
||||
else
|
||||
outcol[1] = 1.0 - (tm + 2.0 * t * (1.0 - col2[1])) * (1.0 - outcol[1]);
|
||||
|
||||
if (outcol[2] < 0.5)
|
||||
outcol[2] *= tm + 2.0 * t * col2[2];
|
||||
else
|
||||
outcol[2] = 1.0 - (tm + 2.0 * t * (1.0 - col2[2])) * (1.0 - outcol[2]);
|
||||
|
||||
return outcol;
|
||||
}
|
||||
|
||||
color node_mix_sub(float t, color col1, color col2)
|
||||
{
|
||||
return mix(col1, col1 - col2, t);
|
||||
}
|
||||
|
||||
color node_mix_div(float t, color col1, color col2)
|
||||
{
|
||||
float tm = 1.0 - t;
|
||||
|
||||
color outcol = col1;
|
||||
|
||||
if (col2[0] != 0.0)
|
||||
outcol[0] = tm * outcol[0] + t * outcol[0] / col2[0];
|
||||
if (col2[1] != 0.0)
|
||||
outcol[1] = tm * outcol[1] + t * outcol[1] / col2[1];
|
||||
if (col2[2] != 0.0)
|
||||
outcol[2] = tm * outcol[2] + t * outcol[2] / col2[2];
|
||||
|
||||
return outcol;
|
||||
}
|
||||
|
||||
color node_mix_diff(float t, color col1, color col2)
|
||||
{
|
||||
return mix(col1, abs(col1 - col2), t);
|
||||
}
|
||||
|
||||
color node_mix_exclusion(float t, color col1, color col2)
|
||||
{
|
||||
return max(mix(col1, col1 + col2 - 2.0 * col1 * col2, t), 0.0);
|
||||
}
|
||||
|
||||
color node_mix_dark(float t, color col1, color col2)
|
||||
{
|
||||
return mix(col1, min(col1, col2), t);
|
||||
}
|
||||
|
||||
color node_mix_light(float t, color col1, color col2)
|
||||
{
|
||||
return mix(col1, max(col1, col2), t);
|
||||
}
|
||||
|
||||
color node_mix_dodge(float t, color col1, color col2)
|
||||
{
|
||||
color outcol = col1;
|
||||
|
||||
if (outcol[0] != 0.0) {
|
||||
float tmp = 1.0 - t * col2[0];
|
||||
if (tmp <= 0.0)
|
||||
outcol[0] = 1.0;
|
||||
else if ((tmp = outcol[0] / tmp) > 1.0)
|
||||
outcol[0] = 1.0;
|
||||
else
|
||||
outcol[0] = tmp;
|
||||
}
|
||||
if (outcol[1] != 0.0) {
|
||||
float tmp = 1.0 - t * col2[1];
|
||||
if (tmp <= 0.0)
|
||||
outcol[1] = 1.0;
|
||||
else if ((tmp = outcol[1] / tmp) > 1.0)
|
||||
outcol[1] = 1.0;
|
||||
else
|
||||
outcol[1] = tmp;
|
||||
}
|
||||
if (outcol[2] != 0.0) {
|
||||
float tmp = 1.0 - t * col2[2];
|
||||
if (tmp <= 0.0)
|
||||
outcol[2] = 1.0;
|
||||
else if ((tmp = outcol[2] / tmp) > 1.0)
|
||||
outcol[2] = 1.0;
|
||||
else
|
||||
outcol[2] = tmp;
|
||||
}
|
||||
|
||||
return outcol;
|
||||
}
|
||||
|
||||
color node_mix_burn(float t, color col1, color col2)
|
||||
{
|
||||
float tmp, tm = 1.0 - t;
|
||||
|
||||
color outcol = col1;
|
||||
|
||||
tmp = tm + t * col2[0];
|
||||
if (tmp <= 0.0)
|
||||
outcol[0] = 0.0;
|
||||
else if ((tmp = (1.0 - (1.0 - outcol[0]) / tmp)) < 0.0)
|
||||
outcol[0] = 0.0;
|
||||
else if (tmp > 1.0)
|
||||
outcol[0] = 1.0;
|
||||
else
|
||||
outcol[0] = tmp;
|
||||
|
||||
tmp = tm + t * col2[1];
|
||||
if (tmp <= 0.0)
|
||||
outcol[1] = 0.0;
|
||||
else if ((tmp = (1.0 - (1.0 - outcol[1]) / tmp)) < 0.0)
|
||||
outcol[1] = 0.0;
|
||||
else if (tmp > 1.0)
|
||||
outcol[1] = 1.0;
|
||||
else
|
||||
outcol[1] = tmp;
|
||||
|
||||
tmp = tm + t * col2[2];
|
||||
if (tmp <= 0.0)
|
||||
outcol[2] = 0.0;
|
||||
else if ((tmp = (1.0 - (1.0 - outcol[2]) / tmp)) < 0.0)
|
||||
outcol[2] = 0.0;
|
||||
else if (tmp > 1.0)
|
||||
outcol[2] = 1.0;
|
||||
else
|
||||
outcol[2] = tmp;
|
||||
|
||||
return outcol;
|
||||
}
|
||||
|
||||
color node_mix_hue(float t, color col1, color col2)
|
||||
{
|
||||
color outcol = col1;
|
||||
color hsv2 = rgb_to_hsv(col2);
|
||||
|
||||
if (hsv2[1] != 0.0) {
|
||||
color hsv = rgb_to_hsv(outcol);
|
||||
hsv[0] = hsv2[0];
|
||||
color tmp = hsv_to_rgb(hsv);
|
||||
|
||||
outcol = mix(outcol, tmp, t);
|
||||
}
|
||||
|
||||
return outcol;
|
||||
}
|
||||
|
||||
color node_mix_sat(float t, color col1, color col2)
|
||||
{
|
||||
float tm = 1.0 - t;
|
||||
|
||||
color outcol = col1;
|
||||
|
||||
color hsv = rgb_to_hsv(outcol);
|
||||
|
||||
if (hsv[1] != 0.0) {
|
||||
color hsv2 = rgb_to_hsv(col2);
|
||||
|
||||
hsv[1] = tm * hsv[1] + t * hsv2[1];
|
||||
outcol = hsv_to_rgb(hsv);
|
||||
}
|
||||
|
||||
return outcol;
|
||||
}
|
||||
|
||||
color node_mix_val(float t, color col1, color col2)
|
||||
{
|
||||
float tm = 1.0 - t;
|
||||
|
||||
color hsv = rgb_to_hsv(col1);
|
||||
color hsv2 = rgb_to_hsv(col2);
|
||||
|
||||
hsv[2] = tm * hsv[2] + t * hsv2[2];
|
||||
|
||||
return hsv_to_rgb(hsv);
|
||||
}
|
||||
|
||||
color node_mix_color(float t, color col1, color col2)
|
||||
{
|
||||
color outcol = col1;
|
||||
color hsv2 = rgb_to_hsv(col2);
|
||||
|
||||
if (hsv2[1] != 0.0) {
|
||||
color hsv = rgb_to_hsv(outcol);
|
||||
hsv[0] = hsv2[0];
|
||||
hsv[1] = hsv2[1];
|
||||
color tmp = hsv_to_rgb(hsv);
|
||||
|
||||
outcol = mix(outcol, tmp, t);
|
||||
}
|
||||
|
||||
return outcol;
|
||||
}
|
||||
|
||||
color node_mix_soft(float t, color col1, color col2)
|
||||
{
|
||||
float tm = 1.0 - t;
|
||||
|
||||
color one = color(1.0);
|
||||
color scr = one - (one - col2) * (one - col1);
|
||||
|
||||
return tm * col1 + t * ((one - col1) * col2 * col1 + col1 * scr);
|
||||
}
|
||||
|
||||
color node_mix_linear(float t, color col1, color col2)
|
||||
{
|
||||
color outcol = col1;
|
||||
|
||||
if (col2[0] > 0.5)
|
||||
outcol[0] = col1[0] + t * (2.0 * (col2[0] - 0.5));
|
||||
else
|
||||
outcol[0] = col1[0] + t * (2.0 * (col2[0]) - 1.0);
|
||||
|
||||
if (col2[1] > 0.5)
|
||||
outcol[1] = col1[1] + t * (2.0 * (col2[1] - 0.5));
|
||||
else
|
||||
outcol[1] = col1[1] + t * (2.0 * (col2[1]) - 1.0);
|
||||
|
||||
if (col2[2] > 0.5)
|
||||
outcol[2] = col1[2] + t * (2.0 * (col2[2] - 0.5));
|
||||
else
|
||||
outcol[2] = col1[2] + t * (2.0 * (col2[2]) - 1.0);
|
||||
|
||||
return outcol;
|
||||
}
|
||||
|
||||
color node_mix_clamp(color col)
|
||||
{
|
||||
color outcol = col;
|
||||
|
||||
outcol[0] = clamp(col[0], 0.0, 1.0);
|
||||
outcol[1] = clamp(col[1], 0.0, 1.0);
|
||||
outcol[2] = clamp(col[2], 0.0, 1.0);
|
||||
|
||||
return outcol;
|
||||
}
|
||||
|
||||
shader node_mix(string mix_type = "mix",
|
||||
int use_clamp = 0,
|
||||
float Fac = 0.5,
|
||||
color Color1 = 0.0,
|
||||
color Color2 = 0.0,
|
||||
output color Color = 0.0)
|
||||
{
|
||||
float t = clamp(Fac, 0.0, 1.0);
|
||||
|
||||
if (mix_type == "mix")
|
||||
Color = node_mix_blend(t, Color1, Color2);
|
||||
if (mix_type == "add")
|
||||
Color = node_mix_add(t, Color1, Color2);
|
||||
if (mix_type == "multiply")
|
||||
Color = node_mix_mul(t, Color1, Color2);
|
||||
if (mix_type == "screen")
|
||||
Color = node_mix_screen(t, Color1, Color2);
|
||||
if (mix_type == "overlay")
|
||||
Color = node_mix_overlay(t, Color1, Color2);
|
||||
if (mix_type == "subtract")
|
||||
Color = node_mix_sub(t, Color1, Color2);
|
||||
if (mix_type == "divide")
|
||||
Color = node_mix_div(t, Color1, Color2);
|
||||
if (mix_type == "difference")
|
||||
Color = node_mix_diff(t, Color1, Color2);
|
||||
if (mix_type == "exclusion")
|
||||
Color = node_mix_exclusion(t, Color1, Color2);
|
||||
if (mix_type == "darken")
|
||||
Color = node_mix_dark(t, Color1, Color2);
|
||||
if (mix_type == "lighten")
|
||||
Color = node_mix_light(t, Color1, Color2);
|
||||
if (mix_type == "dodge")
|
||||
Color = node_mix_dodge(t, Color1, Color2);
|
||||
if (mix_type == "burn")
|
||||
Color = node_mix_burn(t, Color1, Color2);
|
||||
if (mix_type == "hue")
|
||||
Color = node_mix_hue(t, Color1, Color2);
|
||||
if (mix_type == "saturation")
|
||||
Color = node_mix_sat(t, Color1, Color2);
|
||||
if (mix_type == "value")
|
||||
Color = node_mix_val(t, Color1, Color2);
|
||||
if (mix_type == "color")
|
||||
Color = node_mix_color(t, Color1, Color2);
|
||||
if (mix_type == "soft_light")
|
||||
Color = node_mix_soft(t, Color1, Color2);
|
||||
if (mix_type == "linear_light")
|
||||
Color = node_mix_linear(t, Color1, Color2);
|
||||
|
||||
if (use_clamp)
|
||||
Color = node_mix_clamp(Color);
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 */
|
||||
|
||||
#include "stdcycles.h"
|
||||
|
||||
shader node_mix_closure(float Fac = 0.5,
|
||||
closure color Closure1 = 0,
|
||||
closure color Closure2 = 0,
|
||||
output closure color Closure = 0)
|
||||
{
|
||||
float t = clamp(Fac, 0.0, 1.0);
|
||||
Closure = (1.0 - t) * Closure1 + t * Closure2;
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 */
|
||||
|
||||
#include "node_color.h"
|
||||
#include "node_color_blend.h"
|
||||
#include "stdcycles.h"
|
||||
|
||||
shader node_mix_color(string blend_type = "mix",
|
||||
int use_clamp = 0,
|
||||
int use_clamp_result = 0,
|
||||
float Factor = 0.5,
|
||||
color A = 0.0,
|
||||
color B = 0.0,
|
||||
output color Result = 0.0)
|
||||
{
|
||||
float t = (use_clamp) ? clamp(Factor, 0.0, 1.0) : Factor;
|
||||
|
||||
if (blend_type == "mix")
|
||||
Result = mix(A, B, t);
|
||||
if (blend_type == "add")
|
||||
Result = node_mix_add(t, A, B);
|
||||
if (blend_type == "multiply")
|
||||
Result = node_mix_mul(t, A, B);
|
||||
if (blend_type == "screen")
|
||||
Result = node_mix_screen(t, A, B);
|
||||
if (blend_type == "overlay")
|
||||
Result = node_mix_overlay(t, A, B);
|
||||
if (blend_type == "subtract")
|
||||
Result = node_mix_sub(t, A, B);
|
||||
if (blend_type == "divide")
|
||||
Result = node_mix_div(t, A, B);
|
||||
if (blend_type == "difference")
|
||||
Result = node_mix_diff(t, A, B);
|
||||
if (blend_type == "exclusion")
|
||||
Result = node_mix_exclusion(t, A, B);
|
||||
if (blend_type == "darken")
|
||||
Result = node_mix_dark(t, A, B);
|
||||
if (blend_type == "lighten")
|
||||
Result = node_mix_light(t, A, B);
|
||||
if (blend_type == "dodge")
|
||||
Result = node_mix_dodge(t, A, B);
|
||||
if (blend_type == "burn")
|
||||
Result = node_mix_burn(t, A, B);
|
||||
if (blend_type == "hue")
|
||||
Result = node_mix_hue(t, A, B);
|
||||
if (blend_type == "saturation")
|
||||
Result = node_mix_sat(t, A, B);
|
||||
if (blend_type == "value")
|
||||
Result = node_mix_val(t, A, B);
|
||||
if (blend_type == "color")
|
||||
Result = node_mix_color(t, A, B);
|
||||
if (blend_type == "soft_light")
|
||||
Result = node_mix_soft(t, A, B);
|
||||
if (blend_type == "linear_light")
|
||||
Result = node_mix_linear(t, A, B);
|
||||
|
||||
if (use_clamp_result)
|
||||
Result = clamp(Result, 0.0, 1.0);
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 */
|
||||
|
||||
#include "stdcycles.h"
|
||||
|
||||
shader node_mix_float(
|
||||
int use_clamp = 0, float Factor = 0.5, float A = 0.0, float B = 0.0, output float Result = 0.0)
|
||||
{
|
||||
float t = (use_clamp) ? clamp(Factor, 0.0, 1.0) : Factor;
|
||||
Result = mix(A, B, t);
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 */
|
||||
|
||||
#include "stdcycles.h"
|
||||
|
||||
shader node_mix_vector(int use_clamp = 0,
|
||||
float Factor = 0.5,
|
||||
vector A = 0.0,
|
||||
vector B = 0.0,
|
||||
output vector Result = 0.0)
|
||||
{
|
||||
float t = (use_clamp) ? clamp(Factor, 0.0, 1.0) : Factor;
|
||||
Result = mix(A, B, t);
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 */
|
||||
|
||||
#include "stdcycles.h"
|
||||
|
||||
shader node_mix_vector_non_uniform(int use_clamp = 0,
|
||||
vector Factor = 0.5,
|
||||
vector A = 0.0,
|
||||
vector B = 0.0,
|
||||
output vector Result = 0.0)
|
||||
{
|
||||
vector t = (use_clamp) ? clamp(Factor, 0.0, 1.0) : Factor;
|
||||
Result = mix(A, B, t);
|
||||
}
|
||||
277
blender-5.2.0/intern/cycles/kernel/osl/shaders/node_noise.h
Normal file
277
blender-5.2.0/intern/cycles/kernel/osl/shaders/node_noise.h
Normal file
@@ -0,0 +1,277 @@
|
||||
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 */
|
||||
|
||||
#include "vector2.h"
|
||||
#include "vector4.h"
|
||||
|
||||
#define vector3 point
|
||||
|
||||
float safe_noise(float co)
|
||||
{
|
||||
float precision_correction = 0.5 * float(fabs(co) >= 1000000.0);
|
||||
/* Repeat Perlin noise texture every 100000.0 on each axis to prevent floating point
|
||||
* representation issues. */
|
||||
float p = fmod(co, 100000.0) + precision_correction;
|
||||
|
||||
return noise("noise", p);
|
||||
}
|
||||
|
||||
float safe_noise(vector2 co)
|
||||
{
|
||||
vector2 precision_correction = 0.5 * vector2(float(fabs(co.x) >= 1000000.0),
|
||||
float(fabs(co.y) >= 1000000.0));
|
||||
/* Repeat Perlin noise texture every 100000.0 on each axis to prevent floating point
|
||||
* representation issues. This causes discontinuities every 100000.0, however at such scales this
|
||||
* usually shouldn't be noticeable. */
|
||||
vector2 p = fmod(co, 100000.0) + precision_correction;
|
||||
|
||||
return noise("noise", p.x, p.y);
|
||||
}
|
||||
|
||||
float safe_noise(vector3 co)
|
||||
{
|
||||
vector3 precision_correction = 0.5 * vector3(float(fabs(co.x) >= 1000000.0),
|
||||
float(fabs(co.y) >= 1000000.0),
|
||||
float(fabs(co.z) >= 1000000.0));
|
||||
/* Repeat Perlin noise texture every 100000.0 on each axis to prevent floating point
|
||||
* representation issues. This causes discontinuities every 100000.0, however at such scales this
|
||||
* usually shouldn't be noticeable. */
|
||||
vector3 p = fmod(co, 100000.0) + precision_correction;
|
||||
|
||||
return noise("noise", p);
|
||||
}
|
||||
|
||||
float safe_noise(vector4 co)
|
||||
{
|
||||
vector4 precision_correction = 0.5 * vector4(float(fabs(co.x) >= 1000000.0),
|
||||
float(fabs(co.y) >= 1000000.0),
|
||||
float(fabs(co.z) >= 1000000.0),
|
||||
float(fabs(co.w) >= 1000000.0));
|
||||
/* Repeat Perlin noise texture every 100000.0 on each axis to prevent floating point
|
||||
* representation issues. This causes discontinuities every 100000.0, however at such scales this
|
||||
* usually shouldn't be noticeable. */
|
||||
vector4 p = fmod(co, 100000.0) + precision_correction;
|
||||
|
||||
return noise("noise", vector3(p.x, p.y, p.z), p.w);
|
||||
}
|
||||
|
||||
float safe_snoise(float co)
|
||||
{
|
||||
float precision_correction = 0.5 * float(fabs(co) >= 1000000.0);
|
||||
/* Repeat Perlin noise texture every 100000.0 on each axis to prevent floating point
|
||||
* representation issues. */
|
||||
float p = fmod(co, 100000.0) + precision_correction;
|
||||
|
||||
return noise("snoise", p);
|
||||
}
|
||||
|
||||
float safe_snoise(vector2 co)
|
||||
{
|
||||
vector2 precision_correction = 0.5 * vector2(float(fabs(co.x) >= 1000000.0),
|
||||
float(fabs(co.y) >= 1000000.0));
|
||||
/* Repeat Perlin noise texture every 100000.0 on each axis to prevent floating point
|
||||
* representation issues. This causes discontinuities every 100000.0, however at such scales this
|
||||
* usually shouldn't be noticeable. */
|
||||
vector2 p = fmod(co, 100000.0) + precision_correction;
|
||||
|
||||
return noise("snoise", p.x, p.y);
|
||||
}
|
||||
|
||||
float safe_snoise(vector3 co)
|
||||
{
|
||||
vector3 precision_correction = 0.5 * vector3(float(fabs(co.x) >= 1000000.0),
|
||||
float(fabs(co.y) >= 1000000.0),
|
||||
float(fabs(co.z) >= 1000000.0));
|
||||
/* Repeat Perlin noise texture every 100000.0 on each axis to prevent floating point
|
||||
* representation issues. This causes discontinuities every 100000.0, however at such scales this
|
||||
* usually shouldn't be noticeable. */
|
||||
vector3 p = fmod(co, 100000.0) + precision_correction;
|
||||
|
||||
return noise("snoise", p);
|
||||
}
|
||||
|
||||
float safe_snoise(vector4 co)
|
||||
{
|
||||
vector4 precision_correction = 0.5 * vector4(float(fabs(co.x) >= 1000000.0),
|
||||
float(fabs(co.y) >= 1000000.0),
|
||||
float(fabs(co.z) >= 1000000.0),
|
||||
float(fabs(co.w) >= 1000000.0));
|
||||
/* Repeat Perlin noise texture every 100000.0 on each axis to prevent floating point
|
||||
* representation issues. This causes discontinuities every 100000.0, however at such scales this
|
||||
* usually shouldn't be noticeable. */
|
||||
vector4 p = fmod(co, 100000.0) + precision_correction;
|
||||
|
||||
return noise("snoise", vector3(p.x, p.y, p.z), p.w);
|
||||
}
|
||||
|
||||
#define NOISE_FBM(T) \
|
||||
float noise_fbm(T co, float detail, float roughness, float lacunarity, int use_normalize) \
|
||||
{ \
|
||||
T p = co; \
|
||||
float fscale = 1.0; \
|
||||
float amp = 1.0; \
|
||||
float maxamp = 0.0; \
|
||||
float sum = 0.0; \
|
||||
\
|
||||
for (int i = 0; i <= int(detail); i++) { \
|
||||
float t = safe_snoise(fscale * p); \
|
||||
sum += t * amp; \
|
||||
maxamp += amp; \
|
||||
amp *= roughness; \
|
||||
fscale *= lacunarity; \
|
||||
} \
|
||||
float rmd = detail - floor(detail); \
|
||||
if (rmd != 0.0) { \
|
||||
float t = safe_snoise(fscale * p); \
|
||||
float sum2 = sum + t * amp; \
|
||||
return use_normalize ? \
|
||||
mix(0.5 * sum / maxamp + 0.5, 0.5 * sum2 / (maxamp + amp) + 0.5, rmd) : \
|
||||
mix(sum, sum2, rmd); \
|
||||
} \
|
||||
else { \
|
||||
return use_normalize ? 0.5 * sum / maxamp + 0.5 : sum; \
|
||||
} \
|
||||
}
|
||||
|
||||
#define NOISE_MULTI_FRACTAL(T) \
|
||||
float noise_multi_fractal(T co, float detail, float roughness, float lacunarity) \
|
||||
{ \
|
||||
T p = co; \
|
||||
float value = 1.0; \
|
||||
float pwr = 1.0; \
|
||||
\
|
||||
for (int i = 0; i <= (int)detail; i++) { \
|
||||
value *= (pwr * safe_snoise(p) + 1.0); \
|
||||
pwr *= roughness; \
|
||||
p *= lacunarity; \
|
||||
} \
|
||||
\
|
||||
float rmd = detail - floor(detail); \
|
||||
if (rmd != 0.0) { \
|
||||
value *= (rmd * pwr * safe_snoise(p) + 1.0); /* correct? */ \
|
||||
} \
|
||||
\
|
||||
return value; \
|
||||
}
|
||||
|
||||
#define NOISE_HETERO_TERRAIN(T) \
|
||||
float noise_hetero_terrain(T co, float detail, float roughness, float lacunarity, float offset) \
|
||||
{ \
|
||||
T p = co; \
|
||||
float pwr = roughness; \
|
||||
\
|
||||
/* first unscaled octave of function; later octaves are scaled */ \
|
||||
float value = offset + safe_snoise(p); \
|
||||
p *= lacunarity; \
|
||||
\
|
||||
for (int i = 1; i <= (int)detail; i++) { \
|
||||
float increment = (safe_snoise(p) + offset) * pwr * value; \
|
||||
value += increment; \
|
||||
pwr *= roughness; \
|
||||
p *= lacunarity; \
|
||||
} \
|
||||
\
|
||||
float rmd = detail - floor(detail); \
|
||||
if (rmd != 0.0) { \
|
||||
float increment = (safe_snoise(p) + offset) * pwr * value; \
|
||||
value += rmd * increment; \
|
||||
} \
|
||||
\
|
||||
return value; \
|
||||
}
|
||||
|
||||
#define NOISE_HYBRID_MULTI_FRACTAL(T) \
|
||||
float noise_hybrid_multi_fractal( \
|
||||
T co, float detail, float roughness, float lacunarity, float offset, float gain) \
|
||||
{ \
|
||||
T p = co; \
|
||||
float pwr = 1.0; \
|
||||
float value = 0.0; \
|
||||
float weight = 1.0; \
|
||||
\
|
||||
for (int i = 0; (weight > 0.001) && (i <= (int)detail); i++) { \
|
||||
if (weight > 1.0) { \
|
||||
weight = 1.0; \
|
||||
} \
|
||||
\
|
||||
float signal = (safe_snoise(p) + offset) * pwr; \
|
||||
pwr *= roughness; \
|
||||
value += weight * signal; \
|
||||
weight *= gain * signal; \
|
||||
p *= lacunarity; \
|
||||
} \
|
||||
\
|
||||
float rmd = detail - floor(detail); \
|
||||
if ((rmd != 0.0) && (weight > 0.001)) { \
|
||||
if (weight > 1.0) { \
|
||||
weight = 1.0; \
|
||||
} \
|
||||
float signal = (safe_snoise(p) + offset) * pwr; \
|
||||
value += rmd * weight * signal; \
|
||||
} \
|
||||
\
|
||||
return value; \
|
||||
}
|
||||
|
||||
#define NOISE_RIDGED_MULTI_FRACTAL(T) \
|
||||
float noise_ridged_multi_fractal( \
|
||||
T co, float detail, float roughness, float lacunarity, float offset, float gain) \
|
||||
{ \
|
||||
T p = co; \
|
||||
float pwr = roughness; \
|
||||
\
|
||||
float signal = offset - fabs(safe_snoise(p)); \
|
||||
signal *= signal; \
|
||||
float value = signal; \
|
||||
float weight = 1.0; \
|
||||
\
|
||||
for (int i = 1; i <= (int)detail; i++) { \
|
||||
p *= lacunarity; \
|
||||
weight = clamp(signal * gain, 0.0, 1.0); \
|
||||
signal = offset - fabs(safe_snoise(p)); \
|
||||
signal *= signal; \
|
||||
signal *= weight; \
|
||||
value += signal * pwr; \
|
||||
pwr *= roughness; \
|
||||
} \
|
||||
\
|
||||
return value; \
|
||||
}
|
||||
|
||||
/* Noise fBM. */
|
||||
|
||||
NOISE_FBM(float)
|
||||
NOISE_FBM(vector2)
|
||||
NOISE_FBM(vector3)
|
||||
NOISE_FBM(vector4)
|
||||
|
||||
/* Noise Multi-fractal. */
|
||||
|
||||
NOISE_MULTI_FRACTAL(float)
|
||||
NOISE_MULTI_FRACTAL(vector2)
|
||||
NOISE_MULTI_FRACTAL(vector3)
|
||||
NOISE_MULTI_FRACTAL(vector4)
|
||||
|
||||
/* Noise Hetero Terrain. */
|
||||
|
||||
NOISE_HETERO_TERRAIN(float)
|
||||
NOISE_HETERO_TERRAIN(vector2)
|
||||
NOISE_HETERO_TERRAIN(vector3)
|
||||
NOISE_HETERO_TERRAIN(vector4)
|
||||
|
||||
/* Noise Hybrid Multi-fractal. */
|
||||
|
||||
NOISE_HYBRID_MULTI_FRACTAL(float)
|
||||
NOISE_HYBRID_MULTI_FRACTAL(vector2)
|
||||
NOISE_HYBRID_MULTI_FRACTAL(vector3)
|
||||
NOISE_HYBRID_MULTI_FRACTAL(vector4)
|
||||
|
||||
/* Noise Ridged Multi-fractal. */
|
||||
|
||||
NOISE_RIDGED_MULTI_FRACTAL(float)
|
||||
NOISE_RIDGED_MULTI_FRACTAL(vector2)
|
||||
NOISE_RIDGED_MULTI_FRACTAL(vector3)
|
||||
NOISE_RIDGED_MULTI_FRACTAL(vector4)
|
||||
|
||||
#undef vector3
|
||||
@@ -0,0 +1,308 @@
|
||||
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 */
|
||||
|
||||
#include "node_noise.h"
|
||||
#include "stdcycles.h"
|
||||
#include "vector2.h"
|
||||
#include "vector4.h"
|
||||
|
||||
#define vector3 point
|
||||
|
||||
#define NOISE_SELECT(T) \
|
||||
float noise_select(T p, \
|
||||
float detail, \
|
||||
float roughness, \
|
||||
float lacunarity, \
|
||||
float offset, \
|
||||
float gain, \
|
||||
string type, \
|
||||
int use_normalize) \
|
||||
{ \
|
||||
if (type == "multifractal") { \
|
||||
return noise_multi_fractal(p, detail, roughness, lacunarity); \
|
||||
} \
|
||||
else if (type == "fBM") { \
|
||||
return noise_fbm(p, detail, roughness, lacunarity, use_normalize); \
|
||||
} \
|
||||
else if (type == "hybrid_multifractal") { \
|
||||
return noise_hybrid_multi_fractal(p, detail, roughness, lacunarity, offset, gain); \
|
||||
} \
|
||||
else if (type == "ridged_multifractal") { \
|
||||
return noise_ridged_multi_fractal(p, detail, roughness, lacunarity, offset, gain); \
|
||||
} \
|
||||
else if (type == "hetero_terrain") { \
|
||||
return noise_hetero_terrain(p, detail, roughness, lacunarity, offset); \
|
||||
} \
|
||||
else { \
|
||||
error("Unknown Type!"); \
|
||||
return 0.0; \
|
||||
} \
|
||||
}
|
||||
|
||||
/* The following offset functions generate random offsets to be added to texture
|
||||
* coordinates to act as a seed since the noise functions don't have seed values.
|
||||
* A seed value is needed for generating distortion textures and color outputs.
|
||||
* The offset's components are in the range [100, 200], not too high to cause
|
||||
* bad precision and not too small to be noticeable. We use float seed because
|
||||
* OSL only support float hashes.
|
||||
*/
|
||||
|
||||
float random_float_offset(float seed)
|
||||
{
|
||||
return 100.0 + noise("hash", seed) * 100.0;
|
||||
}
|
||||
|
||||
vector2 random_vector2_offset(float seed)
|
||||
{
|
||||
return vector2(100.0 + noise("hash", seed, 0.0) * 100.0,
|
||||
100.0 + noise("hash", seed, 1.0) * 100.0);
|
||||
}
|
||||
|
||||
vector3 random_vector3_offset(float seed)
|
||||
{
|
||||
return vector3(100.0 + noise("hash", seed, 0.0) * 100.0,
|
||||
100.0 + noise("hash", seed, 1.0) * 100.0,
|
||||
100.0 + noise("hash", seed, 2.0) * 100.0);
|
||||
}
|
||||
|
||||
vector4 random_vector4_offset(float seed)
|
||||
{
|
||||
return vector4(100.0 + noise("hash", seed, 0.0) * 100.0,
|
||||
100.0 + noise("hash", seed, 1.0) * 100.0,
|
||||
100.0 + noise("hash", seed, 2.0) * 100.0,
|
||||
100.0 + noise("hash", seed, 3.0) * 100.0);
|
||||
}
|
||||
|
||||
/* Noise Select */
|
||||
|
||||
NOISE_SELECT(float)
|
||||
NOISE_SELECT(vector2)
|
||||
NOISE_SELECT(vector3)
|
||||
NOISE_SELECT(vector4)
|
||||
|
||||
float noise_texture(float co,
|
||||
float detail,
|
||||
float roughness,
|
||||
float lacunarity,
|
||||
float offset,
|
||||
float gain,
|
||||
float distortion,
|
||||
string type,
|
||||
int use_normalize,
|
||||
output color Color)
|
||||
{
|
||||
float p = co;
|
||||
if (distortion != 0.0) {
|
||||
p += safe_snoise(p + random_float_offset(0.0)) * distortion;
|
||||
}
|
||||
|
||||
float value = noise_select(p, detail, roughness, lacunarity, offset, gain, type, use_normalize);
|
||||
if (isconnected(Color) != 0) {
|
||||
Color = color(value,
|
||||
noise_select(p + random_float_offset(1.0),
|
||||
detail,
|
||||
roughness,
|
||||
lacunarity,
|
||||
offset,
|
||||
gain,
|
||||
type,
|
||||
use_normalize),
|
||||
noise_select(p + random_float_offset(2.0),
|
||||
detail,
|
||||
roughness,
|
||||
lacunarity,
|
||||
offset,
|
||||
gain,
|
||||
type,
|
||||
use_normalize));
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
float noise_texture(vector2 co,
|
||||
float detail,
|
||||
float roughness,
|
||||
float lacunarity,
|
||||
float offset,
|
||||
float gain,
|
||||
float distortion,
|
||||
string type,
|
||||
int use_normalize,
|
||||
output color Color)
|
||||
{
|
||||
vector2 p = co;
|
||||
if (distortion != 0.0) {
|
||||
p += vector2(safe_snoise(p + random_vector2_offset(0.0)) * distortion,
|
||||
safe_snoise(p + random_vector2_offset(1.0)) * distortion);
|
||||
}
|
||||
|
||||
float value = noise_select(p, detail, roughness, lacunarity, offset, gain, type, use_normalize);
|
||||
if (isconnected(Color) != 0) {
|
||||
Color = color(value,
|
||||
noise_select(p + random_vector2_offset(2.0),
|
||||
detail,
|
||||
roughness,
|
||||
lacunarity,
|
||||
offset,
|
||||
gain,
|
||||
type,
|
||||
use_normalize),
|
||||
noise_select(p + random_vector2_offset(3.0),
|
||||
detail,
|
||||
roughness,
|
||||
lacunarity,
|
||||
offset,
|
||||
gain,
|
||||
type,
|
||||
use_normalize));
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
float noise_texture(vector3 co,
|
||||
float detail,
|
||||
float roughness,
|
||||
float lacunarity,
|
||||
float offset,
|
||||
float gain,
|
||||
float distortion,
|
||||
string type,
|
||||
int use_normalize,
|
||||
output color Color)
|
||||
{
|
||||
vector3 p = co;
|
||||
if (distortion != 0.0) {
|
||||
p += vector3(safe_snoise(p + random_vector3_offset(0.0)) * distortion,
|
||||
safe_snoise(p + random_vector3_offset(1.0)) * distortion,
|
||||
safe_snoise(p + random_vector3_offset(2.0)) * distortion);
|
||||
}
|
||||
|
||||
float value = noise_select(p, detail, roughness, lacunarity, offset, gain, type, use_normalize);
|
||||
if (isconnected(Color) != 0) {
|
||||
Color = color(value,
|
||||
noise_select(p + random_vector3_offset(3.0),
|
||||
detail,
|
||||
roughness,
|
||||
lacunarity,
|
||||
offset,
|
||||
gain,
|
||||
type,
|
||||
use_normalize),
|
||||
noise_select(p + random_vector3_offset(4.0),
|
||||
detail,
|
||||
roughness,
|
||||
lacunarity,
|
||||
offset,
|
||||
gain,
|
||||
type,
|
||||
use_normalize));
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
float noise_texture(vector4 co,
|
||||
float detail,
|
||||
float roughness,
|
||||
float lacunarity,
|
||||
float offset,
|
||||
float gain,
|
||||
float distortion,
|
||||
string type,
|
||||
int use_normalize,
|
||||
output color Color)
|
||||
{
|
||||
vector4 p = co;
|
||||
if (distortion != 0.0) {
|
||||
p += vector4(safe_snoise(p + random_vector4_offset(0.0)) * distortion,
|
||||
safe_snoise(p + random_vector4_offset(1.0)) * distortion,
|
||||
safe_snoise(p + random_vector4_offset(2.0)) * distortion,
|
||||
safe_snoise(p + random_vector4_offset(3.0)) * distortion);
|
||||
}
|
||||
|
||||
float value = noise_select(p, detail, roughness, lacunarity, offset, gain, type, use_normalize);
|
||||
if (isconnected(Color) != 0) {
|
||||
Color = color(value,
|
||||
noise_select(p + random_vector4_offset(4.0),
|
||||
detail,
|
||||
roughness,
|
||||
lacunarity,
|
||||
offset,
|
||||
gain,
|
||||
type,
|
||||
use_normalize),
|
||||
noise_select(p + random_vector4_offset(5.0),
|
||||
detail,
|
||||
roughness,
|
||||
lacunarity,
|
||||
offset,
|
||||
gain,
|
||||
type,
|
||||
use_normalize));
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
shader node_noise_texture(int use_mapping = 0,
|
||||
matrix mapping = matrix(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
|
||||
string dimensions = "3D",
|
||||
string type = "fBM",
|
||||
int use_normalize = 1,
|
||||
vector3 Vector = vector3(0, 0, 0),
|
||||
float W = 0.0,
|
||||
float Scale = 5.0,
|
||||
float Detail = 2.0,
|
||||
float Roughness = 0.5,
|
||||
float Offset = 0.0,
|
||||
float Gain = 1.0,
|
||||
float Lacunarity = 2.0,
|
||||
float Distortion = 0.0,
|
||||
output float Fac = 0.0,
|
||||
output color Color = 0.0)
|
||||
{
|
||||
vector3 p = Vector;
|
||||
if (use_mapping)
|
||||
p = transform(mapping, p);
|
||||
|
||||
float detail = clamp(Detail, 0.0, 15.0);
|
||||
float roughness = max(Roughness, 0.0);
|
||||
|
||||
p *= Scale;
|
||||
float w = W * Scale;
|
||||
|
||||
if (dimensions == "1D") {
|
||||
Fac = noise_texture(
|
||||
w, detail, roughness, Lacunarity, Offset, Gain, Distortion, type, use_normalize, Color);
|
||||
}
|
||||
else if (dimensions == "2D") {
|
||||
Fac = noise_texture(vector2(p[0], p[1]),
|
||||
detail,
|
||||
roughness,
|
||||
Lacunarity,
|
||||
Offset,
|
||||
Gain,
|
||||
Distortion,
|
||||
type,
|
||||
use_normalize,
|
||||
Color);
|
||||
}
|
||||
else if (dimensions == "3D") {
|
||||
Fac = noise_texture(
|
||||
p, detail, roughness, Lacunarity, Offset, Gain, Distortion, type, use_normalize, Color);
|
||||
}
|
||||
else if (dimensions == "4D") {
|
||||
Fac = noise_texture(vector4(p[0], p[1], p[2], w),
|
||||
detail,
|
||||
roughness,
|
||||
Lacunarity,
|
||||
Offset,
|
||||
Gain,
|
||||
Distortion,
|
||||
type,
|
||||
use_normalize,
|
||||
Color);
|
||||
}
|
||||
else {
|
||||
error("Unknown Dimension!");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 */
|
||||
|
||||
#include "stdcycles.h"
|
||||
|
||||
shader node_normal(normal direction = normal(0.0, 0.0, 0.0),
|
||||
normal NormalIn = normal(0.0, 0.0, 0.0),
|
||||
output normal NormalOut = normal(0.0, 0.0, 0.0),
|
||||
output float Dot = 1.0)
|
||||
{
|
||||
NormalOut = normalize(direction);
|
||||
Dot = dot(NormalOut, normalize(NormalIn));
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 */
|
||||
|
||||
#include "stdcycles.h"
|
||||
|
||||
shader node_normal_map(float Strength = 1.0,
|
||||
color Color = color(0.5, 0.5, 1.0),
|
||||
string space = "tangent",
|
||||
string attr_name = "geom:undisplaced_tangent",
|
||||
string attr_sign_name = "geom:undisplaced_tangent_sign",
|
||||
string convention = "opengl",
|
||||
string base = "original",
|
||||
output normal Normal = N)
|
||||
{
|
||||
color mcolor = 2.0 * color(Color[0] - 0.5, Color[1] - 0.5, Color[2] - 0.5);
|
||||
int is_backfacing = backfacing();
|
||||
int linear_interpolate_strength = 0;
|
||||
|
||||
if (convention == "directx") {
|
||||
mcolor[1] = -mcolor[1];
|
||||
}
|
||||
|
||||
if (space == "tangent") {
|
||||
vector tangent;
|
||||
vector ninterp;
|
||||
float tangent_sign;
|
||||
float is_smooth = 0.0;
|
||||
|
||||
if (!getattribute(attr_name, tangent) || !getattribute(attr_sign_name, tangent_sign)) {
|
||||
Normal = N;
|
||||
return;
|
||||
}
|
||||
|
||||
getattribute("geom:is_smooth", is_smooth);
|
||||
if (is_smooth) {
|
||||
if (base == "original" && getattribute("geom:undisplaced_N", ninterp)) {
|
||||
/* Can't interpolate in tangent space as the displaced normal is not used
|
||||
* for the tangent frame. */
|
||||
linear_interpolate_strength = 1;
|
||||
}
|
||||
else if (getattribute("geom:normal_map_normal", ninterp)) {
|
||||
}
|
||||
else {
|
||||
ninterp = N;
|
||||
}
|
||||
}
|
||||
else {
|
||||
ninterp = normalize(transform("world", "object", Ng));
|
||||
|
||||
/* the normal is already inverted, which is too soon for the math here */
|
||||
if (is_backfacing) {
|
||||
ninterp = -ninterp;
|
||||
}
|
||||
}
|
||||
|
||||
/* apply normal map */
|
||||
vector B = tangent_sign * cross(ninterp, tangent);
|
||||
|
||||
/* apply strength */
|
||||
if (!linear_interpolate_strength) {
|
||||
mcolor[0] *= Strength;
|
||||
mcolor[1] *= Strength;
|
||||
mcolor[2] = mix(1.0, mcolor[2], clamp(Strength, 0.0, 1.0));
|
||||
}
|
||||
|
||||
Normal = normalize(mcolor[0] * tangent + mcolor[1] * B + mcolor[2] * ninterp);
|
||||
|
||||
/* transform to world space */
|
||||
Normal = normalize(transform("object", "world", Normal));
|
||||
}
|
||||
else {
|
||||
linear_interpolate_strength = 1;
|
||||
|
||||
if (space == "object") {
|
||||
Normal = normalize(transform("object", "world", vector(mcolor)));
|
||||
}
|
||||
else if (space == "world") {
|
||||
Normal = normalize(vector(mcolor));
|
||||
}
|
||||
else if (space == "blender_object") {
|
||||
/* strange blender convention */
|
||||
mcolor[1] = -mcolor[1];
|
||||
mcolor[2] = -mcolor[2];
|
||||
|
||||
Normal = normalize(transform("object", "world", vector(mcolor)));
|
||||
}
|
||||
else if (space == "blender_world") {
|
||||
/* strange blender convention */
|
||||
mcolor[1] = -mcolor[1];
|
||||
mcolor[2] = -mcolor[2];
|
||||
|
||||
Normal = normalize(vector(mcolor));
|
||||
}
|
||||
}
|
||||
|
||||
/* invert normal for backfacing polygons */
|
||||
if (is_backfacing) {
|
||||
Normal = -Normal;
|
||||
}
|
||||
|
||||
if (linear_interpolate_strength && Strength != 1.0) {
|
||||
Normal = normalize(N + (Normal - N) * max(Strength, 0.0));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 */
|
||||
|
||||
#include "stdcycles.h"
|
||||
|
||||
shader node_object_info(output point Location = point(0.0, 0.0, 0.0),
|
||||
output color Color = color(1.0, 1.0, 1.0),
|
||||
output float Alpha = 1.0,
|
||||
output float ObjectIndex = 0.0,
|
||||
output float MaterialIndex = 0.0,
|
||||
output float Random = 0.0)
|
||||
{
|
||||
getattribute("object:location", Location);
|
||||
getattribute("object:color", Color);
|
||||
getattribute("object:alpha", Alpha);
|
||||
getattribute("object:index", ObjectIndex);
|
||||
getattribute("material:index", MaterialIndex);
|
||||
getattribute("object:random", Random);
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 */
|
||||
|
||||
#include "stdcycles.h"
|
||||
|
||||
displacement node_output_displacement(vector Displacement = 0.0)
|
||||
{
|
||||
P += Displacement;
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 */
|
||||
|
||||
#include "stdcycles.h"
|
||||
|
||||
surface node_output_surface(closure color Surface = 0)
|
||||
{
|
||||
Ci = Surface;
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 */
|
||||
|
||||
#include "stdcycles.h"
|
||||
|
||||
volume node_output_volume(closure color Volume = 0)
|
||||
{
|
||||
Ci = Volume;
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 */
|
||||
|
||||
#include "stdcycles.h"
|
||||
|
||||
shader node_particle_info(output float Index = 0.0,
|
||||
output float Random = 0.0,
|
||||
output float Age = 0.0,
|
||||
output float Lifetime = 0.0,
|
||||
output point Location = point(0.0, 0.0, 0.0),
|
||||
output float Size = 0.0,
|
||||
output vector Velocity = point(0.0, 0.0, 0.0),
|
||||
output vector AngularVelocity = point(0.0, 0.0, 0.0))
|
||||
{
|
||||
getattribute("particle:index", Index);
|
||||
getattribute("particle:random", Random);
|
||||
getattribute("particle:age", Age);
|
||||
getattribute("particle:lifetime", Lifetime);
|
||||
getattribute("particle:location", Location);
|
||||
getattribute("particle:size", Size);
|
||||
getattribute("particle:velocity", Velocity);
|
||||
getattribute("particle:angular_velocity", AngularVelocity);
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 */
|
||||
|
||||
#include "stdcycles.h"
|
||||
|
||||
shader node_point_info(output point Position = point(0.0, 0.0, 0.0),
|
||||
output float Radius = 0.0,
|
||||
output float Random = 0.0)
|
||||
{
|
||||
getattribute("geom:point_position", Position);
|
||||
getattribute("geom:point_radius", Radius);
|
||||
getattribute("geom:point_random", Random);
|
||||
}
|
||||
@@ -0,0 +1,220 @@
|
||||
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 */
|
||||
|
||||
#include "node_fresnel.h"
|
||||
#include "stdcycles.h"
|
||||
|
||||
shader node_principled_bsdf(string distribution = "multi_ggx",
|
||||
string subsurface_method = "random_walk",
|
||||
color BaseColor = color(0.8, 0.8, 0.8),
|
||||
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 DiffuseRoughness = 0.0,
|
||||
float SpecularIORLevel = 0.5,
|
||||
color SpecularTint = color(1.0),
|
||||
float Roughness = 0.5,
|
||||
float Anisotropic = 0.0,
|
||||
float AnisotropicRotation = 0.0,
|
||||
float SheenWeight = 0.0,
|
||||
float SheenRoughness = 0.5,
|
||||
color SheenTint = 0.5,
|
||||
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 TransmissionWeight = 0.0,
|
||||
color EmissionColor = 1.0,
|
||||
float EmissionStrength = 0.0,
|
||||
float Alpha = 1.0,
|
||||
int ThinWall = 0,
|
||||
float ThinFilmThickness = 0.0,
|
||||
float ThinFilmIOR = 1.33,
|
||||
normal Normal = N,
|
||||
normal CoatNormal = N,
|
||||
normal Tangent = normalize(dPdu),
|
||||
output closure color BSDF = 0)
|
||||
{
|
||||
float CLOSURE_WEIGHT_CUTOFF = 1e-5;
|
||||
|
||||
/* Clamping to match SVM */
|
||||
float metallic = clamp(Metallic, 0.0, 1.0);
|
||||
float transmission = clamp(TransmissionWeight, 0.0, 1.0);
|
||||
float subsurface_weight = clamp(SubsurfaceWeight, 0.0, 1.0);
|
||||
color specular_tint = max(SpecularTint, color(0.0));
|
||||
float coat_weight = max(CoatWeight, 0.0);
|
||||
color coat_tint = max(CoatTint, color(0.0));
|
||||
float sheen_weight = max(SheenWeight, 0.0);
|
||||
color base_color = max(BaseColor, color(0.0));
|
||||
color clamped_base_color = min(base_color, color(1.0));
|
||||
float diffuse_roughness = clamp(DiffuseRoughness, 0.0, 1.0);
|
||||
|
||||
float r2 = clamp(Roughness, 0.0, 1.0);
|
||||
r2 = r2 * r2;
|
||||
|
||||
float alpha_x = r2, alpha_y = r2;
|
||||
|
||||
int is_backfacing = !ThinWall && backfacing();
|
||||
|
||||
/* Handle anisotropy. */
|
||||
vector T = Tangent;
|
||||
if (Anisotropic > 0.0) {
|
||||
float aspect = sqrt(1.0 - clamp(Anisotropic, 0.0, 1.0) * 0.9);
|
||||
alpha_x /= aspect;
|
||||
alpha_y *= aspect;
|
||||
if (AnisotropicRotation != 0.0)
|
||||
T = rotate(T, AnisotropicRotation * M_2PI, point(0.0, 0.0, 0.0), Normal);
|
||||
}
|
||||
|
||||
if (metallic < 1.0 && TransmissionWeight < 1.0) {
|
||||
float eta = max(IOR, 1e-5);
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
if (diffuse_roughness > CLOSURE_WEIGHT_CUTOFF) {
|
||||
BSDF = oren_nayar_diffuse_bsdf(Normal, base_color, diffuse_roughness);
|
||||
}
|
||||
else {
|
||||
BSDF = base_color * diffuse(Normal);
|
||||
}
|
||||
|
||||
if (subsurface_weight > CLOSURE_WEIGHT_CUTOFF) {
|
||||
closure color SubsurfBSDF = 0;
|
||||
if (ThinWall) {
|
||||
SubsurfBSDF = thin_subsurface(
|
||||
Normal, vector(0.0), clamped_base_color, SubsurfaceAnisotropy, diffuse_roughness);
|
||||
}
|
||||
else {
|
||||
vector radius = max(SubsurfaceScale * SubsurfaceRadius, vector(0.0));
|
||||
float subsurface_ior = (subsurface_method == "random_walk_skin") ? SubsurfaceIOR : eta;
|
||||
SubsurfBSDF = bssrdf(subsurface_method,
|
||||
Normal,
|
||||
radius,
|
||||
clamped_base_color,
|
||||
"roughness",
|
||||
r2,
|
||||
"ior",
|
||||
subsurface_ior,
|
||||
"anisotropy",
|
||||
SubsurfaceAnisotropy);
|
||||
}
|
||||
BSDF = mix(clamped_base_color * SubsurfBSDF, BSDF, 1.0 - subsurface_weight);
|
||||
}
|
||||
|
||||
if (eta != 1.0 || ThinFilmThickness > 0.1) {
|
||||
/* Apply specular tint */
|
||||
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,
|
||||
-eta,
|
||||
distribution,
|
||||
"thinfilm_thickness",
|
||||
ThinFilmThickness,
|
||||
"thinfilm_ior",
|
||||
ThinFilmIOR),
|
||||
BSDF);
|
||||
}
|
||||
}
|
||||
|
||||
if (metallic < 1.0 && TransmissionWeight > CLOSURE_WEIGHT_CUTOFF) {
|
||||
float eta = max(IOR, 1e-5);
|
||||
float thinfilm_ior = is_backfacing ? ThinFilmIOR / eta : ThinFilmIOR;
|
||||
eta = is_backfacing ? 1.0 / eta : eta;
|
||||
if (ThinWall) {
|
||||
closure color ThinGlassBSDF = thin_glass(Normal,
|
||||
vector(0.0),
|
||||
specular_tint,
|
||||
clamped_base_color,
|
||||
eta,
|
||||
r2,
|
||||
ThinFilmThickness,
|
||||
thinfilm_ior);
|
||||
BSDF = mix(ThinGlassBSDF, BSDF, 1.0 - transmission);
|
||||
}
|
||||
else {
|
||||
color F0 = F0_from_ior(eta) * specular_tint;
|
||||
color F90 = color(1.0);
|
||||
|
||||
closure color TransmissionBSDF = generalized_schlick_bsdf(Normal,
|
||||
vector(0.0),
|
||||
color(1.0),
|
||||
sqrt(clamped_base_color),
|
||||
r2,
|
||||
r2,
|
||||
F0,
|
||||
F90,
|
||||
-eta,
|
||||
distribution,
|
||||
"thinfilm_thickness",
|
||||
ThinFilmThickness,
|
||||
"thinfilm_ior",
|
||||
thinfilm_ior);
|
||||
BSDF = mix(TransmissionBSDF, BSDF, 1.0 - transmission);
|
||||
}
|
||||
}
|
||||
|
||||
closure color MetallicBSDF = 0;
|
||||
if (metallic > CLOSURE_WEIGHT_CUTOFF) {
|
||||
color F0 = clamped_base_color;
|
||||
color F82 = min(specular_tint, color(1.0));
|
||||
MetallicBSDF = microfacet_f82_tint(distribution,
|
||||
Normal,
|
||||
T,
|
||||
alpha_x,
|
||||
alpha_y,
|
||||
F0,
|
||||
F82,
|
||||
"thinfilm_thickness",
|
||||
ThinFilmThickness,
|
||||
"thinfilm_ior",
|
||||
ThinFilmIOR);
|
||||
BSDF = mix(MetallicBSDF, BSDF, 1.0 - metallic);
|
||||
}
|
||||
|
||||
if (EmissionStrength != 0.0 && EmissionColor != color(0.0)) {
|
||||
BSDF += EmissionStrength * EmissionColor * emission();
|
||||
}
|
||||
|
||||
if (coat_weight > CLOSURE_WEIGHT_CUTOFF) {
|
||||
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 *= mix(color(1.0), pow(CoatTint, 1.0 / cosNT), clamp(coat_weight, 0.0, 1.0));
|
||||
}
|
||||
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, "multi_ggx");
|
||||
BSDF = layer(coat_weight * CoatBSDF, BSDF);
|
||||
}
|
||||
|
||||
if (SheenWeight > CLOSURE_WEIGHT_CUTOFF) {
|
||||
normal sheen_normal = normalize(mix(Normal, CoatNormal, clamp(coat_weight, 0.0, 1.0)));
|
||||
closure color SheenBSDF = sheen(sheen_normal, clamp(SheenRoughness, 0.0, 1.0));
|
||||
BSDF = layer(sheen_weight * max(SheenTint, color(0.0)) * SheenBSDF, BSDF);
|
||||
}
|
||||
|
||||
BSDF = mix(transparent(), BSDF, clamp(Alpha, 0.0, 1.0));
|
||||
}
|
||||
@@ -0,0 +1,108 @@
|
||||
/* SPDX-FileCopyrightText: 2018-2022 Blender Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 */
|
||||
|
||||
#include "stdcycles.h"
|
||||
|
||||
color log3(color a)
|
||||
{
|
||||
return color(log(a[0]), log(a[1]), log(a[2]));
|
||||
}
|
||||
|
||||
color sigma_from_concentration(float eumelanin, float pheomelanin)
|
||||
{
|
||||
return eumelanin * color(0.506, 0.841, 1.653) + pheomelanin * color(0.343, 0.733, 1.924);
|
||||
}
|
||||
|
||||
color sigma_from_reflectance(color c, float azimuthal_roughness)
|
||||
{
|
||||
float x = azimuthal_roughness;
|
||||
float roughness_fac = (((((0.245 * x) + 5.574) * x - 10.73) * x + 2.532) * x - 0.215) * x +
|
||||
5.969;
|
||||
color sigma = log3(c) / roughness_fac;
|
||||
return sigma * sigma;
|
||||
}
|
||||
|
||||
shader node_principled_hair_bsdf(color Color = color(0.017513, 0.005763, 0.002059),
|
||||
float Melanin = 0.8,
|
||||
float MelaninRedness = 1.0,
|
||||
float RandomColor = 0.0,
|
||||
color Tint = 1.0,
|
||||
color AbsorptionCoefficient = color(0.245531, 0.52, 1.365),
|
||||
normal Normal = Ng,
|
||||
string model = "Huang",
|
||||
string parametrization = "Direct Coloring",
|
||||
float Offset = radians(2),
|
||||
float Roughness = 0.3,
|
||||
float RadialRoughness = 0.3,
|
||||
float RandomRoughness = 0.0,
|
||||
float Coat = 0.0,
|
||||
float IOR = 1.55,
|
||||
string AttrRandom = "geom:curve_random",
|
||||
float Random = 0.0,
|
||||
float AspectRatio = 0.85,
|
||||
float Rlobe = 1.0,
|
||||
float TTlobe = 1.0,
|
||||
float TRTlobe = 1.0,
|
||||
|
||||
output closure color BSDF = 0)
|
||||
{
|
||||
/* Get random value from curve in none is specified. */
|
||||
float random_value = 0.0;
|
||||
|
||||
if (isconnected(Random)) {
|
||||
random_value = Random;
|
||||
}
|
||||
else {
|
||||
getattribute(AttrRandom, random_value);
|
||||
}
|
||||
|
||||
/* Compute roughness. */
|
||||
float factor_random_roughness = 1.0 + 2.0 * (random_value - 0.5) * RandomRoughness;
|
||||
float m0_roughness = 1.0 - clamp(Coat, 0.0, 1.0);
|
||||
float roughness = Roughness * factor_random_roughness;
|
||||
float radial_roughness = RadialRoughness * factor_random_roughness;
|
||||
|
||||
/* Compute absorption. */
|
||||
color sigma;
|
||||
|
||||
if (parametrization == "Absorption coefficient") {
|
||||
sigma = AbsorptionCoefficient;
|
||||
}
|
||||
else if (parametrization == "Melanin concentration") {
|
||||
/* Randomize melanin. */
|
||||
float factor_random_color = 1.0 + 2.0 * (random_value - 0.5) * RandomColor;
|
||||
float melanin = Melanin * factor_random_color;
|
||||
|
||||
/* Map melanin 0..inf from more perceptually linear 0..1. */
|
||||
melanin = -log(max(1.0 - melanin, 0.0001));
|
||||
|
||||
/* Benedikt Bitterli's melanin ratio remapping. */
|
||||
float eumelanin = melanin * (1.0 - MelaninRedness);
|
||||
float pheomelanin = melanin * MelaninRedness;
|
||||
color melanin_sigma = sigma_from_concentration(eumelanin, pheomelanin);
|
||||
|
||||
/* Optional tint. */
|
||||
color tint_sigma = sigma_from_reflectance(Tint, radial_roughness);
|
||||
sigma = melanin_sigma + tint_sigma;
|
||||
}
|
||||
else if (parametrization == "Direct coloring") {
|
||||
sigma = sigma_from_reflectance(Color, radial_roughness);
|
||||
}
|
||||
else {
|
||||
/* Fall back to brownish hair, same as defaults for melanin. */
|
||||
sigma = sigma_from_concentration(0.0, 0.8054375);
|
||||
}
|
||||
|
||||
if (model == "Huang") {
|
||||
normal major_axis = Normal;
|
||||
if (AspectRatio != 1.0) {
|
||||
getattribute("geom:N", major_axis);
|
||||
}
|
||||
BSDF = hair_huang(
|
||||
major_axis, sigma, roughness, Offset, IOR, AspectRatio, Rlobe, TTlobe, TRTlobe);
|
||||
}
|
||||
else {
|
||||
BSDF = hair_chiang(Normal, sigma, roughness, radial_roughness, m0_roughness, Offset, IOR);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 */
|
||||
|
||||
#include "node_math.h"
|
||||
#include "stdcycles.h"
|
||||
|
||||
shader node_principled_volume(color Color = color(0.5, 0.5, 0.5),
|
||||
float Density = 1.0,
|
||||
float Anisotropy = 0.0,
|
||||
color AbsorptionColor = color(0.0, 0.0, 0.0),
|
||||
float EmissionStrength = 0.0,
|
||||
color EmissionColor = color(1.0, 1.0, 1.0),
|
||||
float BlackbodyIntensity = 0.0,
|
||||
color BlackbodyTint = color(1.0, 1.0, 1.0),
|
||||
float Temperature = 1500.0,
|
||||
string DensityAttribute = "geom:density",
|
||||
string ColorAttribute = "geom:color",
|
||||
string TemperatureAttribute = "geom:temperature",
|
||||
output closure color Volume = 0)
|
||||
{
|
||||
/* Compute density. */
|
||||
float primitive_density = 1.0;
|
||||
float density = max(Density, 0.0);
|
||||
|
||||
if (density > 0.0) {
|
||||
if (getattribute(DensityAttribute, primitive_density)) {
|
||||
density = max(density * primitive_density, 0.0);
|
||||
}
|
||||
}
|
||||
|
||||
if (density > 0.0) {
|
||||
/* Compute scattering color. */
|
||||
color scatter_color = Color;
|
||||
color primitive_color;
|
||||
if (getattribute(ColorAttribute, primitive_color)) {
|
||||
scatter_color *= primitive_color;
|
||||
}
|
||||
|
||||
/* Add scattering and absorption closures. */
|
||||
color absorption_color = sqrt(max(AbsorptionColor, 0.0));
|
||||
color absorption_coeff = max(1.0 - scatter_color, 0.0) * max(1.0 - absorption_color, 0.0);
|
||||
color extinction = scatter_color + absorption_coeff;
|
||||
color albedo = safe_divide(scatter_color, extinction);
|
||||
Volume = density * anisotropic_vdf(albedo, extinction, Anisotropy);
|
||||
}
|
||||
|
||||
/* Compute emission. */
|
||||
float emission_strength = max(EmissionStrength, 0.0);
|
||||
float blackbody_intensity = BlackbodyIntensity;
|
||||
|
||||
if (emission_strength > 0.0) {
|
||||
Volume += emission_strength * EmissionColor * emission();
|
||||
}
|
||||
|
||||
if (blackbody_intensity > 0.0) {
|
||||
float T = Temperature;
|
||||
|
||||
/* Add temperature from attribute if available. */
|
||||
float temperature;
|
||||
if (getattribute(TemperatureAttribute, temperature)) {
|
||||
T *= max(temperature, 0.0);
|
||||
}
|
||||
|
||||
T = max(T, 0.0);
|
||||
|
||||
/* Stefan-Boltzmann law. */
|
||||
float T4 = (T * T) * (T * T);
|
||||
float sigma = 5.670373e-8 * 1e-6 / M_PI;
|
||||
float intensity = sigma * mix(1.0, T4, blackbody_intensity);
|
||||
|
||||
if (intensity > 0.0) {
|
||||
color bb = blackbody(T);
|
||||
float l = luminance(bb);
|
||||
|
||||
if (l != 0.0) {
|
||||
bb *= BlackbodyTint * intensity / l;
|
||||
Volume += bb * emission();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
/* SPDX-FileCopyrightText: 2024-2025 Blender Authors
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 */
|
||||
|
||||
#include "node_math.h"
|
||||
#include "stdcycles.h"
|
||||
#include "vector2.h"
|
||||
#include "vector4.h"
|
||||
|
||||
#define vector3 point
|
||||
|
||||
/* Define macro flags for code adaption. */
|
||||
#define ADAPT_TO_OSL
|
||||
|
||||
/* The rounded polygon calculation functions are defined in node_radial_tiling_shared.h. */
|
||||
#include "node_radial_tiling_shared.h"
|
||||
|
||||
/* Undefine macro flags used for code adaption. */
|
||||
#undef ADAPT_TO_OSL
|
||||
|
||||
shader node_radial_tiling(int use_normalize = 0,
|
||||
vector3 Vector = P,
|
||||
float Sides = 5.0,
|
||||
float Roundness = 0.0,
|
||||
output vector3 SegmentCoordinates = vector3(0.0, 0.0, 0.0),
|
||||
output float SegmentID = 0.0,
|
||||
output float SegmentWidth = 0.0,
|
||||
output float SegmentRotation = 0.0)
|
||||
{
|
||||
/* isconnected() returns 2 when output socket is connected. */
|
||||
int calculate_r_gon_parameter_field = int(isconnected(SegmentCoordinates) != 0);
|
||||
int calculate_segment_id = int(isconnected(SegmentID) != 0);
|
||||
int calculate_max_unit_parameter = int(isconnected(SegmentWidth) != 0);
|
||||
int calculate_x_axis_A_angle_bisector = int(isconnected(SegmentRotation) != 0);
|
||||
|
||||
if (calculate_r_gon_parameter_field || calculate_max_unit_parameter ||
|
||||
calculate_x_axis_A_angle_bisector)
|
||||
{
|
||||
vector4 out_variables = calculate_out_variables(calculate_r_gon_parameter_field,
|
||||
calculate_max_unit_parameter,
|
||||
use_normalize,
|
||||
max(Sides, 2.0),
|
||||
clamp(Roundness, 0.0, 1.0),
|
||||
vector2(Vector.x, Vector.y));
|
||||
|
||||
SegmentCoordinates = vector3(out_variables.y, out_variables.x, 0.0);
|
||||
SegmentWidth = out_variables.z;
|
||||
SegmentRotation = out_variables.w;
|
||||
}
|
||||
|
||||
if (calculate_segment_id) {
|
||||
SegmentID = calculate_out_segment_id(max(Sides, 2.0), vector2(Vector.x, Vector.y));
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,87 @@
|
||||
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 */
|
||||
|
||||
/* NOTE: svm_ramp.h, svm_ramp_util.h and node_ramp_util.h must stay consistent */
|
||||
|
||||
color rgb_ramp_lookup(color ramp[], float at, int interpolate, int extrapolate)
|
||||
{
|
||||
float f = at;
|
||||
int table_size = arraylength(ramp);
|
||||
|
||||
if ((f < 0.0 || f > 1.0) && extrapolate) {
|
||||
color t0, dy;
|
||||
if (f < 0.0) {
|
||||
t0 = ramp[0];
|
||||
dy = t0 - ramp[1];
|
||||
f = -f;
|
||||
}
|
||||
else {
|
||||
t0 = ramp[table_size - 1];
|
||||
dy = t0 - ramp[table_size - 2];
|
||||
f = f - 1.0;
|
||||
}
|
||||
return t0 + dy * f * (table_size - 1);
|
||||
}
|
||||
|
||||
f = clamp(at, 0.0, 1.0) * (table_size - 1);
|
||||
|
||||
/* clamp int as well in case of NaN */
|
||||
int i = (int)f;
|
||||
if (i < 0) {
|
||||
i = 0;
|
||||
}
|
||||
if (i >= table_size) {
|
||||
i = table_size - 1;
|
||||
}
|
||||
float t = f - (float)i;
|
||||
|
||||
color result = ramp[i];
|
||||
|
||||
if (interpolate && t > 0.0) {
|
||||
result = (1.0 - t) * result + t * ramp[i + 1];
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
float rgb_ramp_lookup(float ramp[], float at, int interpolate, int extrapolate)
|
||||
{
|
||||
float f = at;
|
||||
int table_size = arraylength(ramp);
|
||||
|
||||
if ((f < 0.0 || f > 1.0) && extrapolate) {
|
||||
float t0, dy;
|
||||
if (f < 0.0) {
|
||||
t0 = ramp[0];
|
||||
dy = t0 - ramp[1];
|
||||
f = -f;
|
||||
}
|
||||
else {
|
||||
t0 = ramp[table_size - 1];
|
||||
dy = t0 - ramp[table_size - 2];
|
||||
f = f - 1.0;
|
||||
}
|
||||
return t0 + dy * f * (table_size - 1);
|
||||
}
|
||||
|
||||
f = clamp(at, 0.0, 1.0) * (table_size - 1);
|
||||
|
||||
/* clamp int as well in case of NaN */
|
||||
int i = (int)f;
|
||||
if (i < 0) {
|
||||
i = 0;
|
||||
}
|
||||
if (i >= table_size) {
|
||||
i = table_size - 1;
|
||||
}
|
||||
float t = f - (float)i;
|
||||
|
||||
float result = ramp[i];
|
||||
|
||||
if (interpolate && t > 0.0) {
|
||||
result = (1.0 - t) * result + t * ramp[i + 1];
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 */
|
||||
|
||||
#include "stdcycles.h"
|
||||
|
||||
shader node_ray_portal_bsdf(color Color = 0.8,
|
||||
vector Position = vector(0.0, 0.0, 0.0),
|
||||
vector Direction = vector(0.0, 0.0, 0.0),
|
||||
output closure color BSDF = 0)
|
||||
{
|
||||
BSDF = Color * ray_portal_bsdf(Position, Direction);
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
/* SPDX-FileCopyrightText: 2011-2025 Blender Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 */
|
||||
|
||||
#include "stdcycles.h"
|
||||
|
||||
shader node_raycast(point Position = P,
|
||||
normal Direction = N,
|
||||
float Length = 1.0,
|
||||
int only_local = 0,
|
||||
float bump_filter_width = 0.0,
|
||||
string float_attribute_names[] = {},
|
||||
string alpha_attribute_names[] = {},
|
||||
string vector_attribute_names[] = {},
|
||||
output float IsHit = 0.0,
|
||||
output float SelfHit = 0.0,
|
||||
output float HitDistance = Length,
|
||||
output point HitPosition = point(0.0, 0.0, 0.0),
|
||||
output normal HitNormal = normal(0.0, 0.0, 0.0),
|
||||
output float float_attributes[32] = {},
|
||||
output float alpha_attributes[32] = {},
|
||||
output vector vector_attributes[32] = {})
|
||||
{
|
||||
float mindist = 0.0;
|
||||
if (bump_filter_width > 0.0) {
|
||||
/* If evaluating for bump mapping at a shifted position, increase min
|
||||
* distance by slightly more than the shift distance to avoid self
|
||||
* intersections. */
|
||||
mindist = bump_filter_width * max(length(Dx(P)), length(Dy(P))) * 1.1;
|
||||
}
|
||||
|
||||
if (trace(Position,
|
||||
Direction,
|
||||
"maxdist",
|
||||
Length,
|
||||
"mindist",
|
||||
mindist,
|
||||
"traceset",
|
||||
only_local ? "__only_local__" : ""))
|
||||
{
|
||||
IsHit = 1.0;
|
||||
getmessage("trace", "hitself", SelfHit);
|
||||
getmessage("trace", "hitdist", HitDistance);
|
||||
getmessage("trace", "P", HitPosition);
|
||||
getmessage("trace", "N", HitNormal);
|
||||
|
||||
for (int i = 0; i < arraylength(float_attribute_names); ++i) {
|
||||
getmessage("trace", float_attribute_names[i], float_attributes[i]);
|
||||
}
|
||||
for (int i = 0; i < arraylength(alpha_attribute_names); ++i) {
|
||||
float data[4] = {0.0, 0.0, 0.0, 0.0};
|
||||
getmessage("trace", alpha_attribute_names[i], data);
|
||||
alpha_attributes[i] = data[3];
|
||||
}
|
||||
for (int i = 0; i < arraylength(vector_attribute_names); ++i) {
|
||||
getmessage("trace", vector_attribute_names[i], vector_attributes[i]);
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (int i = 0; i < arraylength(float_attribute_names); ++i) {
|
||||
float_attributes[i] = 0.0;
|
||||
}
|
||||
for (int i = 0; i < arraylength(alpha_attribute_names); ++i) {
|
||||
alpha_attributes[i] = 0.0;
|
||||
}
|
||||
for (int i = 0; i < arraylength(vector_attribute_names); ++i) {
|
||||
vector_attributes[i] = point(0.0, 0.0, 0.0);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
/* SPDX-FileCopyrightText: 2011-2026 Blender Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 */
|
||||
|
||||
#include "stdcycles.h"
|
||||
|
||||
shader node_raycast_attr_float(int attribute_index = 0,
|
||||
float float_attributes[32] = {},
|
||||
output float value = 0.0)
|
||||
{
|
||||
value = float_attributes[attribute_index];
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
/* SPDX-FileCopyrightText: 2011-2026 Blender Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 */
|
||||
|
||||
#include "stdcycles.h"
|
||||
|
||||
shader node_raycast_attr_vector(int attribute_index = 0,
|
||||
point vector_attributes[32] = {},
|
||||
output point value = point(0.0, 0.0, 0.0))
|
||||
{
|
||||
value = vector_attributes[attribute_index];
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 */
|
||||
|
||||
#include "stdcycles.h"
|
||||
|
||||
shader node_refraction_bsdf(color Color = 0.8,
|
||||
string distribution = "ggx",
|
||||
float Roughness = 0.2,
|
||||
float IOR = 1.45,
|
||||
normal Normal = N,
|
||||
output closure color BSDF = 0)
|
||||
{
|
||||
float f = max(IOR, 1e-5);
|
||||
float eta = backfacing() ? 1.0 / f : f;
|
||||
float roughness = Roughness * Roughness;
|
||||
|
||||
BSDF = Color * microfacet(distribution, Normal, roughness, eta, 1);
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 */
|
||||
|
||||
#include "node_ramp_util.h"
|
||||
#include "stdcycles.h"
|
||||
|
||||
shader node_rgb_curves(color ramp[] = {0.0},
|
||||
float min_x = 0.0,
|
||||
float max_x = 1.0,
|
||||
int extrapolate = 1,
|
||||
|
||||
color ColorIn = 0.0,
|
||||
float Fac = 0.0,
|
||||
output color ColorOut = 0.0)
|
||||
{
|
||||
color c = (ColorIn - color(min_x, min_x, min_x)) / (max_x - min_x);
|
||||
|
||||
color r = rgb_ramp_lookup(ramp, c[0], 1, extrapolate);
|
||||
color g = rgb_ramp_lookup(ramp, c[1], 1, extrapolate);
|
||||
color b = rgb_ramp_lookup(ramp, c[2], 1, extrapolate);
|
||||
|
||||
ColorOut[0] = r[0];
|
||||
ColorOut[1] = g[1];
|
||||
ColorOut[2] = b[2];
|
||||
|
||||
ColorOut = mix(ColorIn, ColorOut, Fac);
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 */
|
||||
|
||||
#include "node_ramp_util.h"
|
||||
#include "stdcycles.h"
|
||||
|
||||
shader node_rgb_ramp(color ramp_color[] = {0.0},
|
||||
float ramp_alpha[] = {0.0},
|
||||
int interpolate = 1,
|
||||
|
||||
float Fac = 0.0,
|
||||
output color Color = 0.0,
|
||||
output float Alpha = 1.0)
|
||||
{
|
||||
Color = rgb_ramp_lookup(ramp_color, Fac, interpolate, 0);
|
||||
Alpha = rgb_ramp_lookup(ramp_alpha, Fac, interpolate, 0);
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user