This path merges the Musgrave and Noise Texture nodes into a single combined Noise Texture node. The reasoning is that both nodes intrinsically do the same thing, which is the layering of Perlin noise derivatives to produce fractal noise. So the patch de-duplicates code and unifies the use of fractal noise for the end use. Since the Noise node had a Distortion input and a Color output, while the Musgrave node did not, those are now available to the Musgrave types as new functionalities. The Dimension input of the Musgrave node is analogous to the Roughness input of the Noise node, so both inputs were unified to follow the same behavior of the Roughness input, which is arguable more intuitive to control. Similarly, the Detail input was slightly different across both nodes, since the Noise node evaluated one extra layer of noise. This was also unified to follow the behavior of the Noise node. The patch, coincidentally fixes an unreported bug causing repeated output for certain noise types and another floating precision bug #112180. The versioning code implemented with this patch ensures backward compatibility for both the Musgrave and Noise Texture nodes. When opening older Blender files in Blender 4.1 the output of both nodes are guaranteed to always be exactly identical to that of Blender files created before the nodes were merged in all cases. Forward compatibility with Blender 4.0 is implemented by #114236. Forward compatibility with Blender 3.6 LTS is implemented by #115015. Pull Request: #111187
123 lines
4.0 KiB
C
123 lines
4.0 KiB
C
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0 */
|
|
|
|
#pragma once
|
|
|
|
CCL_NAMESPACE_BEGIN
|
|
|
|
/* Wave */
|
|
|
|
ccl_device_noinline_cpu float svm_wave(NodeWaveType type,
|
|
NodeWaveBandsDirection bands_dir,
|
|
NodeWaveRingsDirection rings_dir,
|
|
NodeWaveProfile profile,
|
|
float3 p,
|
|
float distortion,
|
|
float detail,
|
|
float dscale,
|
|
float droughness,
|
|
float phase)
|
|
{
|
|
/* Prevent precision issues on unit coordinates. */
|
|
p = (p + 0.000001f) * 0.999999f;
|
|
|
|
float n;
|
|
|
|
if (type == NODE_WAVE_BANDS) {
|
|
if (bands_dir == NODE_WAVE_BANDS_DIRECTION_X) {
|
|
n = p.x * 20.0f;
|
|
}
|
|
else if (bands_dir == NODE_WAVE_BANDS_DIRECTION_Y) {
|
|
n = p.y * 20.0f;
|
|
}
|
|
else if (bands_dir == NODE_WAVE_BANDS_DIRECTION_Z) {
|
|
n = p.z * 20.0f;
|
|
}
|
|
else { /* NODE_WAVE_BANDS_DIRECTION_DIAGONAL */
|
|
n = (p.x + p.y + p.z) * 10.0f;
|
|
}
|
|
}
|
|
else { /* NODE_WAVE_RINGS */
|
|
float3 rp = p;
|
|
if (rings_dir == NODE_WAVE_RINGS_DIRECTION_X) {
|
|
rp *= make_float3(0.0f, 1.0f, 1.0f);
|
|
}
|
|
else if (rings_dir == NODE_WAVE_RINGS_DIRECTION_Y) {
|
|
rp *= make_float3(1.0f, 0.0f, 1.0f);
|
|
}
|
|
else if (rings_dir == NODE_WAVE_RINGS_DIRECTION_Z) {
|
|
rp *= make_float3(1.0f, 1.0f, 0.0f);
|
|
}
|
|
/* else: NODE_WAVE_RINGS_DIRECTION_SPHERICAL */
|
|
|
|
n = len(rp) * 20.0f;
|
|
}
|
|
|
|
n += phase;
|
|
|
|
if (distortion != 0.0f) {
|
|
n += distortion * (noise_fbm(p * dscale, detail, droughness, 2.0f, true) * 2.0f - 1.0f);
|
|
}
|
|
|
|
if (profile == NODE_WAVE_PROFILE_SIN) {
|
|
return 0.5f + 0.5f * sinf(n - M_PI_2_F);
|
|
}
|
|
else if (profile == NODE_WAVE_PROFILE_SAW) {
|
|
n /= M_2PI_F;
|
|
return n - floorf(n);
|
|
}
|
|
else { /* NODE_WAVE_PROFILE_TRI */
|
|
n /= M_2PI_F;
|
|
return fabsf(n - floorf(n + 0.5f)) * 2.0f;
|
|
}
|
|
}
|
|
|
|
ccl_device_noinline int svm_node_tex_wave(
|
|
KernelGlobals kg, ccl_private ShaderData *sd, ccl_private float *stack, uint4 node, int offset)
|
|
{
|
|
uint4 node2 = read_node(kg, &offset);
|
|
uint4 node3 = read_node(kg, &offset);
|
|
|
|
/* RNA properties */
|
|
uint type_offset, bands_dir_offset, rings_dir_offset, profile_offset;
|
|
/* Inputs, Outputs */
|
|
uint co_offset, scale_offset, distortion_offset, detail_offset, dscale_offset, droughness_offset,
|
|
phase_offset;
|
|
uint color_offset, fac_offset;
|
|
|
|
svm_unpack_node_uchar4(
|
|
node.y, &type_offset, &bands_dir_offset, &rings_dir_offset, &profile_offset);
|
|
svm_unpack_node_uchar3(node.z, &co_offset, &scale_offset, &distortion_offset);
|
|
svm_unpack_node_uchar4(
|
|
node.w, &detail_offset, &dscale_offset, &droughness_offset, &phase_offset);
|
|
svm_unpack_node_uchar2(node2.x, &color_offset, &fac_offset);
|
|
|
|
float3 co = stack_load_float3(stack, co_offset);
|
|
float scale = stack_load_float_default(stack, scale_offset, node2.y);
|
|
float distortion = stack_load_float_default(stack, distortion_offset, node2.z);
|
|
float detail = stack_load_float_default(stack, detail_offset, node2.w);
|
|
float dscale = stack_load_float_default(stack, dscale_offset, node3.x);
|
|
float droughness = stack_load_float_default(stack, droughness_offset, node3.y);
|
|
float phase = stack_load_float_default(stack, phase_offset, node3.z);
|
|
|
|
float f = svm_wave((NodeWaveType)type_offset,
|
|
(NodeWaveBandsDirection)bands_dir_offset,
|
|
(NodeWaveRingsDirection)rings_dir_offset,
|
|
(NodeWaveProfile)profile_offset,
|
|
co * scale,
|
|
distortion,
|
|
detail,
|
|
dscale,
|
|
droughness,
|
|
phase);
|
|
|
|
if (stack_valid(fac_offset))
|
|
stack_store_float(stack, fac_offset, f);
|
|
if (stack_valid(color_offset))
|
|
stack_store_float3(stack, color_offset, make_float3(f, f, f));
|
|
return offset;
|
|
}
|
|
|
|
CCL_NAMESPACE_END
|