Files
test/intern/cycles/kernel/osl/shaders/node_noise_texture.osl
Hoshinova 0b11c591ec Nodes: Merge Musgrave node into Noise node
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
2023-11-18 09:40:44 +01:00

301 lines
10 KiB
Plaintext

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