2023-06-14 16:52:36 +10:00
|
|
|
/* SPDX-FileCopyrightText: 2009-2010 Sony Pictures Imageworks Inc., et al. All Rights Reserved.
|
|
|
|
|
* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
|
2011-04-27 11:58:34 +00:00
|
|
|
*
|
2023-06-14 16:52:36 +10:00
|
|
|
* SPDX-License-Identifier: BSD-3-Clause
|
2011-04-27 11:58:34 +00:00
|
|
|
*
|
2023-06-14 16:52:36 +10:00
|
|
|
* Adapted code from Open Shading Language. */
|
2011-04-27 11:58:34 +00:00
|
|
|
|
|
|
|
|
#include <OSL/genclosure.h>
|
|
|
|
|
#include <OSL/oslclosure.h>
|
|
|
|
|
|
2022-09-08 19:31:44 +02:00
|
|
|
#include "kernel/types.h"
|
|
|
|
|
|
|
|
|
|
#include "kernel/osl/globals.h"
|
|
|
|
|
#include "kernel/osl/services.h"
|
2011-04-27 11:58:34 +00:00
|
|
|
|
2021-10-24 14:19:19 +02:00
|
|
|
#include "util/math.h"
|
|
|
|
|
#include "util/param.h"
|
2011-04-27 11:58:34 +00:00
|
|
|
|
2024-12-26 17:53:57 +01:00
|
|
|
#include "kernel/globals.h"
|
Cycles: merge of cycles-x branch, a major update to the renderer
This includes much improved GPU rendering performance, viewport interactivity,
new shadow catcher, revamped sampling settings, subsurface scattering anisotropy,
new GPU volume sampling, improved PMJ sampling pattern, and more.
Some features have also been removed or changed, breaking backwards compatibility.
Including the removal of the OpenCL backend, for which alternatives are under
development.
Release notes and code docs:
https://wiki.blender.org/wiki/Reference/Release_Notes/3.0/Cycles
https://wiki.blender.org/wiki/Source/Render/Cycles
Credits:
* Sergey Sharybin
* Brecht Van Lommel
* Patrick Mours (OptiX backend)
* Christophe Hery (subsurface scattering anisotropy)
* William Leeson (PMJ sampling pattern)
* Alaska (various fixes and tweaks)
* Thomas Dinges (various fixes)
For the full commit history, see the cycles-x branch. This squashes together
all the changes since intermediate changes would often fail building or tests.
Ref T87839, T87837, T87836
Fixes T90734, T89353, T80267, T80267, T77185, T69800
2021-09-20 17:59:20 +02:00
|
|
|
|
2022-09-12 18:46:20 +02:00
|
|
|
#include "kernel/geom/object.h"
|
|
|
|
|
#include "kernel/util/differential.h"
|
|
|
|
|
|
2025-04-25 19:27:30 +02:00
|
|
|
#include "kernel/osl/camera.h"
|
2022-09-12 18:46:20 +02:00
|
|
|
#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])
|
2012-10-20 12:18:00 +00:00
|
|
|
|
2011-04-27 11:58:34 +00:00
|
|
|
CCL_NAMESPACE_BEGIN
|
|
|
|
|
|
2022-11-09 14:25:32 +01:00
|
|
|
static_assert(sizeof(OSLClosure) == sizeof(OSL::ClosureColor) &&
|
|
|
|
|
sizeof(OSLClosureAdd) == sizeof(OSL::ClosureAdd) &&
|
|
|
|
|
sizeof(OSLClosureMul) == sizeof(OSL::ClosureMul) &&
|
|
|
|
|
sizeof(OSLClosureComponent) == sizeof(OSL::ClosureComponent));
|
Cycles: Refactor: Store Cycles-specific pointers in our own ShaderGlobals
OSL has OSL::ShaderGlobals, which contains all the state for OSL shader
execution. The renderer fills it out and hands a pointer to OSL, and any
callbacks (e.g. for querying attributes) get the pointer back.
In order to store renderer-specific data in it, there's a few opaque pointers
in the struct, but using those has led to a mess of reinterpret_cast<> and
pointer indirection in order to carry all the data around.
However, there is a way to do this nicer: Good old C-style struct inheritance.
In short: Unless you're doing pointer arithmetic, you can just add additional
data at the end of a base struct, and the rest of the code won't care.
In this case, this means that we can have our own ShaderGlobals struct and
add more Cycles-specific data at the end. Additionally, we can replace the
generic opaque void pointers with ones of the correct type, which saves us
from needing to cast them back.
Since we have a copy of ShaderGlobals for GPU OSL anyways, it's just a matter
of refactoring the code a bit to make use of that.
The advantages of this are:
- Avoids casts all over the place, just needs one cast to turn our
ShaderGlobals into the "base" type that OSL expects and one to turn the
pointer that OSL gives us on callbacks back into our "derived" type.
- Removes indirection, all the relevant stuff (sd, kg, state) is now
directly in the ShaderGlobals
- Removes some OSL-specific state from ShaderData, which helps to keep
memory usage down
Pull Request: https://projects.blender.org/blender/blender/pulls/133689
2025-01-28 03:39:00 +01:00
|
|
|
static_assert(sizeof(ShaderGlobals) >= sizeof(OSL::ShaderGlobals) &&
|
|
|
|
|
offsetof(ShaderGlobals, backfacing) == offsetof(OSL::ShaderGlobals, backfacing));
|
2022-11-09 14:25:32 +01:00
|
|
|
|
2012-10-20 12:18:00 +00:00
|
|
|
/* Registration */
|
|
|
|
|
|
2022-09-08 19:31:44 +02:00
|
|
|
#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; \
|
2017-04-18 11:43:09 +02:00
|
|
|
}
|
2022-09-08 19:31:44 +02:00
|
|
|
#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),
|
2017-04-18 11:43:09 +02:00
|
|
|
|
2022-09-08 19:31:44 +02:00
|
|
|
#include "closures_template.h"
|
2022-05-17 16:27:37 +02:00
|
|
|
|
2023-08-10 23:53:37 +02:00
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
2022-09-08 19:31:44 +02:00
|
|
|
void OSLRenderServices::register_closures(OSL::ShadingSystem *ss)
|
2017-04-18 11:43:09 +02:00
|
|
|
{
|
2022-09-08 19:31:44 +02:00
|
|
|
#define OSL_CLOSURE_STRUCT_BEGIN(Upper, lower) \
|
|
|
|
|
ss->register_closure( \
|
|
|
|
|
#lower, OSL_CLOSURE_##Upper##_ID, osl_closure_##lower##_params(), nullptr, nullptr);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2022-09-08 19:31:44 +02:00
|
|
|
#include "closures_template.h"
|
2023-08-10 23:53:37 +02:00
|
|
|
ss->register_closure(
|
|
|
|
|
"layer", OSL_CLOSURE_LAYER_ID, osl_closure_layer_params(), nullptr, nullptr);
|
2017-04-18 11:43:09 +02:00
|
|
|
}
|
2017-11-01 21:07:15 +01:00
|
|
|
|
2022-11-09 14:25:32 +01:00
|
|
|
/* Surface & Background */
|
2022-09-12 18:46:20 +02:00
|
|
|
|
2022-11-09 14:25:32 +01:00
|
|
|
template<>
|
2024-12-29 23:13:45 +01:00
|
|
|
void osl_eval_nodes<SHADER_TYPE_SURFACE>(const ThreadKernelGlobalsCPU *kg,
|
2022-11-09 14:25:32 +01:00
|
|
|
const void *state,
|
|
|
|
|
ShaderData *sd,
|
2025-01-01 18:15:54 +01:00
|
|
|
const uint32_t path_flag)
|
2022-09-12 18:46:20 +02:00
|
|
|
{
|
2022-11-09 14:25:32 +01:00
|
|
|
/* setup shader globals from shader data */
|
Cycles: Refactor: Store Cycles-specific pointers in our own ShaderGlobals
OSL has OSL::ShaderGlobals, which contains all the state for OSL shader
execution. The renderer fills it out and hands a pointer to OSL, and any
callbacks (e.g. for querying attributes) get the pointer back.
In order to store renderer-specific data in it, there's a few opaque pointers
in the struct, but using those has led to a mess of reinterpret_cast<> and
pointer indirection in order to carry all the data around.
However, there is a way to do this nicer: Good old C-style struct inheritance.
In short: Unless you're doing pointer arithmetic, you can just add additional
data at the end of a base struct, and the rest of the code won't care.
In this case, this means that we can have our own ShaderGlobals struct and
add more Cycles-specific data at the end. Additionally, we can replace the
generic opaque void pointers with ones of the correct type, which saves us
from needing to cast them back.
Since we have a copy of ShaderGlobals for GPU OSL anyways, it's just a matter
of refactoring the code a bit to make use of that.
The advantages of this are:
- Avoids casts all over the place, just needs one cast to turn our
ShaderGlobals into the "base" type that OSL expects and one to turn the
pointer that OSL gives us on callbacks back into our "derived" type.
- Removes indirection, all the relevant stuff (sd, kg, state) is now
directly in the ShaderGlobals
- Removes some OSL-specific state from ShaderData, which helps to keep
memory usage down
Pull Request: https://projects.blender.org/blender/blender/pulls/133689
2025-01-28 03:39:00 +01:00
|
|
|
shaderdata_to_shaderglobals(kg, sd, path_flag, &kg->osl.shader_globals);
|
2022-09-12 18:46:20 +02:00
|
|
|
|
|
|
|
|
/* clear trace data */
|
2024-12-29 23:13:45 +01:00
|
|
|
kg->osl.tracedata.init = false;
|
2022-09-12 18:46:20 +02:00
|
|
|
|
|
|
|
|
/* Used by render-services. */
|
Cycles: Refactor: Store Cycles-specific pointers in our own ShaderGlobals
OSL has OSL::ShaderGlobals, which contains all the state for OSL shader
execution. The renderer fills it out and hands a pointer to OSL, and any
callbacks (e.g. for querying attributes) get the pointer back.
In order to store renderer-specific data in it, there's a few opaque pointers
in the struct, but using those has led to a mess of reinterpret_cast<> and
pointer indirection in order to carry all the data around.
However, there is a way to do this nicer: Good old C-style struct inheritance.
In short: Unless you're doing pointer arithmetic, you can just add additional
data at the end of a base struct, and the rest of the code won't care.
In this case, this means that we can have our own ShaderGlobals struct and
add more Cycles-specific data at the end. Additionally, we can replace the
generic opaque void pointers with ones of the correct type, which saves us
from needing to cast them back.
Since we have a copy of ShaderGlobals for GPU OSL anyways, it's just a matter
of refactoring the code a bit to make use of that.
The advantages of this are:
- Avoids casts all over the place, just needs one cast to turn our
ShaderGlobals into the "base" type that OSL expects and one to turn the
pointer that OSL gives us on callbacks back into our "derived" type.
- Removes indirection, all the relevant stuff (sd, kg, state) is now
directly in the ShaderGlobals
- Removes some OSL-specific state from ShaderData, which helps to keep
memory usage down
Pull Request: https://projects.blender.org/blender/blender/pulls/133689
2025-01-28 03:39:00 +01:00
|
|
|
kg->osl.shader_globals.kg = kg;
|
2022-09-12 18:46:20 +02:00
|
|
|
if (path_flag & PATH_RAY_SHADOW) {
|
Cycles: Refactor: Store Cycles-specific pointers in our own ShaderGlobals
OSL has OSL::ShaderGlobals, which contains all the state for OSL shader
execution. The renderer fills it out and hands a pointer to OSL, and any
callbacks (e.g. for querying attributes) get the pointer back.
In order to store renderer-specific data in it, there's a few opaque pointers
in the struct, but using those has led to a mess of reinterpret_cast<> and
pointer indirection in order to carry all the data around.
However, there is a way to do this nicer: Good old C-style struct inheritance.
In short: Unless you're doing pointer arithmetic, you can just add additional
data at the end of a base struct, and the rest of the code won't care.
In this case, this means that we can have our own ShaderGlobals struct and
add more Cycles-specific data at the end. Additionally, we can replace the
generic opaque void pointers with ones of the correct type, which saves us
from needing to cast them back.
Since we have a copy of ShaderGlobals for GPU OSL anyways, it's just a matter
of refactoring the code a bit to make use of that.
The advantages of this are:
- Avoids casts all over the place, just needs one cast to turn our
ShaderGlobals into the "base" type that OSL expects and one to turn the
pointer that OSL gives us on callbacks back into our "derived" type.
- Removes indirection, all the relevant stuff (sd, kg, state) is now
directly in the ShaderGlobals
- Removes some OSL-specific state from ShaderData, which helps to keep
memory usage down
Pull Request: https://projects.blender.org/blender/blender/pulls/133689
2025-01-28 03:39:00 +01:00
|
|
|
kg->osl.shader_globals.path_state = nullptr;
|
|
|
|
|
kg->osl.shader_globals.shadow_path_state = (const IntegratorShadowStateCPU *)state;
|
2022-09-12 18:46:20 +02:00
|
|
|
}
|
|
|
|
|
else {
|
Cycles: Refactor: Store Cycles-specific pointers in our own ShaderGlobals
OSL has OSL::ShaderGlobals, which contains all the state for OSL shader
execution. The renderer fills it out and hands a pointer to OSL, and any
callbacks (e.g. for querying attributes) get the pointer back.
In order to store renderer-specific data in it, there's a few opaque pointers
in the struct, but using those has led to a mess of reinterpret_cast<> and
pointer indirection in order to carry all the data around.
However, there is a way to do this nicer: Good old C-style struct inheritance.
In short: Unless you're doing pointer arithmetic, you can just add additional
data at the end of a base struct, and the rest of the code won't care.
In this case, this means that we can have our own ShaderGlobals struct and
add more Cycles-specific data at the end. Additionally, we can replace the
generic opaque void pointers with ones of the correct type, which saves us
from needing to cast them back.
Since we have a copy of ShaderGlobals for GPU OSL anyways, it's just a matter
of refactoring the code a bit to make use of that.
The advantages of this are:
- Avoids casts all over the place, just needs one cast to turn our
ShaderGlobals into the "base" type that OSL expects and one to turn the
pointer that OSL gives us on callbacks back into our "derived" type.
- Removes indirection, all the relevant stuff (sd, kg, state) is now
directly in the ShaderGlobals
- Removes some OSL-specific state from ShaderData, which helps to keep
memory usage down
Pull Request: https://projects.blender.org/blender/blender/pulls/133689
2025-01-28 03:39:00 +01:00
|
|
|
kg->osl.shader_globals.path_state = (const IntegratorStateCPU *)state;
|
|
|
|
|
kg->osl.shader_globals.shadow_path_state = nullptr;
|
2022-09-12 18:46:20 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* execute shader for this point */
|
2024-12-29 23:13:45 +01:00
|
|
|
OSL::ShadingSystem *ss = (OSL::ShadingSystem *)kg->osl.ss;
|
Cycles: Refactor: Store Cycles-specific pointers in our own ShaderGlobals
OSL has OSL::ShaderGlobals, which contains all the state for OSL shader
execution. The renderer fills it out and hands a pointer to OSL, and any
callbacks (e.g. for querying attributes) get the pointer back.
In order to store renderer-specific data in it, there's a few opaque pointers
in the struct, but using those has led to a mess of reinterpret_cast<> and
pointer indirection in order to carry all the data around.
However, there is a way to do this nicer: Good old C-style struct inheritance.
In short: Unless you're doing pointer arithmetic, you can just add additional
data at the end of a base struct, and the rest of the code won't care.
In this case, this means that we can have our own ShaderGlobals struct and
add more Cycles-specific data at the end. Additionally, we can replace the
generic opaque void pointers with ones of the correct type, which saves us
from needing to cast them back.
Since we have a copy of ShaderGlobals for GPU OSL anyways, it's just a matter
of refactoring the code a bit to make use of that.
The advantages of this are:
- Avoids casts all over the place, just needs one cast to turn our
ShaderGlobals into the "base" type that OSL expects and one to turn the
pointer that OSL gives us on callbacks back into our "derived" type.
- Removes indirection, all the relevant stuff (sd, kg, state) is now
directly in the ShaderGlobals
- Removes some OSL-specific state from ShaderData, which helps to keep
memory usage down
Pull Request: https://projects.blender.org/blender/blender/pulls/133689
2025-01-28 03:39:00 +01:00
|
|
|
OSL::ShaderGlobals *globals = reinterpret_cast<OSL::ShaderGlobals *>(&kg->osl.shader_globals);
|
2024-12-29 23:13:45 +01:00
|
|
|
OSL::ShadingContext *octx = kg->osl.context;
|
2024-12-29 17:32:00 +01:00
|
|
|
const int shader = sd->shader & SHADER_MASK;
|
2022-09-12 18:46:20 +02:00
|
|
|
|
2025-02-24 23:44:14 +01:00
|
|
|
if (sd->object == OBJECT_NONE) {
|
2022-11-09 14:25:32 +01:00
|
|
|
/* background */
|
2024-12-29 23:13:45 +01:00
|
|
|
if (kg->osl.globals->background_state) {
|
2023-12-10 17:08:47 +01:00
|
|
|
ss->execute(*octx,
|
2024-12-29 23:13:45 +01:00
|
|
|
*(kg->osl.globals->background_state),
|
|
|
|
|
kg->osl.thread_index,
|
2023-12-10 17:08:47 +01:00
|
|
|
0,
|
|
|
|
|
*globals,
|
|
|
|
|
nullptr,
|
|
|
|
|
nullptr);
|
2022-09-12 18:46:20 +02:00
|
|
|
}
|
|
|
|
|
}
|
2022-11-09 14:25:32 +01:00
|
|
|
else {
|
|
|
|
|
/* automatic bump shader */
|
2024-12-29 23:13:45 +01:00
|
|
|
if (kg->osl.globals->bump_state[shader]) {
|
2022-11-09 14:25:32 +01:00
|
|
|
/* 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) {
|
|
|
|
|
float data[9];
|
2024-12-29 23:13:45 +01:00
|
|
|
const bool found = kg->osl.globals->services->get_attribute(
|
Cycles: Refactor: Store Cycles-specific pointers in our own ShaderGlobals
OSL has OSL::ShaderGlobals, which contains all the state for OSL shader
execution. The renderer fills it out and hands a pointer to OSL, and any
callbacks (e.g. for querying attributes) get the pointer back.
In order to store renderer-specific data in it, there's a few opaque pointers
in the struct, but using those has led to a mess of reinterpret_cast<> and
pointer indirection in order to carry all the data around.
However, there is a way to do this nicer: Good old C-style struct inheritance.
In short: Unless you're doing pointer arithmetic, you can just add additional
data at the end of a base struct, and the rest of the code won't care.
In this case, this means that we can have our own ShaderGlobals struct and
add more Cycles-specific data at the end. Additionally, we can replace the
generic opaque void pointers with ones of the correct type, which saves us
from needing to cast them back.
Since we have a copy of ShaderGlobals for GPU OSL anyways, it's just a matter
of refactoring the code a bit to make use of that.
The advantages of this are:
- Avoids casts all over the place, just needs one cast to turn our
ShaderGlobals into the "base" type that OSL expects and one to turn the
pointer that OSL gives us on callbacks back into our "derived" type.
- Removes indirection, all the relevant stuff (sd, kg, state) is now
directly in the ShaderGlobals
- Removes some OSL-specific state from ShaderData, which helps to keep
memory usage down
Pull Request: https://projects.blender.org/blender/blender/pulls/133689
2025-01-28 03:39:00 +01:00
|
|
|
globals,
|
2024-12-29 23:13:45 +01:00
|
|
|
true,
|
|
|
|
|
OSLRenderServices::u_empty,
|
|
|
|
|
TypeVector,
|
|
|
|
|
OSLRenderServices::u_geom_undisplaced,
|
|
|
|
|
data);
|
2022-11-09 14:25:32 +01:00
|
|
|
(void)found;
|
|
|
|
|
assert(found);
|
|
|
|
|
|
|
|
|
|
differential3 tmp_dP;
|
2024-12-27 21:50:31 +01:00
|
|
|
sd->P = make_float3(data[0], data[1], data[2]);
|
|
|
|
|
tmp_dP.dx = make_float3(data[3], data[4], data[5]);
|
|
|
|
|
tmp_dP.dy = make_float3(data[6], data[7], data[8]);
|
2022-11-09 14:25:32 +01:00
|
|
|
|
|
|
|
|
object_position_transform(kg, sd, &sd->P);
|
|
|
|
|
object_dir_transform(kg, sd, &tmp_dP.dx);
|
|
|
|
|
object_dir_transform(kg, sd, &tmp_dP.dy);
|
|
|
|
|
|
|
|
|
|
sd->dP = differential_make_compact(tmp_dP);
|
|
|
|
|
|
|
|
|
|
globals->P = TO_VEC3(sd->P);
|
|
|
|
|
globals->dPdx = TO_VEC3(tmp_dP.dx);
|
|
|
|
|
globals->dPdy = TO_VEC3(tmp_dP.dy);
|
|
|
|
|
}
|
|
|
|
|
|
2025-01-29 21:17:21 +01:00
|
|
|
/* execute bump shader */
|
2023-12-10 17:08:47 +01:00
|
|
|
ss->execute(*octx,
|
2024-12-29 23:13:45 +01:00
|
|
|
*(kg->osl.globals->bump_state[shader]),
|
|
|
|
|
kg->osl.thread_index,
|
2023-12-10 17:08:47 +01:00
|
|
|
0,
|
|
|
|
|
*globals,
|
|
|
|
|
nullptr,
|
|
|
|
|
nullptr);
|
2022-11-09 14:25:32 +01:00
|
|
|
|
|
|
|
|
/* reset state */
|
|
|
|
|
sd->P = P;
|
|
|
|
|
sd->dP = dP;
|
|
|
|
|
|
2025-04-28 14:03:55 +02:00
|
|
|
/* Apply bump output to sd->N since it's used for e.g. shadow terminator logic. */
|
|
|
|
|
sd->N = TO_FLOAT3(globals->N);
|
|
|
|
|
|
2022-11-09 14:25:32 +01:00
|
|
|
globals->P = TO_VEC3(P);
|
|
|
|
|
globals->dPdx = TO_VEC3(dPdx);
|
|
|
|
|
globals->dPdy = TO_VEC3(dPdy);
|
|
|
|
|
}
|
2022-09-12 18:46:20 +02:00
|
|
|
|
2022-11-09 14:25:32 +01:00
|
|
|
/* surface shader */
|
2024-12-29 23:13:45 +01:00
|
|
|
if (kg->osl.globals->surface_state[shader]) {
|
2023-12-10 17:08:47 +01:00
|
|
|
ss->execute(*octx,
|
2024-12-29 23:13:45 +01:00
|
|
|
*(kg->osl.globals->surface_state[shader]),
|
|
|
|
|
kg->osl.thread_index,
|
2023-12-10 17:08:47 +01:00
|
|
|
0,
|
|
|
|
|
*globals,
|
|
|
|
|
nullptr,
|
|
|
|
|
nullptr);
|
2022-11-09 14:25:32 +01:00
|
|
|
}
|
2022-09-12 18:46:20 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* flatten closure tree */
|
Cycles: Refactor: Store Cycles-specific pointers in our own ShaderGlobals
OSL has OSL::ShaderGlobals, which contains all the state for OSL shader
execution. The renderer fills it out and hands a pointer to OSL, and any
callbacks (e.g. for querying attributes) get the pointer back.
In order to store renderer-specific data in it, there's a few opaque pointers
in the struct, but using those has led to a mess of reinterpret_cast<> and
pointer indirection in order to carry all the data around.
However, there is a way to do this nicer: Good old C-style struct inheritance.
In short: Unless you're doing pointer arithmetic, you can just add additional
data at the end of a base struct, and the rest of the code won't care.
In this case, this means that we can have our own ShaderGlobals struct and
add more Cycles-specific data at the end. Additionally, we can replace the
generic opaque void pointers with ones of the correct type, which saves us
from needing to cast them back.
Since we have a copy of ShaderGlobals for GPU OSL anyways, it's just a matter
of refactoring the code a bit to make use of that.
The advantages of this are:
- Avoids casts all over the place, just needs one cast to turn our
ShaderGlobals into the "base" type that OSL expects and one to turn the
pointer that OSL gives us on callbacks back into our "derived" type.
- Removes indirection, all the relevant stuff (sd, kg, state) is now
directly in the ShaderGlobals
- Removes some OSL-specific state from ShaderData, which helps to keep
memory usage down
Pull Request: https://projects.blender.org/blender/blender/pulls/133689
2025-01-28 03:39:00 +01:00
|
|
|
if (kg->osl.shader_globals.Ci) {
|
|
|
|
|
flatten_closure_tree(kg, sd, path_flag, kg->osl.shader_globals.Ci);
|
2022-09-12 18:46:20 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-11-09 14:25:32 +01:00
|
|
|
/* Volume */
|
2022-09-12 18:46:20 +02:00
|
|
|
|
2022-11-09 14:25:32 +01:00
|
|
|
template<>
|
2024-12-29 23:13:45 +01:00
|
|
|
void osl_eval_nodes<SHADER_TYPE_VOLUME>(const ThreadKernelGlobalsCPU *kg,
|
2022-11-09 14:25:32 +01:00
|
|
|
const void *state,
|
|
|
|
|
ShaderData *sd,
|
2025-01-01 18:15:54 +01:00
|
|
|
const uint32_t path_flag)
|
2022-09-12 18:46:20 +02:00
|
|
|
{
|
|
|
|
|
/* setup shader globals from shader data */
|
Cycles: Refactor: Store Cycles-specific pointers in our own ShaderGlobals
OSL has OSL::ShaderGlobals, which contains all the state for OSL shader
execution. The renderer fills it out and hands a pointer to OSL, and any
callbacks (e.g. for querying attributes) get the pointer back.
In order to store renderer-specific data in it, there's a few opaque pointers
in the struct, but using those has led to a mess of reinterpret_cast<> and
pointer indirection in order to carry all the data around.
However, there is a way to do this nicer: Good old C-style struct inheritance.
In short: Unless you're doing pointer arithmetic, you can just add additional
data at the end of a base struct, and the rest of the code won't care.
In this case, this means that we can have our own ShaderGlobals struct and
add more Cycles-specific data at the end. Additionally, we can replace the
generic opaque void pointers with ones of the correct type, which saves us
from needing to cast them back.
Since we have a copy of ShaderGlobals for GPU OSL anyways, it's just a matter
of refactoring the code a bit to make use of that.
The advantages of this are:
- Avoids casts all over the place, just needs one cast to turn our
ShaderGlobals into the "base" type that OSL expects and one to turn the
pointer that OSL gives us on callbacks back into our "derived" type.
- Removes indirection, all the relevant stuff (sd, kg, state) is now
directly in the ShaderGlobals
- Removes some OSL-specific state from ShaderData, which helps to keep
memory usage down
Pull Request: https://projects.blender.org/blender/blender/pulls/133689
2025-01-28 03:39:00 +01:00
|
|
|
shaderdata_to_shaderglobals(kg, sd, path_flag, &kg->osl.shader_globals);
|
2022-09-12 18:46:20 +02:00
|
|
|
|
2022-11-09 14:25:32 +01:00
|
|
|
/* clear trace data */
|
2024-12-29 23:13:45 +01:00
|
|
|
kg->osl.tracedata.init = false;
|
2022-09-12 18:46:20 +02:00
|
|
|
|
2022-11-09 14:25:32 +01:00
|
|
|
/* Used by render-services. */
|
Cycles: Refactor: Store Cycles-specific pointers in our own ShaderGlobals
OSL has OSL::ShaderGlobals, which contains all the state for OSL shader
execution. The renderer fills it out and hands a pointer to OSL, and any
callbacks (e.g. for querying attributes) get the pointer back.
In order to store renderer-specific data in it, there's a few opaque pointers
in the struct, but using those has led to a mess of reinterpret_cast<> and
pointer indirection in order to carry all the data around.
However, there is a way to do this nicer: Good old C-style struct inheritance.
In short: Unless you're doing pointer arithmetic, you can just add additional
data at the end of a base struct, and the rest of the code won't care.
In this case, this means that we can have our own ShaderGlobals struct and
add more Cycles-specific data at the end. Additionally, we can replace the
generic opaque void pointers with ones of the correct type, which saves us
from needing to cast them back.
Since we have a copy of ShaderGlobals for GPU OSL anyways, it's just a matter
of refactoring the code a bit to make use of that.
The advantages of this are:
- Avoids casts all over the place, just needs one cast to turn our
ShaderGlobals into the "base" type that OSL expects and one to turn the
pointer that OSL gives us on callbacks back into our "derived" type.
- Removes indirection, all the relevant stuff (sd, kg, state) is now
directly in the ShaderGlobals
- Removes some OSL-specific state from ShaderData, which helps to keep
memory usage down
Pull Request: https://projects.blender.org/blender/blender/pulls/133689
2025-01-28 03:39:00 +01:00
|
|
|
kg->osl.shader_globals.kg = kg;
|
2022-11-09 14:25:32 +01:00
|
|
|
if (path_flag & PATH_RAY_SHADOW) {
|
Cycles: Refactor: Store Cycles-specific pointers in our own ShaderGlobals
OSL has OSL::ShaderGlobals, which contains all the state for OSL shader
execution. The renderer fills it out and hands a pointer to OSL, and any
callbacks (e.g. for querying attributes) get the pointer back.
In order to store renderer-specific data in it, there's a few opaque pointers
in the struct, but using those has led to a mess of reinterpret_cast<> and
pointer indirection in order to carry all the data around.
However, there is a way to do this nicer: Good old C-style struct inheritance.
In short: Unless you're doing pointer arithmetic, you can just add additional
data at the end of a base struct, and the rest of the code won't care.
In this case, this means that we can have our own ShaderGlobals struct and
add more Cycles-specific data at the end. Additionally, we can replace the
generic opaque void pointers with ones of the correct type, which saves us
from needing to cast them back.
Since we have a copy of ShaderGlobals for GPU OSL anyways, it's just a matter
of refactoring the code a bit to make use of that.
The advantages of this are:
- Avoids casts all over the place, just needs one cast to turn our
ShaderGlobals into the "base" type that OSL expects and one to turn the
pointer that OSL gives us on callbacks back into our "derived" type.
- Removes indirection, all the relevant stuff (sd, kg, state) is now
directly in the ShaderGlobals
- Removes some OSL-specific state from ShaderData, which helps to keep
memory usage down
Pull Request: https://projects.blender.org/blender/blender/pulls/133689
2025-01-28 03:39:00 +01:00
|
|
|
kg->osl.shader_globals.path_state = nullptr;
|
|
|
|
|
kg->osl.shader_globals.shadow_path_state = (const IntegratorShadowStateCPU *)state;
|
2022-09-12 18:46:20 +02:00
|
|
|
}
|
2022-11-09 14:25:32 +01:00
|
|
|
else {
|
Cycles: Refactor: Store Cycles-specific pointers in our own ShaderGlobals
OSL has OSL::ShaderGlobals, which contains all the state for OSL shader
execution. The renderer fills it out and hands a pointer to OSL, and any
callbacks (e.g. for querying attributes) get the pointer back.
In order to store renderer-specific data in it, there's a few opaque pointers
in the struct, but using those has led to a mess of reinterpret_cast<> and
pointer indirection in order to carry all the data around.
However, there is a way to do this nicer: Good old C-style struct inheritance.
In short: Unless you're doing pointer arithmetic, you can just add additional
data at the end of a base struct, and the rest of the code won't care.
In this case, this means that we can have our own ShaderGlobals struct and
add more Cycles-specific data at the end. Additionally, we can replace the
generic opaque void pointers with ones of the correct type, which saves us
from needing to cast them back.
Since we have a copy of ShaderGlobals for GPU OSL anyways, it's just a matter
of refactoring the code a bit to make use of that.
The advantages of this are:
- Avoids casts all over the place, just needs one cast to turn our
ShaderGlobals into the "base" type that OSL expects and one to turn the
pointer that OSL gives us on callbacks back into our "derived" type.
- Removes indirection, all the relevant stuff (sd, kg, state) is now
directly in the ShaderGlobals
- Removes some OSL-specific state from ShaderData, which helps to keep
memory usage down
Pull Request: https://projects.blender.org/blender/blender/pulls/133689
2025-01-28 03:39:00 +01:00
|
|
|
kg->osl.shader_globals.path_state = (const IntegratorStateCPU *)state;
|
|
|
|
|
kg->osl.shader_globals.shadow_path_state = nullptr;
|
2022-09-12 18:46:20 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* execute shader */
|
2024-12-29 23:13:45 +01:00
|
|
|
OSL::ShadingSystem *ss = (OSL::ShadingSystem *)kg->osl.ss;
|
Cycles: Refactor: Store Cycles-specific pointers in our own ShaderGlobals
OSL has OSL::ShaderGlobals, which contains all the state for OSL shader
execution. The renderer fills it out and hands a pointer to OSL, and any
callbacks (e.g. for querying attributes) get the pointer back.
In order to store renderer-specific data in it, there's a few opaque pointers
in the struct, but using those has led to a mess of reinterpret_cast<> and
pointer indirection in order to carry all the data around.
However, there is a way to do this nicer: Good old C-style struct inheritance.
In short: Unless you're doing pointer arithmetic, you can just add additional
data at the end of a base struct, and the rest of the code won't care.
In this case, this means that we can have our own ShaderGlobals struct and
add more Cycles-specific data at the end. Additionally, we can replace the
generic opaque void pointers with ones of the correct type, which saves us
from needing to cast them back.
Since we have a copy of ShaderGlobals for GPU OSL anyways, it's just a matter
of refactoring the code a bit to make use of that.
The advantages of this are:
- Avoids casts all over the place, just needs one cast to turn our
ShaderGlobals into the "base" type that OSL expects and one to turn the
pointer that OSL gives us on callbacks back into our "derived" type.
- Removes indirection, all the relevant stuff (sd, kg, state) is now
directly in the ShaderGlobals
- Removes some OSL-specific state from ShaderData, which helps to keep
memory usage down
Pull Request: https://projects.blender.org/blender/blender/pulls/133689
2025-01-28 03:39:00 +01:00
|
|
|
OSL::ShaderGlobals *globals = reinterpret_cast<OSL::ShaderGlobals *>(&kg->osl.shader_globals);
|
2024-12-29 23:13:45 +01:00
|
|
|
OSL::ShadingContext *octx = kg->osl.context;
|
2024-12-29 17:32:00 +01:00
|
|
|
const int shader = sd->shader & SHADER_MASK;
|
2022-09-12 18:46:20 +02:00
|
|
|
|
2024-12-29 23:13:45 +01:00
|
|
|
if (kg->osl.globals->volume_state[shader]) {
|
2023-12-10 17:08:47 +01:00
|
|
|
ss->execute(*octx,
|
2024-12-29 23:13:45 +01:00
|
|
|
*(kg->osl.globals->volume_state[shader]),
|
|
|
|
|
kg->osl.thread_index,
|
2023-12-10 17:08:47 +01:00
|
|
|
0,
|
|
|
|
|
*globals,
|
|
|
|
|
nullptr,
|
|
|
|
|
nullptr);
|
2022-09-12 18:46:20 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* flatten closure tree */
|
Cycles: Refactor: Store Cycles-specific pointers in our own ShaderGlobals
OSL has OSL::ShaderGlobals, which contains all the state for OSL shader
execution. The renderer fills it out and hands a pointer to OSL, and any
callbacks (e.g. for querying attributes) get the pointer back.
In order to store renderer-specific data in it, there's a few opaque pointers
in the struct, but using those has led to a mess of reinterpret_cast<> and
pointer indirection in order to carry all the data around.
However, there is a way to do this nicer: Good old C-style struct inheritance.
In short: Unless you're doing pointer arithmetic, you can just add additional
data at the end of a base struct, and the rest of the code won't care.
In this case, this means that we can have our own ShaderGlobals struct and
add more Cycles-specific data at the end. Additionally, we can replace the
generic opaque void pointers with ones of the correct type, which saves us
from needing to cast them back.
Since we have a copy of ShaderGlobals for GPU OSL anyways, it's just a matter
of refactoring the code a bit to make use of that.
The advantages of this are:
- Avoids casts all over the place, just needs one cast to turn our
ShaderGlobals into the "base" type that OSL expects and one to turn the
pointer that OSL gives us on callbacks back into our "derived" type.
- Removes indirection, all the relevant stuff (sd, kg, state) is now
directly in the ShaderGlobals
- Removes some OSL-specific state from ShaderData, which helps to keep
memory usage down
Pull Request: https://projects.blender.org/blender/blender/pulls/133689
2025-01-28 03:39:00 +01:00
|
|
|
if (kg->osl.shader_globals.Ci) {
|
|
|
|
|
flatten_closure_tree(kg, sd, path_flag, kg->osl.shader_globals.Ci);
|
2022-09-12 18:46:20 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Displacement */
|
|
|
|
|
|
2022-11-09 14:25:32 +01:00
|
|
|
template<>
|
2024-12-29 23:13:45 +01:00
|
|
|
void osl_eval_nodes<SHADER_TYPE_DISPLACEMENT>(const ThreadKernelGlobalsCPU *kg,
|
2022-11-09 14:25:32 +01:00
|
|
|
const void *state,
|
|
|
|
|
ShaderData *sd,
|
2025-01-01 18:15:54 +01:00
|
|
|
const uint32_t path_flag)
|
2022-09-12 18:46:20 +02:00
|
|
|
{
|
|
|
|
|
/* setup shader globals from shader data */
|
Cycles: Refactor: Store Cycles-specific pointers in our own ShaderGlobals
OSL has OSL::ShaderGlobals, which contains all the state for OSL shader
execution. The renderer fills it out and hands a pointer to OSL, and any
callbacks (e.g. for querying attributes) get the pointer back.
In order to store renderer-specific data in it, there's a few opaque pointers
in the struct, but using those has led to a mess of reinterpret_cast<> and
pointer indirection in order to carry all the data around.
However, there is a way to do this nicer: Good old C-style struct inheritance.
In short: Unless you're doing pointer arithmetic, you can just add additional
data at the end of a base struct, and the rest of the code won't care.
In this case, this means that we can have our own ShaderGlobals struct and
add more Cycles-specific data at the end. Additionally, we can replace the
generic opaque void pointers with ones of the correct type, which saves us
from needing to cast them back.
Since we have a copy of ShaderGlobals for GPU OSL anyways, it's just a matter
of refactoring the code a bit to make use of that.
The advantages of this are:
- Avoids casts all over the place, just needs one cast to turn our
ShaderGlobals into the "base" type that OSL expects and one to turn the
pointer that OSL gives us on callbacks back into our "derived" type.
- Removes indirection, all the relevant stuff (sd, kg, state) is now
directly in the ShaderGlobals
- Removes some OSL-specific state from ShaderData, which helps to keep
memory usage down
Pull Request: https://projects.blender.org/blender/blender/pulls/133689
2025-01-28 03:39:00 +01:00
|
|
|
shaderdata_to_shaderglobals(kg, sd, path_flag, &kg->osl.shader_globals);
|
2022-11-09 14:25:32 +01:00
|
|
|
|
|
|
|
|
/* clear trace data */
|
2024-12-29 23:13:45 +01:00
|
|
|
kg->osl.tracedata.init = false;
|
2022-11-09 14:25:32 +01:00
|
|
|
|
|
|
|
|
/* Used by render-services. */
|
Cycles: Refactor: Store Cycles-specific pointers in our own ShaderGlobals
OSL has OSL::ShaderGlobals, which contains all the state for OSL shader
execution. The renderer fills it out and hands a pointer to OSL, and any
callbacks (e.g. for querying attributes) get the pointer back.
In order to store renderer-specific data in it, there's a few opaque pointers
in the struct, but using those has led to a mess of reinterpret_cast<> and
pointer indirection in order to carry all the data around.
However, there is a way to do this nicer: Good old C-style struct inheritance.
In short: Unless you're doing pointer arithmetic, you can just add additional
data at the end of a base struct, and the rest of the code won't care.
In this case, this means that we can have our own ShaderGlobals struct and
add more Cycles-specific data at the end. Additionally, we can replace the
generic opaque void pointers with ones of the correct type, which saves us
from needing to cast them back.
Since we have a copy of ShaderGlobals for GPU OSL anyways, it's just a matter
of refactoring the code a bit to make use of that.
The advantages of this are:
- Avoids casts all over the place, just needs one cast to turn our
ShaderGlobals into the "base" type that OSL expects and one to turn the
pointer that OSL gives us on callbacks back into our "derived" type.
- Removes indirection, all the relevant stuff (sd, kg, state) is now
directly in the ShaderGlobals
- Removes some OSL-specific state from ShaderData, which helps to keep
memory usage down
Pull Request: https://projects.blender.org/blender/blender/pulls/133689
2025-01-28 03:39:00 +01:00
|
|
|
kg->osl.shader_globals.kg = kg;
|
|
|
|
|
kg->osl.shader_globals.path_state = (const IntegratorStateCPU *)state;
|
|
|
|
|
kg->osl.shader_globals.shadow_path_state = nullptr;
|
2022-09-12 18:46:20 +02:00
|
|
|
|
|
|
|
|
/* execute shader */
|
2024-12-29 23:13:45 +01:00
|
|
|
OSL::ShadingSystem *ss = (OSL::ShadingSystem *)kg->osl.ss;
|
Cycles: Refactor: Store Cycles-specific pointers in our own ShaderGlobals
OSL has OSL::ShaderGlobals, which contains all the state for OSL shader
execution. The renderer fills it out and hands a pointer to OSL, and any
callbacks (e.g. for querying attributes) get the pointer back.
In order to store renderer-specific data in it, there's a few opaque pointers
in the struct, but using those has led to a mess of reinterpret_cast<> and
pointer indirection in order to carry all the data around.
However, there is a way to do this nicer: Good old C-style struct inheritance.
In short: Unless you're doing pointer arithmetic, you can just add additional
data at the end of a base struct, and the rest of the code won't care.
In this case, this means that we can have our own ShaderGlobals struct and
add more Cycles-specific data at the end. Additionally, we can replace the
generic opaque void pointers with ones of the correct type, which saves us
from needing to cast them back.
Since we have a copy of ShaderGlobals for GPU OSL anyways, it's just a matter
of refactoring the code a bit to make use of that.
The advantages of this are:
- Avoids casts all over the place, just needs one cast to turn our
ShaderGlobals into the "base" type that OSL expects and one to turn the
pointer that OSL gives us on callbacks back into our "derived" type.
- Removes indirection, all the relevant stuff (sd, kg, state) is now
directly in the ShaderGlobals
- Removes some OSL-specific state from ShaderData, which helps to keep
memory usage down
Pull Request: https://projects.blender.org/blender/blender/pulls/133689
2025-01-28 03:39:00 +01:00
|
|
|
OSL::ShaderGlobals *globals = reinterpret_cast<OSL::ShaderGlobals *>(&kg->osl.shader_globals);
|
2024-12-29 23:13:45 +01:00
|
|
|
OSL::ShadingContext *octx = kg->osl.context;
|
2024-12-29 17:32:00 +01:00
|
|
|
const int shader = sd->shader & SHADER_MASK;
|
2022-09-12 18:46:20 +02:00
|
|
|
|
2024-12-29 23:13:45 +01:00
|
|
|
if (kg->osl.globals->displacement_state[shader]) {
|
2023-12-10 17:08:47 +01:00
|
|
|
ss->execute(*octx,
|
2024-12-29 23:13:45 +01:00
|
|
|
*(kg->osl.globals->displacement_state[shader]),
|
|
|
|
|
kg->osl.thread_index,
|
2023-12-10 17:08:47 +01:00
|
|
|
0,
|
|
|
|
|
*globals,
|
|
|
|
|
nullptr,
|
|
|
|
|
nullptr);
|
2022-09-12 18:46:20 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* get back position */
|
|
|
|
|
sd->P = TO_FLOAT3(globals->P);
|
|
|
|
|
}
|
|
|
|
|
|
2025-04-25 19:27:30 +02:00
|
|
|
/* Camera */
|
|
|
|
|
|
|
|
|
|
packed_float3 osl_eval_camera(const ThreadKernelGlobalsCPU *kg,
|
|
|
|
|
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->osl.globals->camera_state) {
|
|
|
|
|
return zero_spectrum();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Setup shader globals from from the sensor position. */
|
|
|
|
|
cameradata_to_shaderglobals(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]);
|
|
|
|
|
}
|
|
|
|
|
|
2011-04-27 11:58:34 +00:00
|
|
|
CCL_NAMESPACE_END
|