blender/intern/cycles/kernel/osl/shaders/node_noise_texture.osl
Tenkai Raiko da515aa084 Fix #143940: Only Compute the Noise Node Outputs That Are Actually Used
Performance is improved by roughly 25% when both the Factor and Color
outputs are used in Geometry nodes.

For EEVEE and OSL only a small improvement was measured, as dead code
eliminate can optimize this. But there may be cases where it doesn't
work so best to be explicit.

Pull Request: https://projects.blender.org/blender/blender/pulls/152684
2026-02-16 12:34:41 +01:00

308 lines
10 KiB
Text

/* 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!");
}
}