1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180
//! Helpers for using ɴsɪ with 3Delight.
//!
//! Shortcuts for instancing common nodes.
use nsi_core as nsi;
use nsi_toolbelt::{append, generate_or_use_handle, node, rotation};
/// Creates a typical environment node.
///
/// A latitutde-lungitude environment map will be aligned as-shot
/// with the horizon along the X-Z plane at infinity.
///
/// If `handle` is [`None`] a random handle is generated.
///
/// # Arguments
/// * `angle` – In degrees; specifies how much to rotate the environment around
/// the Y (up) axis.
///
/// * `visible` – If the environment is visible to the camera.
///
/// Returns `handle` and the handle of the created `shader`.
///
/// Note that the `shader` node is empty. It is up to the user
/// to set the resp. attributes on the node or hook up an OSL
/// network below it.
pub fn environment(
ctx: &nsi::Context,
handle: Option<&str>,
angle: Option<f64>,
visible: Option<bool>,
) -> (String, String) {
// Create a rotation transform – this is the handle we return.
let rotation = rotation(ctx, None, angle.unwrap_or(0.0), &[0.0, 1.0, 0.0]);
let environment = generate_or_use_handle(handle, Some("environment"));
// Set up an environment light.
append(
ctx,
&rotation,
None,
&node(
ctx,
Some(environment.as_str()),
nsi::node::ENVIRONMENT,
None,
),
);
let shader = node(ctx, None, nsi::node::SHADER, None);
append(
ctx,
&environment,
Some("geometryattributes"),
append(
ctx,
&node(
ctx,
None,
nsi::node::ATTRIBUTES,
Some(&[nsi::integer!(
"visibility.camera",
visible.unwrap_or(true) as _
)]),
),
Some("surfaceshader"),
shader.as_str(),
)
.0,
);
(rotation, shader)
}
/// Creates a textured environment light.
///
/// If `handle` is [`None`] a random handle is generated.
///
/// # Arguments
/// * `texture – A latitude-longitude texture map in one of these formats:
/// * TIFF
/// * JPEG
/// * Radiance
/// * OpenEXR
/// * GIF
/// * IFF
/// * SGI
/// * PIC
/// * Photoshop PSD
/// * TGA
///
/// * `angle` – In degrees; specifies how much to rotate the environment around
/// the Y (up) axis.
///
/// * `exposure` – Scales the intensity in [stops or EV values](https://en.wikipedia.org/wiki/Exposure_value).
///
/// * `visible` – If the environment is visible to the camera.
///
/// Returns `handle` and the handle of the created `shader`.
///
/// Note that the `shader` node is empty. It is up to the user
/// to set the resp. attributes on the node or hook up an OSL
/// network below it.
pub fn environment_texture<'a, 'b>(
ctx: &nsi::Context<'a>,
handle: Option<&str>,
texture: &str,
angle: Option<f64>,
exposure: Option<f32>,
visible: Option<bool>,
args: Option<&nsi::ArgSlice<'b, 'a>>,
) -> (String, String)
where
'a: 'b,
{
let (rotation, shader) = environment(ctx, handle, angle, visible);
// Environment light attributes.
ctx.set_attribute(
shader.as_str(),
&[
nsi::string!("shaderfilename", "${DELIGHT}/osl/environmentLight"),
nsi::float!("intensity", 2.0f32.powf(exposure.unwrap_or(0.0))),
nsi::string!("image", texture),
],
);
if let Some(args) = args {
ctx.set_attribute(shader.as_str(), args);
}
(rotation, shader)
}
/// **Convenience method; not part of the official ɴsɪ API.**
///
/// Creates a physically plausible, procedural sky environment light.
///
/// If `handle` is [`None`] a random handle is generated.
///
/// # Arguments
/// * `angle` – In degrees; specifies how much to rotate the environment around
/// the Y (up) axis.
///
/// * `exposure` – Scales the intensity in [stops or EV values](https://en.wikipedia.org/wiki/Exposure_value).
///
/// * `visible` – If the environment is visible to the camera.
///
/// Returns `handle` and the handle of the created `shader`.
///
/// Note that this instances a `dlSky` shader. Using the returned `shader`
/// handle you can set more attributes on this node.
pub fn environment_sky<'a, 'b>(
ctx: &nsi::Context<'a>,
handle: Option<&str>,
angle: Option<f64>,
exposure: Option<f32>,
visible: Option<bool>,
args: Option<&nsi::ArgSlice<'b, 'a>>,
) -> (String, String)
where
'a: 'b,
{
let (rotation, shader) = environment(ctx, handle, angle, visible);
// Environment light attributes.
ctx.set_attribute(
shader.as_str(),
&[
nsi::string!("shaderfilename", "${DELIGHT}/osl/dlSky"),
nsi::float!("intensity", 2.0f32.powf(exposure.unwrap_or(0.0))),
],
);
if let Some(args) = args {
ctx.set_attribute(shader.as_str(), args);
}
(rotation, shader)
}