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
This commit is contained in:
@@ -936,20 +936,12 @@ static ShaderNode *add_node(Scene *scene,
|
||||
BL::ShaderNodeTexNoise b_noise_node(b_node);
|
||||
NoiseTextureNode *noise = graph->create_node<NoiseTextureNode>();
|
||||
noise->set_dimensions(b_noise_node.noise_dimensions());
|
||||
noise->set_type((NodeNoiseType)b_noise_node.type());
|
||||
noise->set_use_normalize(b_noise_node.normalize());
|
||||
BL::TexMapping b_texture_mapping(b_noise_node.texture_mapping());
|
||||
get_tex_mapping(noise, b_texture_mapping);
|
||||
node = noise;
|
||||
}
|
||||
else if (b_node.is_a(&RNA_ShaderNodeTexMusgrave)) {
|
||||
BL::ShaderNodeTexMusgrave b_musgrave_node(b_node);
|
||||
MusgraveTextureNode *musgrave_node = graph->create_node<MusgraveTextureNode>();
|
||||
musgrave_node->set_musgrave_type((NodeMusgraveType)b_musgrave_node.musgrave_type());
|
||||
musgrave_node->set_dimensions(b_musgrave_node.musgrave_dimensions());
|
||||
BL::TexMapping b_texture_mapping(b_musgrave_node.texture_mapping());
|
||||
get_tex_mapping(musgrave_node, b_texture_mapping);
|
||||
node = musgrave_node;
|
||||
}
|
||||
else if (b_node.is_a(&RNA_ShaderNodeTexCoord)) {
|
||||
BL::ShaderNodeTexCoord b_tex_coord_node(b_node);
|
||||
TextureCoordinateNode *tex_coord = graph->create_node<TextureCoordinateNode>();
|
||||
|
||||
@@ -178,7 +178,6 @@ set(SRC_KERNEL_SVM_HEADERS
|
||||
svm/math.h
|
||||
svm/math_util.h
|
||||
svm/mix.h
|
||||
svm/musgrave.h
|
||||
svm/node_types_template.h
|
||||
svm/noise.h
|
||||
svm/noisetex.h
|
||||
|
||||
@@ -61,7 +61,6 @@ set(SRC_OSL
|
||||
node_mix_float.osl
|
||||
node_mix_vector.osl
|
||||
node_mix_vector_non_uniform.osl
|
||||
node_musgrave_texture.osl
|
||||
node_noise_texture.osl
|
||||
node_normal.osl
|
||||
node_normal_map.osl
|
||||
|
||||
@@ -1,803 +0,0 @@
|
||||
/* 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
|
||||
|
||||
/* 1D Musgrave fBm
|
||||
*
|
||||
* H: fractal increment parameter
|
||||
* lacunarity: gap between successive frequencies
|
||||
* octaves: number of frequencies in the fBm
|
||||
*
|
||||
* from "Texturing and Modelling: A procedural approach"
|
||||
*/
|
||||
|
||||
float noise_musgrave_fBm_1d(float co, float H, float lacunarity, float octaves)
|
||||
{
|
||||
float p = co;
|
||||
float value = 0.0;
|
||||
float pwr = 1.0;
|
||||
float pwHL = pow(lacunarity, -H);
|
||||
|
||||
for (int i = 0; i < (int)octaves; i++) {
|
||||
value += safe_snoise(p) * pwr;
|
||||
pwr *= pwHL;
|
||||
p *= lacunarity;
|
||||
}
|
||||
|
||||
float rmd = octaves - floor(octaves);
|
||||
if (rmd != 0.0) {
|
||||
value += rmd * safe_snoise(p) * pwr;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
/* 1D Musgrave Multifractal
|
||||
*
|
||||
* H: highest fractal dimension
|
||||
* lacunarity: gap between successive frequencies
|
||||
* octaves: number of frequencies in the fBm
|
||||
*/
|
||||
|
||||
float noise_musgrave_multi_fractal_1d(float co, float H, float lacunarity, float octaves)
|
||||
{
|
||||
float p = co;
|
||||
float value = 1.0;
|
||||
float pwr = 1.0;
|
||||
float pwHL = pow(lacunarity, -H);
|
||||
|
||||
for (int i = 0; i < (int)octaves; i++) {
|
||||
value *= (pwr * safe_snoise(p) + 1.0);
|
||||
pwr *= pwHL;
|
||||
p *= lacunarity;
|
||||
}
|
||||
|
||||
float rmd = octaves - floor(octaves);
|
||||
if (rmd != 0.0) {
|
||||
value *= (rmd * pwr * safe_snoise(p) + 1.0); /* correct? */
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
/* 1D Musgrave Heterogeneous Terrain
|
||||
*
|
||||
* H: fractal dimension of the roughest area
|
||||
* lacunarity: gap between successive frequencies
|
||||
* octaves: number of frequencies in the fBm
|
||||
* offset: raises the terrain from `sea level'
|
||||
*/
|
||||
|
||||
float noise_musgrave_hetero_terrain_1d(
|
||||
float co, float H, float lacunarity, float octaves, float offset)
|
||||
{
|
||||
float p = co;
|
||||
float pwHL = pow(lacunarity, -H);
|
||||
float pwr = pwHL;
|
||||
|
||||
/* first unscaled octave of function; later octaves are scaled */
|
||||
float value = offset + safe_snoise(p);
|
||||
p *= lacunarity;
|
||||
|
||||
for (int i = 1; i < (int)octaves; i++) {
|
||||
float increment = (safe_snoise(p) + offset) * pwr * value;
|
||||
value += increment;
|
||||
pwr *= pwHL;
|
||||
p *= lacunarity;
|
||||
}
|
||||
|
||||
float rmd = octaves - floor(octaves);
|
||||
if (rmd != 0.0) {
|
||||
float increment = (safe_snoise(p) + offset) * pwr * value;
|
||||
value += rmd * increment;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
/* 1D Hybrid Additive/Multiplicative Multifractal Terrain
|
||||
*
|
||||
* H: fractal dimension of the roughest area
|
||||
* lacunarity: gap between successive frequencies
|
||||
* octaves: number of frequencies in the fBm
|
||||
* offset: raises the terrain from `sea level'
|
||||
*/
|
||||
|
||||
float noise_musgrave_hybrid_multi_fractal_1d(
|
||||
float co, float H, float lacunarity, float octaves, float offset, float gain)
|
||||
{
|
||||
float p = co;
|
||||
float pwHL = pow(lacunarity, -H);
|
||||
|
||||
float pwr = 1.0;
|
||||
float value = 0.0;
|
||||
float weight = 1.0;
|
||||
|
||||
for (int i = 0; (weight > 0.001) && (i < (int)octaves); i++) {
|
||||
if (weight > 1.0) {
|
||||
weight = 1.0;
|
||||
}
|
||||
|
||||
float signal = (safe_snoise(p) + offset) * pwr;
|
||||
pwr *= pwHL;
|
||||
value += weight * signal;
|
||||
weight *= gain * signal;
|
||||
p *= lacunarity;
|
||||
}
|
||||
|
||||
float rmd = octaves - floor(octaves);
|
||||
if ((rmd != 0.0) && (weight > 0.001)) {
|
||||
if (weight > 1.0) {
|
||||
weight = 1.0;
|
||||
}
|
||||
float signal = (safe_snoise(p) + offset) * pwr;
|
||||
value += rmd * weight * signal;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
/* 1D Ridged Multifractal Terrain
|
||||
*
|
||||
* H: fractal dimension of the roughest area
|
||||
* lacunarity: gap between successive frequencies
|
||||
* octaves: number of frequencies in the fBm
|
||||
* offset: raises the terrain from `sea level'
|
||||
*/
|
||||
|
||||
float noise_musgrave_ridged_multi_fractal_1d(
|
||||
float co, float H, float lacunarity, float octaves, float offset, float gain)
|
||||
{
|
||||
float p = co;
|
||||
float pwHL = pow(lacunarity, -H);
|
||||
float pwr = pwHL;
|
||||
|
||||
float signal = offset - fabs(safe_snoise(p));
|
||||
signal *= signal;
|
||||
float value = signal;
|
||||
float weight = 1.0;
|
||||
|
||||
for (int i = 1; i < (int)octaves; i++) {
|
||||
p *= lacunarity;
|
||||
weight = clamp(signal * gain, 0.0, 1.0);
|
||||
signal = offset - fabs(safe_snoise(p));
|
||||
signal *= signal;
|
||||
signal *= weight;
|
||||
value += signal * pwr;
|
||||
pwr *= pwHL;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
/* 2D Musgrave fBm
|
||||
*
|
||||
* H: fractal increment parameter
|
||||
* lacunarity: gap between successive frequencies
|
||||
* octaves: number of frequencies in the fBm
|
||||
*
|
||||
* from "Texturing and Modelling: A procedural approach"
|
||||
*/
|
||||
|
||||
float noise_musgrave_fBm_2d(vector2 co, float H, float lacunarity, float octaves)
|
||||
{
|
||||
vector2 p = co;
|
||||
float value = 0.0;
|
||||
float pwr = 1.0;
|
||||
float pwHL = pow(lacunarity, -H);
|
||||
|
||||
for (int i = 0; i < (int)octaves; i++) {
|
||||
value += safe_snoise(p) * pwr;
|
||||
pwr *= pwHL;
|
||||
p *= lacunarity;
|
||||
}
|
||||
|
||||
float rmd = octaves - floor(octaves);
|
||||
if (rmd != 0.0) {
|
||||
value += rmd * safe_snoise(p) * pwr;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
/* 2D Musgrave Multifractal
|
||||
*
|
||||
* H: highest fractal dimension
|
||||
* lacunarity: gap between successive frequencies
|
||||
* octaves: number of frequencies in the fBm
|
||||
*/
|
||||
|
||||
float noise_musgrave_multi_fractal_2d(vector2 co, float H, float lacunarity, float octaves)
|
||||
{
|
||||
vector2 p = co;
|
||||
float value = 1.0;
|
||||
float pwr = 1.0;
|
||||
float pwHL = pow(lacunarity, -H);
|
||||
|
||||
for (int i = 0; i < (int)octaves; i++) {
|
||||
value *= (pwr * safe_snoise(p) + 1.0);
|
||||
pwr *= pwHL;
|
||||
p *= lacunarity;
|
||||
}
|
||||
|
||||
float rmd = octaves - floor(octaves);
|
||||
if (rmd != 0.0) {
|
||||
value *= (rmd * pwr * safe_snoise(p) + 1.0); /* correct? */
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
/* 2D Musgrave Heterogeneous Terrain
|
||||
*
|
||||
* H: fractal dimension of the roughest area
|
||||
* lacunarity: gap between successive frequencies
|
||||
* octaves: number of frequencies in the fBm
|
||||
* offset: raises the terrain from `sea level'
|
||||
*/
|
||||
|
||||
float noise_musgrave_hetero_terrain_2d(
|
||||
vector2 co, float H, float lacunarity, float octaves, float offset)
|
||||
{
|
||||
vector2 p = co;
|
||||
float pwHL = pow(lacunarity, -H);
|
||||
float pwr = pwHL;
|
||||
|
||||
/* first unscaled octave of function; later octaves are scaled */
|
||||
float value = offset + safe_snoise(p);
|
||||
p *= lacunarity;
|
||||
|
||||
for (int i = 1; i < (int)octaves; i++) {
|
||||
float increment = (safe_snoise(p) + offset) * pwr * value;
|
||||
value += increment;
|
||||
pwr *= pwHL;
|
||||
p *= lacunarity;
|
||||
}
|
||||
|
||||
float rmd = octaves - floor(octaves);
|
||||
if (rmd != 0.0) {
|
||||
float increment = (safe_snoise(p) + offset) * pwr * value;
|
||||
value += rmd * increment;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
/* 2D Hybrid Additive/Multiplicative Multifractal Terrain
|
||||
*
|
||||
* H: fractal dimension of the roughest area
|
||||
* lacunarity: gap between successive frequencies
|
||||
* octaves: number of frequencies in the fBm
|
||||
* offset: raises the terrain from `sea level'
|
||||
*/
|
||||
|
||||
float noise_musgrave_hybrid_multi_fractal_2d(
|
||||
vector2 co, float H, float lacunarity, float octaves, float offset, float gain)
|
||||
{
|
||||
vector2 p = co;
|
||||
float pwHL = pow(lacunarity, -H);
|
||||
|
||||
float pwr = 1.0;
|
||||
float value = 0.0;
|
||||
float weight = 1.0;
|
||||
|
||||
for (int i = 0; (weight > 0.001) && (i < (int)octaves); i++) {
|
||||
if (weight > 1.0) {
|
||||
weight = 1.0;
|
||||
}
|
||||
|
||||
float signal = (safe_snoise(p) + offset) * pwr;
|
||||
pwr *= pwHL;
|
||||
value += weight * signal;
|
||||
weight *= gain * signal;
|
||||
p *= lacunarity;
|
||||
}
|
||||
|
||||
float rmd = octaves - floor(octaves);
|
||||
if ((rmd != 0.0) && (weight > 0.001)) {
|
||||
if (weight > 1.0) {
|
||||
weight = 1.0;
|
||||
}
|
||||
float signal = (safe_snoise(p) + offset) * pwr;
|
||||
value += rmd * weight * signal;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
/* 2D Ridged Multifractal Terrain
|
||||
*
|
||||
* H: fractal dimension of the roughest area
|
||||
* lacunarity: gap between successive frequencies
|
||||
* octaves: number of frequencies in the fBm
|
||||
* offset: raises the terrain from `sea level'
|
||||
*/
|
||||
|
||||
float noise_musgrave_ridged_multi_fractal_2d(
|
||||
vector2 co, float H, float lacunarity, float octaves, float offset, float gain)
|
||||
{
|
||||
vector2 p = co;
|
||||
float pwHL = pow(lacunarity, -H);
|
||||
float pwr = pwHL;
|
||||
|
||||
float signal = offset - fabs(safe_snoise(p));
|
||||
signal *= signal;
|
||||
float value = signal;
|
||||
float weight = 1.0;
|
||||
|
||||
for (int i = 1; i < (int)octaves; i++) {
|
||||
p *= lacunarity;
|
||||
weight = clamp(signal * gain, 0.0, 1.0);
|
||||
signal = offset - fabs(safe_snoise(p));
|
||||
signal *= signal;
|
||||
signal *= weight;
|
||||
value += signal * pwr;
|
||||
pwr *= pwHL;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
/* 3D Musgrave fBm
|
||||
*
|
||||
* H: fractal increment parameter
|
||||
* lacunarity: gap between successive frequencies
|
||||
* octaves: number of frequencies in the fBm
|
||||
*
|
||||
* from "Texturing and Modelling: A procedural approach"
|
||||
*/
|
||||
|
||||
float noise_musgrave_fBm_3d(vector3 co, float H, float lacunarity, float octaves)
|
||||
{
|
||||
vector3 p = co;
|
||||
float value = 0.0;
|
||||
float pwr = 1.0;
|
||||
float pwHL = pow(lacunarity, -H);
|
||||
|
||||
for (int i = 0; i < (int)octaves; i++) {
|
||||
value += safe_snoise(p) * pwr;
|
||||
pwr *= pwHL;
|
||||
p *= lacunarity;
|
||||
}
|
||||
|
||||
float rmd = octaves - floor(octaves);
|
||||
if (rmd != 0.0) {
|
||||
value += rmd * safe_snoise(p) * pwr;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
/* 3D Musgrave Multifractal
|
||||
*
|
||||
* H: highest fractal dimension
|
||||
* lacunarity: gap between successive frequencies
|
||||
* octaves: number of frequencies in the fBm
|
||||
*/
|
||||
|
||||
float noise_musgrave_multi_fractal_3d(vector3 co, float H, float lacunarity, float octaves)
|
||||
{
|
||||
vector3 p = co;
|
||||
float value = 1.0;
|
||||
float pwr = 1.0;
|
||||
float pwHL = pow(lacunarity, -H);
|
||||
|
||||
for (int i = 0; i < (int)octaves; i++) {
|
||||
value *= (pwr * safe_snoise(p) + 1.0);
|
||||
pwr *= pwHL;
|
||||
p *= lacunarity;
|
||||
}
|
||||
|
||||
float rmd = octaves - floor(octaves);
|
||||
if (rmd != 0.0) {
|
||||
value *= (rmd * pwr * safe_snoise(p) + 1.0); /* correct? */
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
/* 3D Musgrave Heterogeneous Terrain
|
||||
*
|
||||
* H: fractal dimension of the roughest area
|
||||
* lacunarity: gap between successive frequencies
|
||||
* octaves: number of frequencies in the fBm
|
||||
* offset: raises the terrain from `sea level'
|
||||
*/
|
||||
|
||||
float noise_musgrave_hetero_terrain_3d(
|
||||
vector3 co, float H, float lacunarity, float octaves, float offset)
|
||||
{
|
||||
vector3 p = co;
|
||||
float pwHL = pow(lacunarity, -H);
|
||||
float pwr = pwHL;
|
||||
|
||||
/* first unscaled octave of function; later octaves are scaled */
|
||||
float value = offset + safe_snoise(p);
|
||||
p *= lacunarity;
|
||||
|
||||
for (int i = 1; i < (int)octaves; i++) {
|
||||
float increment = (safe_snoise(p) + offset) * pwr * value;
|
||||
value += increment;
|
||||
pwr *= pwHL;
|
||||
p *= lacunarity;
|
||||
}
|
||||
|
||||
float rmd = octaves - floor(octaves);
|
||||
if (rmd != 0.0) {
|
||||
float increment = (safe_snoise(p) + offset) * pwr * value;
|
||||
value += rmd * increment;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
/* 3D Hybrid Additive/Multiplicative Multifractal Terrain
|
||||
*
|
||||
* H: fractal dimension of the roughest area
|
||||
* lacunarity: gap between successive frequencies
|
||||
* octaves: number of frequencies in the fBm
|
||||
* offset: raises the terrain from `sea level'
|
||||
*/
|
||||
|
||||
float noise_musgrave_hybrid_multi_fractal_3d(
|
||||
vector3 co, float H, float lacunarity, float octaves, float offset, float gain)
|
||||
{
|
||||
vector3 p = co;
|
||||
float pwHL = pow(lacunarity, -H);
|
||||
|
||||
float pwr = 1.0;
|
||||
float value = 0.0;
|
||||
float weight = 1.0;
|
||||
|
||||
for (int i = 0; (weight > 0.001) && (i < (int)octaves); i++) {
|
||||
if (weight > 1.0) {
|
||||
weight = 1.0;
|
||||
}
|
||||
|
||||
float signal = (safe_snoise(p) + offset) * pwr;
|
||||
pwr *= pwHL;
|
||||
value += weight * signal;
|
||||
weight *= gain * signal;
|
||||
p *= lacunarity;
|
||||
}
|
||||
|
||||
float rmd = octaves - floor(octaves);
|
||||
if ((rmd != 0.0) && (weight > 0.001)) {
|
||||
if (weight > 1.0) {
|
||||
weight = 1.0;
|
||||
}
|
||||
float signal = (safe_snoise(p) + offset) * pwr;
|
||||
value += rmd * weight * signal;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
/* 3D Ridged Multifractal Terrain
|
||||
*
|
||||
* H: fractal dimension of the roughest area
|
||||
* lacunarity: gap between successive frequencies
|
||||
* octaves: number of frequencies in the fBm
|
||||
* offset: raises the terrain from `sea level'
|
||||
*/
|
||||
|
||||
float noise_musgrave_ridged_multi_fractal_3d(
|
||||
vector3 co, float H, float lacunarity, float octaves, float offset, float gain)
|
||||
{
|
||||
vector3 p = co;
|
||||
float pwHL = pow(lacunarity, -H);
|
||||
float pwr = pwHL;
|
||||
|
||||
float signal = offset - fabs(safe_snoise(p));
|
||||
signal *= signal;
|
||||
float value = signal;
|
||||
float weight = 1.0;
|
||||
|
||||
for (int i = 1; i < (int)octaves; i++) {
|
||||
p *= lacunarity;
|
||||
weight = clamp(signal * gain, 0.0, 1.0);
|
||||
signal = offset - fabs(safe_snoise(p));
|
||||
signal *= signal;
|
||||
signal *= weight;
|
||||
value += signal * pwr;
|
||||
pwr *= pwHL;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
/* 4D Musgrave fBm
|
||||
*
|
||||
* H: fractal increment parameter
|
||||
* lacunarity: gap between successive frequencies
|
||||
* octaves: number of frequencies in the fBm
|
||||
*
|
||||
* from "Texturing and Modelling: A procedural approach"
|
||||
*/
|
||||
|
||||
float noise_musgrave_fBm_4d(vector4 co, float H, float lacunarity, float octaves)
|
||||
{
|
||||
vector4 p = co;
|
||||
float value = 0.0;
|
||||
float pwr = 1.0;
|
||||
float pwHL = pow(lacunarity, -H);
|
||||
|
||||
for (int i = 0; i < (int)octaves; i++) {
|
||||
value += safe_snoise(p) * pwr;
|
||||
pwr *= pwHL;
|
||||
p *= lacunarity;
|
||||
}
|
||||
|
||||
float rmd = octaves - floor(octaves);
|
||||
if (rmd != 0.0) {
|
||||
value += rmd * safe_snoise(p) * pwr;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
/* 4D Musgrave Multifractal
|
||||
*
|
||||
* H: highest fractal dimension
|
||||
* lacunarity: gap between successive frequencies
|
||||
* octaves: number of frequencies in the fBm
|
||||
*/
|
||||
|
||||
float noise_musgrave_multi_fractal_4d(vector4 co, float H, float lacunarity, float octaves)
|
||||
{
|
||||
vector4 p = co;
|
||||
float value = 1.0;
|
||||
float pwr = 1.0;
|
||||
float pwHL = pow(lacunarity, -H);
|
||||
|
||||
for (int i = 0; i < (int)octaves; i++) {
|
||||
value *= (pwr * safe_snoise(p) + 1.0);
|
||||
pwr *= pwHL;
|
||||
p *= lacunarity;
|
||||
}
|
||||
|
||||
float rmd = octaves - floor(octaves);
|
||||
if (rmd != 0.0) {
|
||||
value *= (rmd * pwr * safe_snoise(p) + 1.0); /* correct? */
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
/* 4D Musgrave Heterogeneous Terrain
|
||||
*
|
||||
* H: fractal dimension of the roughest area
|
||||
* lacunarity: gap between successive frequencies
|
||||
* octaves: number of frequencies in the fBm
|
||||
* offset: raises the terrain from `sea level'
|
||||
*/
|
||||
|
||||
float noise_musgrave_hetero_terrain_4d(
|
||||
vector4 co, float H, float lacunarity, float octaves, float offset)
|
||||
{
|
||||
vector4 p = co;
|
||||
float pwHL = pow(lacunarity, -H);
|
||||
float pwr = pwHL;
|
||||
|
||||
/* first unscaled octave of function; later octaves are scaled */
|
||||
float value = offset + safe_snoise(p);
|
||||
p *= lacunarity;
|
||||
|
||||
for (int i = 1; i < (int)octaves; i++) {
|
||||
float increment = (safe_snoise(p) + offset) * pwr * value;
|
||||
value += increment;
|
||||
pwr *= pwHL;
|
||||
p *= lacunarity;
|
||||
}
|
||||
|
||||
float rmd = octaves - floor(octaves);
|
||||
if (rmd != 0.0) {
|
||||
float increment = (safe_snoise(p) + offset) * pwr * value;
|
||||
value += rmd * increment;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
/* 4D Hybrid Additive/Multiplicative Multifractal Terrain
|
||||
*
|
||||
* H: fractal dimension of the roughest area
|
||||
* lacunarity: gap between successive frequencies
|
||||
* octaves: number of frequencies in the fBm
|
||||
* offset: raises the terrain from `sea level'
|
||||
*/
|
||||
|
||||
float noise_musgrave_hybrid_multi_fractal_4d(
|
||||
vector4 co, float H, float lacunarity, float octaves, float offset, float gain)
|
||||
{
|
||||
vector4 p = co;
|
||||
float pwHL = pow(lacunarity, -H);
|
||||
|
||||
float pwr = 1.0;
|
||||
float value = 0.0;
|
||||
float weight = 1.0;
|
||||
|
||||
for (int i = 0; (weight > 0.001) && (i < (int)octaves); i++) {
|
||||
if (weight > 1.0) {
|
||||
weight = 1.0;
|
||||
}
|
||||
|
||||
float signal = (safe_snoise(p) + offset) * pwr;
|
||||
pwr *= pwHL;
|
||||
value += weight * signal;
|
||||
weight *= gain * signal;
|
||||
p *= lacunarity;
|
||||
}
|
||||
|
||||
float rmd = octaves - floor(octaves);
|
||||
if ((rmd != 0.0) && (weight > 0.001)) {
|
||||
if (weight > 1.0) {
|
||||
weight = 1.0;
|
||||
}
|
||||
float signal = (safe_snoise(p) + offset) * pwr;
|
||||
value += rmd * weight * signal;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
/* 4D Ridged Multifractal Terrain
|
||||
*
|
||||
* H: fractal dimension of the roughest area
|
||||
* lacunarity: gap between successive frequencies
|
||||
* octaves: number of frequencies in the fBm
|
||||
* offset: raises the terrain from `sea level'
|
||||
*/
|
||||
|
||||
float noise_musgrave_ridged_multi_fractal_4d(
|
||||
vector4 co, float H, float lacunarity, float octaves, float offset, float gain)
|
||||
{
|
||||
vector4 p = co;
|
||||
float pwHL = pow(lacunarity, -H);
|
||||
float pwr = pwHL;
|
||||
|
||||
float signal = offset - fabs(safe_snoise(p));
|
||||
signal *= signal;
|
||||
float value = signal;
|
||||
float weight = 1.0;
|
||||
|
||||
for (int i = 1; i < (int)octaves; i++) {
|
||||
p *= lacunarity;
|
||||
weight = clamp(signal * gain, 0.0, 1.0);
|
||||
signal = offset - fabs(safe_snoise(p));
|
||||
signal *= signal;
|
||||
signal *= weight;
|
||||
value += signal * pwr;
|
||||
pwr *= pwHL;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
shader node_musgrave_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 musgrave_type = "fBM",
|
||||
string dimensions = "3D",
|
||||
point Vector = P,
|
||||
float W = 0.0,
|
||||
float Dimension = 2.0,
|
||||
float Scale = 5.0,
|
||||
float Detail = 2.0,
|
||||
float Lacunarity = 2.0,
|
||||
float Offset = 0.0,
|
||||
float Gain = 1.0,
|
||||
output float Fac = 0.0)
|
||||
{
|
||||
float dimension = max(Dimension, 1e-5);
|
||||
float octaves = clamp(Detail, 0.0, 15.0);
|
||||
float lacunarity = max(Lacunarity, 1e-5);
|
||||
|
||||
vector3 s = Vector;
|
||||
|
||||
if (use_mapping)
|
||||
s = transform(mapping, s);
|
||||
|
||||
if (dimensions == "1D") {
|
||||
float p = W * Scale;
|
||||
if (musgrave_type == "multifractal") {
|
||||
Fac = noise_musgrave_multi_fractal_1d(p, dimension, lacunarity, octaves);
|
||||
}
|
||||
else if (musgrave_type == "fBM") {
|
||||
Fac = noise_musgrave_fBm_1d(p, dimension, lacunarity, octaves);
|
||||
}
|
||||
else if (musgrave_type == "hybrid_multifractal") {
|
||||
Fac = noise_musgrave_hybrid_multi_fractal_1d(
|
||||
p, dimension, lacunarity, octaves, Offset, Gain);
|
||||
}
|
||||
else if (musgrave_type == "ridged_multifractal") {
|
||||
Fac = noise_musgrave_ridged_multi_fractal_1d(
|
||||
p, dimension, lacunarity, octaves, Offset, Gain);
|
||||
}
|
||||
else if (musgrave_type == "hetero_terrain") {
|
||||
Fac = noise_musgrave_hetero_terrain_1d(p, dimension, lacunarity, octaves, Offset);
|
||||
}
|
||||
else {
|
||||
Fac = 0.0;
|
||||
}
|
||||
}
|
||||
else if (dimensions == "2D") {
|
||||
vector2 p = vector2(s[0], s[1]) * Scale;
|
||||
if (musgrave_type == "multifractal") {
|
||||
Fac = noise_musgrave_multi_fractal_2d(p, dimension, lacunarity, octaves);
|
||||
}
|
||||
else if (musgrave_type == "fBM") {
|
||||
Fac = noise_musgrave_fBm_2d(p, dimension, lacunarity, octaves);
|
||||
}
|
||||
else if (musgrave_type == "hybrid_multifractal") {
|
||||
Fac = noise_musgrave_hybrid_multi_fractal_2d(
|
||||
p, dimension, lacunarity, octaves, Offset, Gain);
|
||||
}
|
||||
else if (musgrave_type == "ridged_multifractal") {
|
||||
Fac = noise_musgrave_ridged_multi_fractal_2d(
|
||||
p, dimension, lacunarity, octaves, Offset, Gain);
|
||||
}
|
||||
else if (musgrave_type == "hetero_terrain") {
|
||||
Fac = noise_musgrave_hetero_terrain_2d(p, dimension, lacunarity, octaves, Offset);
|
||||
}
|
||||
else {
|
||||
Fac = 0.0;
|
||||
}
|
||||
}
|
||||
else if (dimensions == "3D") {
|
||||
vector3 p = s * Scale;
|
||||
if (musgrave_type == "multifractal") {
|
||||
Fac = noise_musgrave_multi_fractal_3d(p, dimension, lacunarity, octaves);
|
||||
}
|
||||
else if (musgrave_type == "fBM") {
|
||||
Fac = noise_musgrave_fBm_3d(p, dimension, lacunarity, octaves);
|
||||
}
|
||||
else if (musgrave_type == "hybrid_multifractal") {
|
||||
Fac = noise_musgrave_hybrid_multi_fractal_3d(
|
||||
p, dimension, lacunarity, octaves, Offset, Gain);
|
||||
}
|
||||
else if (musgrave_type == "ridged_multifractal") {
|
||||
Fac = noise_musgrave_ridged_multi_fractal_3d(
|
||||
p, dimension, lacunarity, octaves, Offset, Gain);
|
||||
}
|
||||
else if (musgrave_type == "hetero_terrain") {
|
||||
Fac = noise_musgrave_hetero_terrain_3d(p, dimension, lacunarity, octaves, Offset);
|
||||
}
|
||||
else {
|
||||
Fac = 0.0;
|
||||
}
|
||||
}
|
||||
else if (dimensions == "4D") {
|
||||
vector4 p = vector4(s[0], s[1], s[2], W) * Scale;
|
||||
if (musgrave_type == "multifractal") {
|
||||
Fac = noise_musgrave_multi_fractal_4d(p, dimension, lacunarity, octaves);
|
||||
}
|
||||
else if (musgrave_type == "fBM") {
|
||||
Fac = noise_musgrave_fBm_4d(p, dimension, lacunarity, octaves);
|
||||
}
|
||||
else if (musgrave_type == "hybrid_multifractal") {
|
||||
Fac = noise_musgrave_hybrid_multi_fractal_4d(
|
||||
p, dimension, lacunarity, octaves, Offset, Gain);
|
||||
}
|
||||
else if (musgrave_type == "ridged_multifractal") {
|
||||
Fac = noise_musgrave_ridged_multi_fractal_4d(
|
||||
p, dimension, lacunarity, octaves, Offset, Gain);
|
||||
}
|
||||
else if (musgrave_type == "hetero_terrain") {
|
||||
Fac = noise_musgrave_hetero_terrain_4d(p, dimension, lacunarity, octaves, Offset);
|
||||
}
|
||||
else {
|
||||
Fac = 0.0;
|
||||
}
|
||||
}
|
||||
else {
|
||||
Fac = 0.0;
|
||||
}
|
||||
}
|
||||
@@ -79,116 +79,173 @@ float safe_snoise(vector4 p)
|
||||
return f;
|
||||
}
|
||||
|
||||
/* The fractal_noise functions are all exactly the same except for the input type. */
|
||||
float fractal_noise(float p, float details, float roughness, float lacunarity, int use_normalize)
|
||||
{
|
||||
float fscale = 1.0;
|
||||
float amp = 1.0;
|
||||
float maxamp = 0.0;
|
||||
float sum = 0.0;
|
||||
float octaves = clamp(details, 0.0, 15.0);
|
||||
int n = (int)octaves;
|
||||
for (int i = 0; i <= n; i++) {
|
||||
float t = safe_snoise(fscale * p);
|
||||
sum += t * amp;
|
||||
maxamp += amp;
|
||||
amp *= clamp(roughness, 0.0, 1.0);
|
||||
fscale *= lacunarity;
|
||||
#define NOISE_FBM(T) \
|
||||
float noise_fbm(T co, float detail, float roughness, float lacunarity, int use_normalize) \
|
||||
{ \
|
||||
T p = co; \
|
||||
float fscale = 1.0; \
|
||||
float amp = 1.0; \
|
||||
float maxamp = 0.0; \
|
||||
float sum = 0.0; \
|
||||
\
|
||||
for (int i = 0; i <= int(detail); i++) { \
|
||||
float t = safe_snoise(fscale * p); \
|
||||
sum += t * amp; \
|
||||
maxamp += amp; \
|
||||
amp *= roughness; \
|
||||
fscale *= lacunarity; \
|
||||
} \
|
||||
float rmd = detail - floor(detail); \
|
||||
if (rmd != 0.0) { \
|
||||
float t = safe_snoise(fscale * p); \
|
||||
float sum2 = sum + t * amp; \
|
||||
return use_normalize ? \
|
||||
mix(0.5 * sum / maxamp + 0.5, 0.5 * sum2 / (maxamp + amp) + 0.5, rmd) : \
|
||||
mix(sum, sum2, rmd); \
|
||||
} \
|
||||
else { \
|
||||
return use_normalize ? 0.5 * sum / maxamp + 0.5 : sum; \
|
||||
} \
|
||||
}
|
||||
float rmd = octaves - floor(octaves);
|
||||
if (rmd != 0.0) {
|
||||
float t = safe_snoise(fscale * p);
|
||||
float sum2 = sum + t * amp;
|
||||
return use_normalize ? mix(0.5 * sum / maxamp + 0.5, 0.5 * sum2 / (maxamp + amp) + 0.5, rmd) :
|
||||
mix(sum, sum2, rmd);
|
||||
}
|
||||
else {
|
||||
return use_normalize ? 0.5 * sum / maxamp + 0.5 : sum;
|
||||
}
|
||||
}
|
||||
|
||||
/* The fractal_noise functions are all exactly the same except for the input type. */
|
||||
float fractal_noise(vector2 p, float details, float roughness, float lacunarity, int use_normalize)
|
||||
{
|
||||
float fscale = 1.0;
|
||||
float amp = 1.0;
|
||||
float maxamp = 0.0;
|
||||
float sum = 0.0;
|
||||
float octaves = clamp(details, 0.0, 15.0);
|
||||
int n = (int)octaves;
|
||||
for (int i = 0; i <= n; i++) {
|
||||
float t = safe_snoise(fscale * p);
|
||||
sum += t * amp;
|
||||
maxamp += amp;
|
||||
amp *= clamp(roughness, 0.0, 1.0);
|
||||
fscale *= lacunarity;
|
||||
#define NOISE_MULTI_FRACTAL(T) \
|
||||
float noise_multi_fractal(T co, float detail, float roughness, float lacunarity) \
|
||||
{ \
|
||||
T p = co; \
|
||||
float value = 1.0; \
|
||||
float pwr = 1.0; \
|
||||
\
|
||||
for (int i = 0; i <= (int)detail; i++) { \
|
||||
value *= (pwr * safe_snoise(p) + 1.0); \
|
||||
pwr *= roughness; \
|
||||
p *= lacunarity; \
|
||||
} \
|
||||
\
|
||||
float rmd = detail - floor(detail); \
|
||||
if (rmd != 0.0) { \
|
||||
value *= (rmd * pwr * safe_snoise(p) + 1.0); /* correct? */ \
|
||||
} \
|
||||
\
|
||||
return value; \
|
||||
}
|
||||
float rmd = octaves - floor(octaves);
|
||||
if (rmd != 0.0) {
|
||||
float t = safe_snoise(fscale * p);
|
||||
float sum2 = sum + t * amp;
|
||||
return use_normalize ? mix(0.5 * sum / maxamp + 0.5, 0.5 * sum2 / (maxamp + amp) + 0.5, rmd) :
|
||||
mix(sum, sum2, rmd);
|
||||
}
|
||||
else {
|
||||
return use_normalize ? 0.5 * sum / maxamp + 0.5 : sum;
|
||||
}
|
||||
}
|
||||
|
||||
/* The fractal_noise functions are all exactly the same except for the input type. */
|
||||
float fractal_noise(vector3 p, float details, float roughness, float lacunarity, int use_normalize)
|
||||
{
|
||||
float fscale = 1.0;
|
||||
float amp = 1.0;
|
||||
float maxamp = 0.0;
|
||||
float sum = 0.0;
|
||||
float octaves = clamp(details, 0.0, 15.0);
|
||||
int n = (int)octaves;
|
||||
for (int i = 0; i <= n; i++) {
|
||||
float t = safe_snoise(fscale * p);
|
||||
sum += t * amp;
|
||||
maxamp += amp;
|
||||
amp *= clamp(roughness, 0.0, 1.0);
|
||||
fscale *= lacunarity;
|
||||
#define NOISE_HETERO_TERRAIN(T) \
|
||||
float noise_hetero_terrain(T co, float detail, float roughness, float lacunarity, float offset) \
|
||||
{ \
|
||||
T p = co; \
|
||||
float pwr = roughness; \
|
||||
\
|
||||
/* first unscaled octave of function; later octaves are scaled */ \
|
||||
float value = offset + safe_snoise(p); \
|
||||
p *= lacunarity; \
|
||||
\
|
||||
for (int i = 1; i <= (int)detail; i++) { \
|
||||
float increment = (safe_snoise(p) + offset) * pwr * value; \
|
||||
value += increment; \
|
||||
pwr *= roughness; \
|
||||
p *= lacunarity; \
|
||||
} \
|
||||
\
|
||||
float rmd = detail - floor(detail); \
|
||||
if (rmd != 0.0) { \
|
||||
float increment = (safe_snoise(p) + offset) * pwr * value; \
|
||||
value += rmd * increment; \
|
||||
} \
|
||||
\
|
||||
return value; \
|
||||
}
|
||||
float rmd = octaves - floor(octaves);
|
||||
if (rmd != 0.0) {
|
||||
float t = safe_snoise(fscale * p);
|
||||
float sum2 = sum + t * amp;
|
||||
return use_normalize ? mix(0.5 * sum / maxamp + 0.5, 0.5 * sum2 / (maxamp + amp) + 0.5, rmd) :
|
||||
mix(sum, sum2, rmd);
|
||||
}
|
||||
else {
|
||||
return use_normalize ? 0.5 * sum / maxamp + 0.5 : sum;
|
||||
}
|
||||
}
|
||||
|
||||
/* The fractal_noise functions are all exactly the same except for the input type. */
|
||||
float fractal_noise(vector4 p, float details, float roughness, float lacunarity, int use_normalize)
|
||||
{
|
||||
float fscale = 1.0;
|
||||
float amp = 1.0;
|
||||
float maxamp = 0.0;
|
||||
float sum = 0.0;
|
||||
float octaves = clamp(details, 0.0, 15.0);
|
||||
int n = (int)octaves;
|
||||
for (int i = 0; i <= n; i++) {
|
||||
float t = safe_snoise(fscale * p);
|
||||
sum += t * amp;
|
||||
maxamp += amp;
|
||||
amp *= clamp(roughness, 0.0, 1.0);
|
||||
fscale *= lacunarity;
|
||||
#define NOISE_HYBRID_MULTI_FRACTAL(T) \
|
||||
float noise_hybrid_multi_fractal( \
|
||||
T co, float detail, float roughness, float lacunarity, float offset, float gain) \
|
||||
{ \
|
||||
T p = co; \
|
||||
float pwr = 1.0; \
|
||||
float value = 0.0; \
|
||||
float weight = 1.0; \
|
||||
\
|
||||
for (int i = 0; (weight > 0.001) && (i <= (int)detail); i++) { \
|
||||
if (weight > 1.0) { \
|
||||
weight = 1.0; \
|
||||
} \
|
||||
\
|
||||
float signal = (safe_snoise(p) + offset) * pwr; \
|
||||
pwr *= roughness; \
|
||||
value += weight * signal; \
|
||||
weight *= gain * signal; \
|
||||
p *= lacunarity; \
|
||||
} \
|
||||
\
|
||||
float rmd = detail - floor(detail); \
|
||||
if ((rmd != 0.0) && (weight > 0.001)) { \
|
||||
if (weight > 1.0) { \
|
||||
weight = 1.0; \
|
||||
} \
|
||||
float signal = (safe_snoise(p) + offset) * pwr; \
|
||||
value += rmd * weight * signal; \
|
||||
} \
|
||||
\
|
||||
return value; \
|
||||
}
|
||||
float rmd = octaves - floor(octaves);
|
||||
if (rmd != 0.0) {
|
||||
float t = safe_snoise(fscale * p);
|
||||
float sum2 = sum + t * amp;
|
||||
return use_normalize ? mix(0.5 * sum / maxamp + 0.5, 0.5 * sum2 / (maxamp + amp) + 0.5, rmd) :
|
||||
mix(sum, sum2, rmd);
|
||||
|
||||
#define NOISE_RIDGED_MULTI_FRACTAL(T) \
|
||||
float noise_ridged_multi_fractal( \
|
||||
T co, float detail, float roughness, float lacunarity, float offset, float gain) \
|
||||
{ \
|
||||
T p = co; \
|
||||
float pwr = roughness; \
|
||||
\
|
||||
float signal = offset - fabs(safe_snoise(p)); \
|
||||
signal *= signal; \
|
||||
float value = signal; \
|
||||
float weight = 1.0; \
|
||||
\
|
||||
for (int i = 1; i <= (int)detail; i++) { \
|
||||
p *= lacunarity; \
|
||||
weight = clamp(signal * gain, 0.0, 1.0); \
|
||||
signal = offset - fabs(safe_snoise(p)); \
|
||||
signal *= signal; \
|
||||
signal *= weight; \
|
||||
value += signal * pwr; \
|
||||
pwr *= roughness; \
|
||||
} \
|
||||
\
|
||||
return value; \
|
||||
}
|
||||
else {
|
||||
return use_normalize ? 0.5 * sum / maxamp + 0.5 : sum;
|
||||
}
|
||||
}
|
||||
|
||||
/* Noise fBM */
|
||||
|
||||
NOISE_FBM(float)
|
||||
NOISE_FBM(vector2)
|
||||
NOISE_FBM(vector3)
|
||||
NOISE_FBM(vector4)
|
||||
|
||||
/* Noise Multifractal */
|
||||
|
||||
NOISE_MULTI_FRACTAL(float)
|
||||
NOISE_MULTI_FRACTAL(vector2)
|
||||
NOISE_MULTI_FRACTAL(vector3)
|
||||
NOISE_MULTI_FRACTAL(vector4)
|
||||
|
||||
/* Noise Hetero Terrain */
|
||||
|
||||
NOISE_HETERO_TERRAIN(float)
|
||||
NOISE_HETERO_TERRAIN(vector2)
|
||||
NOISE_HETERO_TERRAIN(vector3)
|
||||
NOISE_HETERO_TERRAIN(vector4)
|
||||
|
||||
/* Noise Hybrid Multifractal */
|
||||
|
||||
NOISE_HYBRID_MULTI_FRACTAL(float)
|
||||
NOISE_HYBRID_MULTI_FRACTAL(vector2)
|
||||
NOISE_HYBRID_MULTI_FRACTAL(vector3)
|
||||
NOISE_HYBRID_MULTI_FRACTAL(vector4)
|
||||
|
||||
/* Noise Ridged Multifractal */
|
||||
|
||||
NOISE_RIDGED_MULTI_FRACTAL(float)
|
||||
NOISE_RIDGED_MULTI_FRACTAL(vector2)
|
||||
NOISE_RIDGED_MULTI_FRACTAL(vector3)
|
||||
NOISE_RIDGED_MULTI_FRACTAL(vector4)
|
||||
|
||||
#undef vector3
|
||||
|
||||
@@ -9,6 +9,37 @@
|
||||
|
||||
#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.
|
||||
@@ -43,11 +74,21 @@ vector4 random_vector4_offset(float seed)
|
||||
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)
|
||||
{
|
||||
@@ -56,11 +97,24 @@ float noise_texture(float co,
|
||||
p += safe_snoise(p + random_float_offset(0.0)) * distortion;
|
||||
}
|
||||
|
||||
float value = fractal_noise(p, detail, roughness, lacunarity, use_normalize);
|
||||
Color = color(
|
||||
value,
|
||||
fractal_noise(p + random_float_offset(1.0), detail, roughness, lacunarity, use_normalize),
|
||||
fractal_noise(p + random_float_offset(2.0), detail, roughness, lacunarity, use_normalize));
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -68,7 +122,10 @@ 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)
|
||||
{
|
||||
@@ -78,11 +135,24 @@ float noise_texture(vector2 co,
|
||||
safe_snoise(p + random_vector2_offset(1.0)) * distortion);
|
||||
}
|
||||
|
||||
float value = fractal_noise(p, detail, roughness, lacunarity, use_normalize);
|
||||
Color = color(
|
||||
value,
|
||||
fractal_noise(p + random_vector2_offset(2.0), detail, roughness, lacunarity, use_normalize),
|
||||
fractal_noise(p + random_vector2_offset(3.0), detail, roughness, lacunarity, use_normalize));
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -90,7 +160,10 @@ 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)
|
||||
{
|
||||
@@ -101,11 +174,24 @@ float noise_texture(vector3 co,
|
||||
safe_snoise(p + random_vector3_offset(2.0)) * distortion);
|
||||
}
|
||||
|
||||
float value = fractal_noise(p, detail, roughness, lacunarity, use_normalize);
|
||||
Color = color(
|
||||
value,
|
||||
fractal_noise(p + random_vector3_offset(3.0), detail, roughness, lacunarity, use_normalize),
|
||||
fractal_noise(p + random_vector3_offset(4.0), detail, roughness, lacunarity, use_normalize));
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -113,7 +199,10 @@ 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)
|
||||
{
|
||||
@@ -125,23 +214,39 @@ float noise_texture(vector4 co,
|
||||
safe_snoise(p + random_vector4_offset(3.0)) * distortion);
|
||||
}
|
||||
|
||||
float value = fractal_noise(p, detail, roughness, lacunarity, use_normalize);
|
||||
Color = color(
|
||||
value,
|
||||
fractal_noise(p + random_vector4_offset(4.0), detail, roughness, lacunarity, use_normalize),
|
||||
fractal_noise(p + random_vector4_offset(5.0), detail, roughness, lacunarity, use_normalize));
|
||||
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",
|
||||
int use_normalize = 0,
|
||||
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,
|
||||
@@ -151,24 +256,45 @@ shader node_noise_texture(int use_mapping = 0,
|
||||
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, Distortion, use_normalize, Color);
|
||||
else if (dimensions == "2D")
|
||||
if (dimensions == "1D") {
|
||||
Fac = noise_texture(
|
||||
vector2(p[0], p[1]), Detail, Roughness, Lacunarity, Distortion, use_normalize, Color);
|
||||
else if (dimensions == "3D")
|
||||
Fac = noise_texture(p, Detail, Roughness, Lacunarity, Distortion, use_normalize, Color);
|
||||
else if (dimensions == "4D")
|
||||
Fac = noise_texture(vector4(p[0], p[1], p[2], w),
|
||||
Detail,
|
||||
Roughness,
|
||||
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
|
||||
error("Unknown dimension!");
|
||||
}
|
||||
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!");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -56,7 +56,7 @@ float wave(point p_input,
|
||||
n += phase;
|
||||
|
||||
if (distortion != 0.0) {
|
||||
n = n + (distortion * (fractal_noise(p * dscale, detail, droughness, 2.0, 1) * 2.0 - 1.0));
|
||||
n = n + (distortion * (noise_fbm(p * dscale, detail, droughness, 2.0, 1) * 2.0 - 1.0));
|
||||
}
|
||||
|
||||
if (profile == "sine") {
|
||||
|
||||
@@ -8,24 +8,24 @@
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
||||
/* The fractal_noise_[1-4] functions are all exactly the same except for the input type. */
|
||||
ccl_device_noinline float fractal_noise_1d(
|
||||
float p, float octaves, float roughness, float lacunarity, bool normalize)
|
||||
/* Fractal Brownian motion*/
|
||||
|
||||
ccl_device_noinline float noise_fbm(
|
||||
float p, float detail, float roughness, float lacunarity, bool normalize)
|
||||
{
|
||||
float fscale = 1.0f;
|
||||
float amp = 1.0f;
|
||||
float maxamp = 0.0f;
|
||||
float sum = 0.0f;
|
||||
octaves = clamp(octaves, 0.0f, 15.0f);
|
||||
int n = float_to_int(octaves);
|
||||
for (int i = 0; i <= n; i++) {
|
||||
|
||||
for (int i = 0; i <= float_to_int(detail); i++) {
|
||||
float t = snoise_1d(fscale * p);
|
||||
sum += t * amp;
|
||||
maxamp += amp;
|
||||
amp *= clamp(roughness, 0.0f, 1.0f);
|
||||
amp *= roughness;
|
||||
fscale *= lacunarity;
|
||||
}
|
||||
float rmd = octaves - floorf(octaves);
|
||||
float rmd = detail - floorf(detail);
|
||||
if (rmd != 0.0f) {
|
||||
float t = snoise_1d(fscale * p);
|
||||
float sum2 = sum + t * amp;
|
||||
@@ -37,24 +37,22 @@ ccl_device_noinline float fractal_noise_1d(
|
||||
}
|
||||
}
|
||||
|
||||
/* The fractal_noise_[1-4] functions are all exactly the same except for the input type. */
|
||||
ccl_device_noinline float fractal_noise_2d(
|
||||
float2 p, float octaves, float roughness, float lacunarity, bool normalize)
|
||||
ccl_device_noinline float noise_fbm(
|
||||
float2 p, float detail, float roughness, float lacunarity, bool normalize)
|
||||
{
|
||||
float fscale = 1.0f;
|
||||
float amp = 1.0f;
|
||||
float maxamp = 0.0f;
|
||||
float sum = 0.0f;
|
||||
octaves = clamp(octaves, 0.0f, 15.0f);
|
||||
int n = float_to_int(octaves);
|
||||
for (int i = 0; i <= n; i++) {
|
||||
|
||||
for (int i = 0; i <= float_to_int(detail); i++) {
|
||||
float t = snoise_2d(fscale * p);
|
||||
sum += t * amp;
|
||||
maxamp += amp;
|
||||
amp *= clamp(roughness, 0.0f, 1.0f);
|
||||
amp *= roughness;
|
||||
fscale *= lacunarity;
|
||||
}
|
||||
float rmd = octaves - floorf(octaves);
|
||||
float rmd = detail - floorf(detail);
|
||||
if (rmd != 0.0f) {
|
||||
float t = snoise_2d(fscale * p);
|
||||
float sum2 = sum + t * amp;
|
||||
@@ -66,24 +64,22 @@ ccl_device_noinline float fractal_noise_2d(
|
||||
}
|
||||
}
|
||||
|
||||
/* The fractal_noise_[1-4] functions are all exactly the same except for the input type. */
|
||||
ccl_device_noinline float fractal_noise_3d(
|
||||
float3 p, float octaves, float roughness, float lacunarity, bool normalize)
|
||||
ccl_device_noinline float noise_fbm(
|
||||
float3 p, float detail, float roughness, float lacunarity, bool normalize)
|
||||
{
|
||||
float fscale = 1.0f;
|
||||
float amp = 1.0f;
|
||||
float maxamp = 0.0f;
|
||||
float sum = 0.0f;
|
||||
octaves = clamp(octaves, 0.0f, 15.0f);
|
||||
int n = float_to_int(octaves);
|
||||
for (int i = 0; i <= n; i++) {
|
||||
|
||||
for (int i = 0; i <= float_to_int(detail); i++) {
|
||||
float t = snoise_3d(fscale * p);
|
||||
sum += t * amp;
|
||||
maxamp += amp;
|
||||
amp *= clamp(roughness, 0.0f, 1.0f);
|
||||
amp *= roughness;
|
||||
fscale *= lacunarity;
|
||||
}
|
||||
float rmd = octaves - floorf(octaves);
|
||||
float rmd = detail - floorf(detail);
|
||||
if (rmd != 0.0f) {
|
||||
float t = snoise_3d(fscale * p);
|
||||
float sum2 = sum + t * amp;
|
||||
@@ -95,24 +91,22 @@ ccl_device_noinline float fractal_noise_3d(
|
||||
}
|
||||
}
|
||||
|
||||
/* The fractal_noise_[1-4] functions are all exactly the same except for the input type. */
|
||||
ccl_device_noinline float fractal_noise_4d(
|
||||
float4 p, float octaves, float roughness, float lacunarity, bool normalize)
|
||||
ccl_device_noinline float noise_fbm(
|
||||
float4 p, float detail, float roughness, float lacunarity, bool normalize)
|
||||
{
|
||||
float fscale = 1.0f;
|
||||
float amp = 1.0f;
|
||||
float maxamp = 0.0f;
|
||||
float sum = 0.0f;
|
||||
octaves = clamp(octaves, 0.0f, 15.0f);
|
||||
int n = float_to_int(octaves);
|
||||
for (int i = 0; i <= n; i++) {
|
||||
|
||||
for (int i = 0; i <= float_to_int(detail); i++) {
|
||||
float t = snoise_4d(fscale * p);
|
||||
sum += t * amp;
|
||||
maxamp += amp;
|
||||
amp *= clamp(roughness, 0.0f, 1.0f);
|
||||
amp *= roughness;
|
||||
fscale *= lacunarity;
|
||||
}
|
||||
float rmd = octaves - floorf(octaves);
|
||||
float rmd = detail - floorf(detail);
|
||||
if (rmd != 0.0f) {
|
||||
float t = snoise_4d(fscale * p);
|
||||
float sum2 = sum + t * amp;
|
||||
@@ -124,4 +118,416 @@ ccl_device_noinline float fractal_noise_4d(
|
||||
}
|
||||
}
|
||||
|
||||
/* Multifractal */
|
||||
|
||||
ccl_device_noinline float noise_multi_fractal(float p,
|
||||
float detail,
|
||||
float roughness,
|
||||
float lacunarity)
|
||||
{
|
||||
float value = 1.0f;
|
||||
float pwr = 1.0f;
|
||||
|
||||
for (int i = 0; i <= float_to_int(detail); i++) {
|
||||
value *= (pwr * snoise_1d(p) + 1.0f);
|
||||
pwr *= roughness;
|
||||
p *= lacunarity;
|
||||
}
|
||||
|
||||
float rmd = detail - floorf(detail);
|
||||
if (rmd != 0.0f) {
|
||||
value *= (rmd * pwr * snoise_1d(p) + 1.0f); /* correct? */
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
ccl_device_noinline float noise_multi_fractal(float2 p,
|
||||
float detail,
|
||||
float roughness,
|
||||
float lacunarity)
|
||||
{
|
||||
float value = 1.0f;
|
||||
float pwr = 1.0f;
|
||||
|
||||
for (int i = 0; i <= float_to_int(detail); i++) {
|
||||
value *= (pwr * snoise_2d(p) + 1.0f);
|
||||
pwr *= roughness;
|
||||
p *= lacunarity;
|
||||
}
|
||||
|
||||
float rmd = detail - floorf(detail);
|
||||
if (rmd != 0.0f) {
|
||||
value *= (rmd * pwr * snoise_2d(p) + 1.0f); /* correct? */
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
ccl_device_noinline float noise_multi_fractal(float3 p,
|
||||
float detail,
|
||||
float roughness,
|
||||
float lacunarity)
|
||||
{
|
||||
float value = 1.0f;
|
||||
float pwr = 1.0f;
|
||||
|
||||
for (int i = 0; i <= float_to_int(detail); i++) {
|
||||
value *= (pwr * snoise_3d(p) + 1.0f);
|
||||
pwr *= roughness;
|
||||
p *= lacunarity;
|
||||
}
|
||||
|
||||
float rmd = detail - floorf(detail);
|
||||
if (rmd != 0.0f) {
|
||||
value *= (rmd * pwr * snoise_3d(p) + 1.0f); /* correct? */
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
ccl_device_noinline float noise_multi_fractal(float4 p,
|
||||
float detail,
|
||||
float roughness,
|
||||
float lacunarity)
|
||||
{
|
||||
float value = 1.0f;
|
||||
float pwr = 1.0f;
|
||||
|
||||
for (int i = 0; i <= float_to_int(detail); i++) {
|
||||
value *= (pwr * snoise_4d(p) + 1.0f);
|
||||
pwr *= roughness;
|
||||
p *= lacunarity;
|
||||
}
|
||||
|
||||
float rmd = detail - floorf(detail);
|
||||
if (rmd != 0.0f) {
|
||||
value *= (rmd * pwr * snoise_4d(p) + 1.0f); /* correct? */
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
/* Heterogeneous Terrain */
|
||||
|
||||
ccl_device_noinline float noise_hetero_terrain(
|
||||
float p, float detail, float roughness, float lacunarity, float offset)
|
||||
{
|
||||
float pwr = roughness;
|
||||
|
||||
/* first unscaled octave of function; later octaves are scaled */
|
||||
float value = offset + snoise_1d(p);
|
||||
p *= lacunarity;
|
||||
|
||||
for (int i = 1; i <= float_to_int(detail); i++) {
|
||||
float increment = (snoise_1d(p) + offset) * pwr * value;
|
||||
value += increment;
|
||||
pwr *= roughness;
|
||||
p *= lacunarity;
|
||||
}
|
||||
|
||||
float rmd = detail - floorf(detail);
|
||||
if (rmd != 0.0f) {
|
||||
float increment = (snoise_1d(p) + offset) * pwr * value;
|
||||
value += rmd * increment;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
ccl_device_noinline float noise_hetero_terrain(
|
||||
float2 p, float detail, float roughness, float lacunarity, float offset)
|
||||
{
|
||||
float pwr = roughness;
|
||||
|
||||
/* first unscaled octave of function; later octaves are scaled */
|
||||
float value = offset + snoise_2d(p);
|
||||
p *= lacunarity;
|
||||
|
||||
for (int i = 1; i <= float_to_int(detail); i++) {
|
||||
float increment = (snoise_2d(p) + offset) * pwr * value;
|
||||
value += increment;
|
||||
pwr *= roughness;
|
||||
p *= lacunarity;
|
||||
}
|
||||
|
||||
float rmd = detail - floorf(detail);
|
||||
if (rmd != 0.0f) {
|
||||
float increment = (snoise_2d(p) + offset) * pwr * value;
|
||||
value += rmd * increment;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
ccl_device_noinline float noise_hetero_terrain(
|
||||
float3 p, float detail, float roughness, float lacunarity, float offset)
|
||||
{
|
||||
float pwr = roughness;
|
||||
|
||||
/* first unscaled octave of function; later octaves are scaled */
|
||||
float value = offset + snoise_3d(p);
|
||||
p *= lacunarity;
|
||||
|
||||
for (int i = 1; i <= float_to_int(detail); i++) {
|
||||
float increment = (snoise_3d(p) + offset) * pwr * value;
|
||||
value += increment;
|
||||
pwr *= roughness;
|
||||
p *= lacunarity;
|
||||
}
|
||||
|
||||
float rmd = detail - floorf(detail);
|
||||
if (rmd != 0.0f) {
|
||||
float increment = (snoise_3d(p) + offset) * pwr * value;
|
||||
value += rmd * increment;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
ccl_device_noinline float noise_hetero_terrain(
|
||||
float4 p, float detail, float roughness, float lacunarity, float offset)
|
||||
{
|
||||
float pwr = roughness;
|
||||
|
||||
/* first unscaled octave of function; later octaves are scaled */
|
||||
float value = offset + snoise_4d(p);
|
||||
p *= lacunarity;
|
||||
|
||||
for (int i = 1; i <= float_to_int(detail); i++) {
|
||||
float increment = (snoise_4d(p) + offset) * pwr * value;
|
||||
value += increment;
|
||||
pwr *= roughness;
|
||||
p *= lacunarity;
|
||||
}
|
||||
|
||||
float rmd = detail - floorf(detail);
|
||||
if (rmd != 0.0f) {
|
||||
float increment = (snoise_4d(p) + offset) * pwr * value;
|
||||
value += rmd * increment;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
/* Hybrid Additive/Multiplicative Multifractal Terrain */
|
||||
|
||||
ccl_device_noinline float noise_hybrid_multi_fractal(
|
||||
float p, float detail, float roughness, float lacunarity, float offset, float gain)
|
||||
{
|
||||
float pwr = 1.0f;
|
||||
float value = 0.0f;
|
||||
float weight = 1.0f;
|
||||
|
||||
for (int i = 0; (weight > 0.001f) && (i <= float_to_int(detail)); i++) {
|
||||
if (weight > 1.0f) {
|
||||
weight = 1.0f;
|
||||
}
|
||||
|
||||
float signal = (snoise_1d(p) + offset) * pwr;
|
||||
pwr *= roughness;
|
||||
value += weight * signal;
|
||||
weight *= gain * signal;
|
||||
p *= lacunarity;
|
||||
}
|
||||
|
||||
float rmd = detail - floorf(detail);
|
||||
if ((rmd != 0.0f) && (weight > 0.001f)) {
|
||||
if (weight > 1.0f) {
|
||||
weight = 1.0f;
|
||||
}
|
||||
float signal = (snoise_1d(p) + offset) * pwr;
|
||||
value += rmd * weight * signal;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
ccl_device_noinline float noise_hybrid_multi_fractal(
|
||||
float2 p, float detail, float roughness, float lacunarity, float offset, float gain)
|
||||
{
|
||||
float pwr = 1.0f;
|
||||
float value = 0.0f;
|
||||
float weight = 1.0f;
|
||||
|
||||
for (int i = 0; (weight > 0.001f) && (i <= float_to_int(detail)); i++) {
|
||||
if (weight > 1.0f) {
|
||||
weight = 1.0f;
|
||||
}
|
||||
|
||||
float signal = (snoise_2d(p) + offset) * pwr;
|
||||
pwr *= roughness;
|
||||
value += weight * signal;
|
||||
weight *= gain * signal;
|
||||
p *= lacunarity;
|
||||
}
|
||||
|
||||
float rmd = detail - floorf(detail);
|
||||
if ((rmd != 0.0f) && (weight > 0.001f)) {
|
||||
if (weight > 1.0f) {
|
||||
weight = 1.0f;
|
||||
}
|
||||
float signal = (snoise_2d(p) + offset) * pwr;
|
||||
value += rmd * weight * signal;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
ccl_device_noinline float noise_hybrid_multi_fractal(
|
||||
float3 p, float detail, float roughness, float lacunarity, float offset, float gain)
|
||||
{
|
||||
float pwr = 1.0f;
|
||||
float value = 0.0f;
|
||||
float weight = 1.0f;
|
||||
|
||||
for (int i = 0; (weight > 0.001f) && (i <= float_to_int(detail)); i++) {
|
||||
if (weight > 1.0f) {
|
||||
weight = 1.0f;
|
||||
}
|
||||
|
||||
float signal = (snoise_3d(p) + offset) * pwr;
|
||||
pwr *= roughness;
|
||||
value += weight * signal;
|
||||
weight *= gain * signal;
|
||||
p *= lacunarity;
|
||||
}
|
||||
|
||||
float rmd = detail - floorf(detail);
|
||||
if ((rmd != 0.0f) && (weight > 0.001f)) {
|
||||
if (weight > 1.0f) {
|
||||
weight = 1.0f;
|
||||
}
|
||||
float signal = (snoise_3d(p) + offset) * pwr;
|
||||
value += rmd * weight * signal;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
ccl_device_noinline float noise_hybrid_multi_fractal(
|
||||
float4 p, float detail, float roughness, float lacunarity, float offset, float gain)
|
||||
{
|
||||
float pwr = 1.0f;
|
||||
float value = 0.0f;
|
||||
float weight = 1.0f;
|
||||
|
||||
for (int i = 0; (weight > 0.001f) && (i <= float_to_int(detail)); i++) {
|
||||
if (weight > 1.0f) {
|
||||
weight = 1.0f;
|
||||
}
|
||||
|
||||
float signal = (snoise_4d(p) + offset) * pwr;
|
||||
pwr *= roughness;
|
||||
value += weight * signal;
|
||||
weight *= gain * signal;
|
||||
p *= lacunarity;
|
||||
}
|
||||
|
||||
float rmd = detail - floorf(detail);
|
||||
if ((rmd != 0.0f) && (weight > 0.001f)) {
|
||||
if (weight > 1.0f) {
|
||||
weight = 1.0f;
|
||||
}
|
||||
float signal = (snoise_4d(p) + offset) * pwr;
|
||||
value += rmd * weight * signal;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
/* Ridged Multifractal Terrain */
|
||||
|
||||
ccl_device_noinline float noise_ridged_multi_fractal(
|
||||
float p, float detail, float roughness, float lacunarity, float offset, float gain)
|
||||
{
|
||||
float pwr = roughness;
|
||||
|
||||
float signal = offset - fabsf(snoise_1d(p));
|
||||
signal *= signal;
|
||||
float value = signal;
|
||||
float weight = 1.0f;
|
||||
|
||||
for (int i = 1; i <= float_to_int(detail); i++) {
|
||||
p *= lacunarity;
|
||||
weight = saturatef(signal * gain);
|
||||
signal = offset - fabsf(snoise_1d(p));
|
||||
signal *= signal;
|
||||
signal *= weight;
|
||||
value += signal * pwr;
|
||||
pwr *= roughness;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
ccl_device_noinline float noise_ridged_multi_fractal(
|
||||
float2 p, float detail, float roughness, float lacunarity, float offset, float gain)
|
||||
{
|
||||
float pwr = roughness;
|
||||
|
||||
float signal = offset - fabsf(snoise_2d(p));
|
||||
signal *= signal;
|
||||
float value = signal;
|
||||
float weight = 1.0f;
|
||||
|
||||
for (int i = 1; i <= float_to_int(detail); i++) {
|
||||
p *= lacunarity;
|
||||
weight = saturatef(signal * gain);
|
||||
signal = offset - fabsf(snoise_2d(p));
|
||||
signal *= signal;
|
||||
signal *= weight;
|
||||
value += signal * pwr;
|
||||
pwr *= roughness;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
ccl_device_noinline float noise_ridged_multi_fractal(
|
||||
float3 p, float detail, float roughness, float lacunarity, float offset, float gain)
|
||||
{
|
||||
float pwr = roughness;
|
||||
|
||||
float signal = offset - fabsf(snoise_3d(p));
|
||||
signal *= signal;
|
||||
float value = signal;
|
||||
float weight = 1.0f;
|
||||
|
||||
for (int i = 1; i <= float_to_int(detail); i++) {
|
||||
p *= lacunarity;
|
||||
weight = saturatef(signal * gain);
|
||||
signal = offset - fabsf(snoise_3d(p));
|
||||
signal *= signal;
|
||||
signal *= weight;
|
||||
value += signal * pwr;
|
||||
pwr *= roughness;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
ccl_device_noinline float noise_ridged_multi_fractal(
|
||||
float4 p, float detail, float roughness, float lacunarity, float offset, float gain)
|
||||
{
|
||||
float pwr = roughness;
|
||||
|
||||
float signal = offset - fabsf(snoise_4d(p));
|
||||
signal *= signal;
|
||||
float value = signal;
|
||||
float weight = 1.0f;
|
||||
|
||||
for (int i = 1; i <= float_to_int(detail); i++) {
|
||||
p *= lacunarity;
|
||||
weight = saturatef(signal * gain);
|
||||
signal = offset - fabsf(snoise_4d(p));
|
||||
signal *= signal;
|
||||
signal *= weight;
|
||||
value += signal * pwr;
|
||||
pwr *= roughness;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
|
||||
@@ -1,854 +0,0 @@
|
||||
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "kernel/svm/noise.h"
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
||||
/* 1D Musgrave fBm
|
||||
*
|
||||
* H: fractal increment parameter
|
||||
* lacunarity: gap between successive frequencies
|
||||
* octaves: number of frequencies in the fBm
|
||||
*
|
||||
* from "Texturing and Modelling: A procedural approach"
|
||||
*/
|
||||
|
||||
ccl_device_noinline_cpu float noise_musgrave_fBm_1d(float co,
|
||||
float H,
|
||||
float lacunarity,
|
||||
float octaves)
|
||||
{
|
||||
float p = co;
|
||||
float value = 0.0f;
|
||||
float pwr = 1.0f;
|
||||
float pwHL = powf(lacunarity, -H);
|
||||
|
||||
for (int i = 0; i < float_to_int(octaves); i++) {
|
||||
value += snoise_1d(p) * pwr;
|
||||
pwr *= pwHL;
|
||||
p *= lacunarity;
|
||||
}
|
||||
|
||||
float rmd = octaves - floorf(octaves);
|
||||
if (rmd != 0.0f) {
|
||||
value += rmd * snoise_1d(p) * pwr;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
/* 1D Musgrave Multifractal
|
||||
*
|
||||
* H: highest fractal dimension
|
||||
* lacunarity: gap between successive frequencies
|
||||
* octaves: number of frequencies in the fBm
|
||||
*/
|
||||
|
||||
ccl_device_noinline_cpu float noise_musgrave_multi_fractal_1d(float co,
|
||||
float H,
|
||||
float lacunarity,
|
||||
float octaves)
|
||||
{
|
||||
float p = co;
|
||||
float value = 1.0f;
|
||||
float pwr = 1.0f;
|
||||
float pwHL = powf(lacunarity, -H);
|
||||
|
||||
for (int i = 0; i < float_to_int(octaves); i++) {
|
||||
value *= (pwr * snoise_1d(p) + 1.0f);
|
||||
pwr *= pwHL;
|
||||
p *= lacunarity;
|
||||
}
|
||||
|
||||
float rmd = octaves - floorf(octaves);
|
||||
if (rmd != 0.0f) {
|
||||
value *= (rmd * pwr * snoise_1d(p) + 1.0f); /* correct? */
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
/* 1D Musgrave Heterogeneous Terrain
|
||||
*
|
||||
* H: fractal dimension of the roughest area
|
||||
* lacunarity: gap between successive frequencies
|
||||
* octaves: number of frequencies in the fBm
|
||||
* offset: raises the terrain from `sea level'
|
||||
*/
|
||||
|
||||
ccl_device_noinline_cpu float noise_musgrave_hetero_terrain_1d(
|
||||
float co, float H, float lacunarity, float octaves, float offset)
|
||||
{
|
||||
float p = co;
|
||||
float pwHL = powf(lacunarity, -H);
|
||||
float pwr = pwHL;
|
||||
|
||||
/* first unscaled octave of function; later octaves are scaled */
|
||||
float value = offset + snoise_1d(p);
|
||||
p *= lacunarity;
|
||||
|
||||
for (int i = 1; i < float_to_int(octaves); i++) {
|
||||
float increment = (snoise_1d(p) + offset) * pwr * value;
|
||||
value += increment;
|
||||
pwr *= pwHL;
|
||||
p *= lacunarity;
|
||||
}
|
||||
|
||||
float rmd = octaves - floorf(octaves);
|
||||
if (rmd != 0.0f) {
|
||||
float increment = (snoise_1d(p) + offset) * pwr * value;
|
||||
value += rmd * increment;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
/* 1D Hybrid Additive/Multiplicative Multifractal Terrain
|
||||
*
|
||||
* H: fractal dimension of the roughest area
|
||||
* lacunarity: gap between successive frequencies
|
||||
* octaves: number of frequencies in the fBm
|
||||
* offset: raises the terrain from `sea level'
|
||||
*/
|
||||
|
||||
ccl_device_noinline_cpu float noise_musgrave_hybrid_multi_fractal_1d(
|
||||
float co, float H, float lacunarity, float octaves, float offset, float gain)
|
||||
{
|
||||
float p = co;
|
||||
float pwHL = powf(lacunarity, -H);
|
||||
|
||||
float pwr = 1.0f;
|
||||
float value = 0.0f;
|
||||
float weight = 1.0f;
|
||||
|
||||
for (int i = 0; (weight > 0.001f) && (i < float_to_int(octaves)); i++) {
|
||||
if (weight > 1.0f) {
|
||||
weight = 1.0f;
|
||||
}
|
||||
|
||||
float signal = (snoise_1d(p) + offset) * pwr;
|
||||
pwr *= pwHL;
|
||||
value += weight * signal;
|
||||
weight *= gain * signal;
|
||||
p *= lacunarity;
|
||||
}
|
||||
|
||||
float rmd = octaves - floorf(octaves);
|
||||
if ((rmd != 0.0f) && (weight > 0.001f)) {
|
||||
if (weight > 1.0f) {
|
||||
weight = 1.0f;
|
||||
}
|
||||
float signal = (snoise_1d(p) + offset) * pwr;
|
||||
value += rmd * weight * signal;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
/* 1D Ridged Multifractal Terrain
|
||||
*
|
||||
* H: fractal dimension of the roughest area
|
||||
* lacunarity: gap between successive frequencies
|
||||
* octaves: number of frequencies in the fBm
|
||||
* offset: raises the terrain from `sea level'
|
||||
*/
|
||||
|
||||
ccl_device_noinline_cpu float noise_musgrave_ridged_multi_fractal_1d(
|
||||
float co, float H, float lacunarity, float octaves, float offset, float gain)
|
||||
{
|
||||
float p = co;
|
||||
float pwHL = powf(lacunarity, -H);
|
||||
float pwr = pwHL;
|
||||
|
||||
float signal = offset - fabsf(snoise_1d(p));
|
||||
signal *= signal;
|
||||
float value = signal;
|
||||
float weight = 1.0f;
|
||||
|
||||
for (int i = 1; i < float_to_int(octaves); i++) {
|
||||
p *= lacunarity;
|
||||
weight = saturatef(signal * gain);
|
||||
signal = offset - fabsf(snoise_1d(p));
|
||||
signal *= signal;
|
||||
signal *= weight;
|
||||
value += signal * pwr;
|
||||
pwr *= pwHL;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
/* 2D Musgrave fBm
|
||||
*
|
||||
* H: fractal increment parameter
|
||||
* lacunarity: gap between successive frequencies
|
||||
* octaves: number of frequencies in the fBm
|
||||
*
|
||||
* from "Texturing and Modelling: A procedural approach"
|
||||
*/
|
||||
|
||||
ccl_device_noinline_cpu float noise_musgrave_fBm_2d(float2 co,
|
||||
float H,
|
||||
float lacunarity,
|
||||
float octaves)
|
||||
{
|
||||
float2 p = co;
|
||||
float value = 0.0f;
|
||||
float pwr = 1.0f;
|
||||
float pwHL = powf(lacunarity, -H);
|
||||
|
||||
for (int i = 0; i < float_to_int(octaves); i++) {
|
||||
value += snoise_2d(p) * pwr;
|
||||
pwr *= pwHL;
|
||||
p *= lacunarity;
|
||||
}
|
||||
|
||||
float rmd = octaves - floorf(octaves);
|
||||
if (rmd != 0.0f) {
|
||||
value += rmd * snoise_2d(p) * pwr;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
/* 2D Musgrave Multifractal
|
||||
*
|
||||
* H: highest fractal dimension
|
||||
* lacunarity: gap between successive frequencies
|
||||
* octaves: number of frequencies in the fBm
|
||||
*/
|
||||
|
||||
ccl_device_noinline_cpu float noise_musgrave_multi_fractal_2d(float2 co,
|
||||
float H,
|
||||
float lacunarity,
|
||||
float octaves)
|
||||
{
|
||||
float2 p = co;
|
||||
float value = 1.0f;
|
||||
float pwr = 1.0f;
|
||||
float pwHL = powf(lacunarity, -H);
|
||||
|
||||
for (int i = 0; i < float_to_int(octaves); i++) {
|
||||
value *= (pwr * snoise_2d(p) + 1.0f);
|
||||
pwr *= pwHL;
|
||||
p *= lacunarity;
|
||||
}
|
||||
|
||||
float rmd = octaves - floorf(octaves);
|
||||
if (rmd != 0.0f) {
|
||||
value *= (rmd * pwr * snoise_2d(p) + 1.0f); /* correct? */
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
/* 2D Musgrave Heterogeneous Terrain
|
||||
*
|
||||
* H: fractal dimension of the roughest area
|
||||
* lacunarity: gap between successive frequencies
|
||||
* octaves: number of frequencies in the fBm
|
||||
* offset: raises the terrain from `sea level'
|
||||
*/
|
||||
|
||||
ccl_device_noinline_cpu float noise_musgrave_hetero_terrain_2d(
|
||||
float2 co, float H, float lacunarity, float octaves, float offset)
|
||||
{
|
||||
float2 p = co;
|
||||
float pwHL = powf(lacunarity, -H);
|
||||
float pwr = pwHL;
|
||||
|
||||
/* first unscaled octave of function; later octaves are scaled */
|
||||
float value = offset + snoise_2d(p);
|
||||
p *= lacunarity;
|
||||
|
||||
for (int i = 1; i < float_to_int(octaves); i++) {
|
||||
float increment = (snoise_2d(p) + offset) * pwr * value;
|
||||
value += increment;
|
||||
pwr *= pwHL;
|
||||
p *= lacunarity;
|
||||
}
|
||||
|
||||
float rmd = octaves - floorf(octaves);
|
||||
if (rmd != 0.0f) {
|
||||
float increment = (snoise_2d(p) + offset) * pwr * value;
|
||||
value += rmd * increment;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
/* 2D Hybrid Additive/Multiplicative Multifractal Terrain
|
||||
*
|
||||
* H: fractal dimension of the roughest area
|
||||
* lacunarity: gap between successive frequencies
|
||||
* octaves: number of frequencies in the fBm
|
||||
* offset: raises the terrain from `sea level'
|
||||
*/
|
||||
|
||||
ccl_device_noinline_cpu float noise_musgrave_hybrid_multi_fractal_2d(
|
||||
float2 co, float H, float lacunarity, float octaves, float offset, float gain)
|
||||
{
|
||||
float2 p = co;
|
||||
float pwHL = powf(lacunarity, -H);
|
||||
|
||||
float pwr = 1.0f;
|
||||
float value = 0.0f;
|
||||
float weight = 1.0f;
|
||||
|
||||
for (int i = 0; (weight > 0.001f) && (i < float_to_int(octaves)); i++) {
|
||||
if (weight > 1.0f) {
|
||||
weight = 1.0f;
|
||||
}
|
||||
|
||||
float signal = (snoise_2d(p) + offset) * pwr;
|
||||
pwr *= pwHL;
|
||||
value += weight * signal;
|
||||
weight *= gain * signal;
|
||||
p *= lacunarity;
|
||||
}
|
||||
|
||||
float rmd = octaves - floorf(octaves);
|
||||
if ((rmd != 0.0f) && (weight > 0.001f)) {
|
||||
if (weight > 1.0f) {
|
||||
weight = 1.0f;
|
||||
}
|
||||
float signal = (snoise_2d(p) + offset) * pwr;
|
||||
value += rmd * weight * signal;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
/* 2D Ridged Multifractal Terrain
|
||||
*
|
||||
* H: fractal dimension of the roughest area
|
||||
* lacunarity: gap between successive frequencies
|
||||
* octaves: number of frequencies in the fBm
|
||||
* offset: raises the terrain from `sea level'
|
||||
*/
|
||||
|
||||
ccl_device_noinline_cpu float noise_musgrave_ridged_multi_fractal_2d(
|
||||
float2 co, float H, float lacunarity, float octaves, float offset, float gain)
|
||||
{
|
||||
float2 p = co;
|
||||
float pwHL = powf(lacunarity, -H);
|
||||
float pwr = pwHL;
|
||||
|
||||
float signal = offset - fabsf(snoise_2d(p));
|
||||
signal *= signal;
|
||||
float value = signal;
|
||||
float weight = 1.0f;
|
||||
|
||||
for (int i = 1; i < float_to_int(octaves); i++) {
|
||||
p *= lacunarity;
|
||||
weight = saturatef(signal * gain);
|
||||
signal = offset - fabsf(snoise_2d(p));
|
||||
signal *= signal;
|
||||
signal *= weight;
|
||||
value += signal * pwr;
|
||||
pwr *= pwHL;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
/* 3D Musgrave fBm
|
||||
*
|
||||
* H: fractal increment parameter
|
||||
* lacunarity: gap between successive frequencies
|
||||
* octaves: number of frequencies in the fBm
|
||||
*
|
||||
* from "Texturing and Modelling: A procedural approach"
|
||||
*/
|
||||
|
||||
ccl_device_noinline_cpu float noise_musgrave_fBm_3d(float3 co,
|
||||
float H,
|
||||
float lacunarity,
|
||||
float octaves)
|
||||
{
|
||||
float3 p = co;
|
||||
float value = 0.0f;
|
||||
float pwr = 1.0f;
|
||||
float pwHL = powf(lacunarity, -H);
|
||||
|
||||
for (int i = 0; i < float_to_int(octaves); i++) {
|
||||
value += snoise_3d(p) * pwr;
|
||||
pwr *= pwHL;
|
||||
p *= lacunarity;
|
||||
}
|
||||
|
||||
float rmd = octaves - floorf(octaves);
|
||||
if (rmd != 0.0f) {
|
||||
value += rmd * snoise_3d(p) * pwr;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
/* 3D Musgrave Multifractal
|
||||
*
|
||||
* H: highest fractal dimension
|
||||
* lacunarity: gap between successive frequencies
|
||||
* octaves: number of frequencies in the fBm
|
||||
*/
|
||||
|
||||
ccl_device_noinline_cpu float noise_musgrave_multi_fractal_3d(float3 co,
|
||||
float H,
|
||||
float lacunarity,
|
||||
float octaves)
|
||||
{
|
||||
float3 p = co;
|
||||
float value = 1.0f;
|
||||
float pwr = 1.0f;
|
||||
float pwHL = powf(lacunarity, -H);
|
||||
|
||||
for (int i = 0; i < float_to_int(octaves); i++) {
|
||||
value *= (pwr * snoise_3d(p) + 1.0f);
|
||||
pwr *= pwHL;
|
||||
p *= lacunarity;
|
||||
}
|
||||
|
||||
float rmd = octaves - floorf(octaves);
|
||||
if (rmd != 0.0f) {
|
||||
value *= (rmd * pwr * snoise_3d(p) + 1.0f); /* correct? */
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
/* 3D Musgrave Heterogeneous Terrain
|
||||
*
|
||||
* H: fractal dimension of the roughest area
|
||||
* lacunarity: gap between successive frequencies
|
||||
* octaves: number of frequencies in the fBm
|
||||
* offset: raises the terrain from `sea level'
|
||||
*/
|
||||
|
||||
ccl_device_noinline_cpu float noise_musgrave_hetero_terrain_3d(
|
||||
float3 co, float H, float lacunarity, float octaves, float offset)
|
||||
{
|
||||
float3 p = co;
|
||||
float pwHL = powf(lacunarity, -H);
|
||||
float pwr = pwHL;
|
||||
|
||||
/* first unscaled octave of function; later octaves are scaled */
|
||||
float value = offset + snoise_3d(p);
|
||||
p *= lacunarity;
|
||||
|
||||
for (int i = 1; i < float_to_int(octaves); i++) {
|
||||
float increment = (snoise_3d(p) + offset) * pwr * value;
|
||||
value += increment;
|
||||
pwr *= pwHL;
|
||||
p *= lacunarity;
|
||||
}
|
||||
|
||||
float rmd = octaves - floorf(octaves);
|
||||
if (rmd != 0.0f) {
|
||||
float increment = (snoise_3d(p) + offset) * pwr * value;
|
||||
value += rmd * increment;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
/* 3D Hybrid Additive/Multiplicative Multifractal Terrain
|
||||
*
|
||||
* H: fractal dimension of the roughest area
|
||||
* lacunarity: gap between successive frequencies
|
||||
* octaves: number of frequencies in the fBm
|
||||
* offset: raises the terrain from `sea level'
|
||||
*/
|
||||
|
||||
ccl_device_noinline_cpu float noise_musgrave_hybrid_multi_fractal_3d(
|
||||
float3 co, float H, float lacunarity, float octaves, float offset, float gain)
|
||||
{
|
||||
float3 p = co;
|
||||
float pwHL = powf(lacunarity, -H);
|
||||
|
||||
float pwr = 1.0f;
|
||||
float value = 0.0f;
|
||||
float weight = 1.0f;
|
||||
|
||||
for (int i = 0; (weight > 0.001f) && (i < float_to_int(octaves)); i++) {
|
||||
if (weight > 1.0f) {
|
||||
weight = 1.0f;
|
||||
}
|
||||
|
||||
float signal = (snoise_3d(p) + offset) * pwr;
|
||||
pwr *= pwHL;
|
||||
value += weight * signal;
|
||||
weight *= gain * signal;
|
||||
p *= lacunarity;
|
||||
}
|
||||
|
||||
float rmd = octaves - floorf(octaves);
|
||||
if ((rmd != 0.0f) && (weight > 0.001f)) {
|
||||
if (weight > 1.0f) {
|
||||
weight = 1.0f;
|
||||
}
|
||||
float signal = (snoise_3d(p) + offset) * pwr;
|
||||
value += rmd * weight * signal;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
/* 3D Ridged Multifractal Terrain
|
||||
*
|
||||
* H: fractal dimension of the roughest area
|
||||
* lacunarity: gap between successive frequencies
|
||||
* octaves: number of frequencies in the fBm
|
||||
* offset: raises the terrain from `sea level'
|
||||
*/
|
||||
|
||||
ccl_device_noinline_cpu float noise_musgrave_ridged_multi_fractal_3d(
|
||||
float3 co, float H, float lacunarity, float octaves, float offset, float gain)
|
||||
{
|
||||
float3 p = co;
|
||||
float pwHL = powf(lacunarity, -H);
|
||||
float pwr = pwHL;
|
||||
|
||||
float signal = offset - fabsf(snoise_3d(p));
|
||||
signal *= signal;
|
||||
float value = signal;
|
||||
float weight = 1.0f;
|
||||
|
||||
for (int i = 1; i < float_to_int(octaves); i++) {
|
||||
p *= lacunarity;
|
||||
weight = saturatef(signal * gain);
|
||||
signal = offset - fabsf(snoise_3d(p));
|
||||
signal *= signal;
|
||||
signal *= weight;
|
||||
value += signal * pwr;
|
||||
pwr *= pwHL;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
/* 4D Musgrave fBm
|
||||
*
|
||||
* H: fractal increment parameter
|
||||
* lacunarity: gap between successive frequencies
|
||||
* octaves: number of frequencies in the fBm
|
||||
*
|
||||
* from "Texturing and Modelling: A procedural approach"
|
||||
*/
|
||||
|
||||
ccl_device_noinline_cpu float noise_musgrave_fBm_4d(float4 co,
|
||||
float H,
|
||||
float lacunarity,
|
||||
float octaves)
|
||||
{
|
||||
float4 p = co;
|
||||
float value = 0.0f;
|
||||
float pwr = 1.0f;
|
||||
float pwHL = powf(lacunarity, -H);
|
||||
|
||||
for (int i = 0; i < float_to_int(octaves); i++) {
|
||||
value += snoise_4d(p) * pwr;
|
||||
pwr *= pwHL;
|
||||
p *= lacunarity;
|
||||
}
|
||||
|
||||
float rmd = octaves - floorf(octaves);
|
||||
if (rmd != 0.0f) {
|
||||
value += rmd * snoise_4d(p) * pwr;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
/* 4D Musgrave Multifractal
|
||||
*
|
||||
* H: highest fractal dimension
|
||||
* lacunarity: gap between successive frequencies
|
||||
* octaves: number of frequencies in the fBm
|
||||
*/
|
||||
|
||||
ccl_device_noinline_cpu float noise_musgrave_multi_fractal_4d(float4 co,
|
||||
float H,
|
||||
float lacunarity,
|
||||
float octaves)
|
||||
{
|
||||
float4 p = co;
|
||||
float value = 1.0f;
|
||||
float pwr = 1.0f;
|
||||
float pwHL = powf(lacunarity, -H);
|
||||
|
||||
for (int i = 0; i < float_to_int(octaves); i++) {
|
||||
value *= (pwr * snoise_4d(p) + 1.0f);
|
||||
pwr *= pwHL;
|
||||
p *= lacunarity;
|
||||
}
|
||||
|
||||
float rmd = octaves - floorf(octaves);
|
||||
if (rmd != 0.0f) {
|
||||
value *= (rmd * pwr * snoise_4d(p) + 1.0f); /* correct? */
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
/* 4D Musgrave Heterogeneous Terrain
|
||||
*
|
||||
* H: fractal dimension of the roughest area
|
||||
* lacunarity: gap between successive frequencies
|
||||
* octaves: number of frequencies in the fBm
|
||||
* offset: raises the terrain from `sea level'
|
||||
*/
|
||||
|
||||
ccl_device_noinline_cpu float noise_musgrave_hetero_terrain_4d(
|
||||
float4 co, float H, float lacunarity, float octaves, float offset)
|
||||
{
|
||||
float4 p = co;
|
||||
float pwHL = powf(lacunarity, -H);
|
||||
float pwr = pwHL;
|
||||
|
||||
/* first unscaled octave of function; later octaves are scaled */
|
||||
float value = offset + snoise_4d(p);
|
||||
p *= lacunarity;
|
||||
|
||||
for (int i = 1; i < float_to_int(octaves); i++) {
|
||||
float increment = (snoise_4d(p) + offset) * pwr * value;
|
||||
value += increment;
|
||||
pwr *= pwHL;
|
||||
p *= lacunarity;
|
||||
}
|
||||
|
||||
float rmd = octaves - floorf(octaves);
|
||||
if (rmd != 0.0f) {
|
||||
float increment = (snoise_4d(p) + offset) * pwr * value;
|
||||
value += rmd * increment;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
/* 4D Hybrid Additive/Multiplicative Multifractal Terrain
|
||||
*
|
||||
* H: fractal dimension of the roughest area
|
||||
* lacunarity: gap between successive frequencies
|
||||
* octaves: number of frequencies in the fBm
|
||||
* offset: raises the terrain from `sea level'
|
||||
*/
|
||||
|
||||
ccl_device_noinline_cpu float noise_musgrave_hybrid_multi_fractal_4d(
|
||||
float4 co, float H, float lacunarity, float octaves, float offset, float gain)
|
||||
{
|
||||
float4 p = co;
|
||||
float pwHL = powf(lacunarity, -H);
|
||||
|
||||
float pwr = 1.0f;
|
||||
float value = 0.0f;
|
||||
float weight = 1.0f;
|
||||
|
||||
for (int i = 0; (weight > 0.001f) && (i < float_to_int(octaves)); i++) {
|
||||
if (weight > 1.0f) {
|
||||
weight = 1.0f;
|
||||
}
|
||||
|
||||
float signal = (snoise_4d(p) + offset) * pwr;
|
||||
pwr *= pwHL;
|
||||
value += weight * signal;
|
||||
weight *= gain * signal;
|
||||
p *= lacunarity;
|
||||
}
|
||||
|
||||
float rmd = octaves - floorf(octaves);
|
||||
if ((rmd != 0.0f) && (weight > 0.001f)) {
|
||||
if (weight > 1.0f) {
|
||||
weight = 1.0f;
|
||||
}
|
||||
float signal = (snoise_4d(p) + offset) * pwr;
|
||||
value += rmd * weight * signal;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
/* 4D Ridged Multifractal Terrain
|
||||
*
|
||||
* H: fractal dimension of the roughest area
|
||||
* lacunarity: gap between successive frequencies
|
||||
* octaves: number of frequencies in the fBm
|
||||
* offset: raises the terrain from `sea level'
|
||||
*/
|
||||
|
||||
ccl_device_noinline_cpu float noise_musgrave_ridged_multi_fractal_4d(
|
||||
float4 co, float H, float lacunarity, float octaves, float offset, float gain)
|
||||
{
|
||||
float4 p = co;
|
||||
float pwHL = powf(lacunarity, -H);
|
||||
float pwr = pwHL;
|
||||
|
||||
float signal = offset - fabsf(snoise_4d(p));
|
||||
signal *= signal;
|
||||
float value = signal;
|
||||
float weight = 1.0f;
|
||||
|
||||
for (int i = 1; i < float_to_int(octaves); i++) {
|
||||
p *= lacunarity;
|
||||
weight = saturatef(signal * gain);
|
||||
signal = offset - fabsf(snoise_4d(p));
|
||||
signal *= signal;
|
||||
signal *= weight;
|
||||
value += signal * pwr;
|
||||
pwr *= pwHL;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
ccl_device_noinline int svm_node_tex_musgrave(KernelGlobals kg,
|
||||
ccl_private ShaderData *sd,
|
||||
ccl_private float *stack,
|
||||
uint offsets1,
|
||||
uint offsets2,
|
||||
uint offsets3,
|
||||
int offset)
|
||||
{
|
||||
uint type, dimensions, co_stack_offset, w_stack_offset;
|
||||
uint scale_stack_offset, detail_stack_offset, dimension_stack_offset, lacunarity_stack_offset;
|
||||
uint offset_stack_offset, gain_stack_offset, fac_stack_offset;
|
||||
|
||||
svm_unpack_node_uchar4(offsets1, &type, &dimensions, &co_stack_offset, &w_stack_offset);
|
||||
svm_unpack_node_uchar4(offsets2,
|
||||
&scale_stack_offset,
|
||||
&detail_stack_offset,
|
||||
&dimension_stack_offset,
|
||||
&lacunarity_stack_offset);
|
||||
svm_unpack_node_uchar3(offsets3, &offset_stack_offset, &gain_stack_offset, &fac_stack_offset);
|
||||
|
||||
uint4 defaults1 = read_node(kg, &offset);
|
||||
uint4 defaults2 = read_node(kg, &offset);
|
||||
|
||||
float3 co = stack_load_float3(stack, co_stack_offset);
|
||||
float w = stack_load_float_default(stack, w_stack_offset, defaults1.x);
|
||||
float scale = stack_load_float_default(stack, scale_stack_offset, defaults1.y);
|
||||
float detail = stack_load_float_default(stack, detail_stack_offset, defaults1.z);
|
||||
float dimension = stack_load_float_default(stack, dimension_stack_offset, defaults1.w);
|
||||
float lacunarity = stack_load_float_default(stack, lacunarity_stack_offset, defaults2.x);
|
||||
float foffset = stack_load_float_default(stack, offset_stack_offset, defaults2.y);
|
||||
float gain = stack_load_float_default(stack, gain_stack_offset, defaults2.z);
|
||||
|
||||
dimension = fmaxf(dimension, 1e-5f);
|
||||
detail = clamp(detail, 0.0f, 15.0f);
|
||||
lacunarity = fmaxf(lacunarity, 1e-5f);
|
||||
|
||||
float fac;
|
||||
|
||||
switch (dimensions) {
|
||||
case 1: {
|
||||
float p = w * scale;
|
||||
switch ((NodeMusgraveType)type) {
|
||||
case NODE_MUSGRAVE_MULTIFRACTAL:
|
||||
fac = noise_musgrave_multi_fractal_1d(p, dimension, lacunarity, detail);
|
||||
break;
|
||||
case NODE_MUSGRAVE_FBM:
|
||||
fac = noise_musgrave_fBm_1d(p, dimension, lacunarity, detail);
|
||||
break;
|
||||
case NODE_MUSGRAVE_HYBRID_MULTIFRACTAL:
|
||||
fac = noise_musgrave_hybrid_multi_fractal_1d(
|
||||
p, dimension, lacunarity, detail, foffset, gain);
|
||||
break;
|
||||
case NODE_MUSGRAVE_RIDGED_MULTIFRACTAL:
|
||||
fac = noise_musgrave_ridged_multi_fractal_1d(
|
||||
p, dimension, lacunarity, detail, foffset, gain);
|
||||
break;
|
||||
case NODE_MUSGRAVE_HETERO_TERRAIN:
|
||||
fac = noise_musgrave_hetero_terrain_1d(p, dimension, lacunarity, detail, foffset);
|
||||
break;
|
||||
default:
|
||||
fac = 0.0f;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 2: {
|
||||
float2 p = make_float2(co.x, co.y) * scale;
|
||||
switch ((NodeMusgraveType)type) {
|
||||
case NODE_MUSGRAVE_MULTIFRACTAL:
|
||||
fac = noise_musgrave_multi_fractal_2d(p, dimension, lacunarity, detail);
|
||||
break;
|
||||
case NODE_MUSGRAVE_FBM:
|
||||
fac = noise_musgrave_fBm_2d(p, dimension, lacunarity, detail);
|
||||
break;
|
||||
case NODE_MUSGRAVE_HYBRID_MULTIFRACTAL:
|
||||
fac = noise_musgrave_hybrid_multi_fractal_2d(
|
||||
p, dimension, lacunarity, detail, foffset, gain);
|
||||
break;
|
||||
case NODE_MUSGRAVE_RIDGED_MULTIFRACTAL:
|
||||
fac = noise_musgrave_ridged_multi_fractal_2d(
|
||||
p, dimension, lacunarity, detail, foffset, gain);
|
||||
break;
|
||||
case NODE_MUSGRAVE_HETERO_TERRAIN:
|
||||
fac = noise_musgrave_hetero_terrain_2d(p, dimension, lacunarity, detail, foffset);
|
||||
break;
|
||||
default:
|
||||
fac = 0.0f;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 3: {
|
||||
float3 p = co * scale;
|
||||
switch ((NodeMusgraveType)type) {
|
||||
case NODE_MUSGRAVE_MULTIFRACTAL:
|
||||
fac = noise_musgrave_multi_fractal_3d(p, dimension, lacunarity, detail);
|
||||
break;
|
||||
case NODE_MUSGRAVE_FBM:
|
||||
fac = noise_musgrave_fBm_3d(p, dimension, lacunarity, detail);
|
||||
break;
|
||||
case NODE_MUSGRAVE_HYBRID_MULTIFRACTAL:
|
||||
fac = noise_musgrave_hybrid_multi_fractal_3d(
|
||||
p, dimension, lacunarity, detail, foffset, gain);
|
||||
break;
|
||||
case NODE_MUSGRAVE_RIDGED_MULTIFRACTAL:
|
||||
fac = noise_musgrave_ridged_multi_fractal_3d(
|
||||
p, dimension, lacunarity, detail, foffset, gain);
|
||||
break;
|
||||
case NODE_MUSGRAVE_HETERO_TERRAIN:
|
||||
fac = noise_musgrave_hetero_terrain_3d(p, dimension, lacunarity, detail, foffset);
|
||||
break;
|
||||
default:
|
||||
fac = 0.0f;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 4: {
|
||||
float4 p = make_float4(co.x, co.y, co.z, w) * scale;
|
||||
switch ((NodeMusgraveType)type) {
|
||||
case NODE_MUSGRAVE_MULTIFRACTAL:
|
||||
fac = noise_musgrave_multi_fractal_4d(p, dimension, lacunarity, detail);
|
||||
break;
|
||||
case NODE_MUSGRAVE_FBM:
|
||||
fac = noise_musgrave_fBm_4d(p, dimension, lacunarity, detail);
|
||||
break;
|
||||
case NODE_MUSGRAVE_HYBRID_MULTIFRACTAL:
|
||||
fac = noise_musgrave_hybrid_multi_fractal_4d(
|
||||
p, dimension, lacunarity, detail, foffset, gain);
|
||||
break;
|
||||
case NODE_MUSGRAVE_RIDGED_MULTIFRACTAL:
|
||||
fac = noise_musgrave_ridged_multi_fractal_4d(
|
||||
p, dimension, lacunarity, detail, foffset, gain);
|
||||
break;
|
||||
case NODE_MUSGRAVE_HETERO_TERRAIN:
|
||||
fac = noise_musgrave_hetero_terrain_4d(p, dimension, lacunarity, detail, foffset);
|
||||
break;
|
||||
default:
|
||||
fac = 0.0f;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
fac = 0.0f;
|
||||
}
|
||||
|
||||
stack_store_float(stack, fac_stack_offset, fac);
|
||||
return offset;
|
||||
}
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
@@ -69,7 +69,6 @@ SHADER_NODE_TYPE(NODE_TEX_ENVIRONMENT)
|
||||
SHADER_NODE_TYPE(NODE_TEX_SKY)
|
||||
SHADER_NODE_TYPE(NODE_TEX_GRADIENT)
|
||||
SHADER_NODE_TYPE(NODE_TEX_VORONOI)
|
||||
SHADER_NODE_TYPE(NODE_TEX_MUSGRAVE)
|
||||
SHADER_NODE_TYPE(NODE_TEX_WAVE)
|
||||
SHADER_NODE_TYPE(NODE_TEX_MAGIC)
|
||||
SHADER_NODE_TYPE(NODE_TEX_CHECKER)
|
||||
@@ -111,5 +110,6 @@ SHADER_NODE_TYPE(NODE_MIX_VECTOR_NON_UNIFORM)
|
||||
|
||||
/* Padding for struct alignment. */
|
||||
SHADER_NODE_TYPE(NODE_PAD1)
|
||||
SHADER_NODE_TYPE(NODE_PAD2)
|
||||
|
||||
#undef SHADER_NODE_TYPE
|
||||
|
||||
@@ -42,11 +42,47 @@ ccl_device_inline float4 random_float4_offset(float seed)
|
||||
100.0f + hash_float2_to_float(make_float2(seed, 3.0f)) * 100.0f);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ccl_device float noise_select(T p,
|
||||
float detail,
|
||||
float roughness,
|
||||
float lacunarity,
|
||||
float offset,
|
||||
float gain,
|
||||
int type,
|
||||
bool normalize)
|
||||
{
|
||||
switch ((NodeNoiseType)type) {
|
||||
case NODE_NOISE_MULTIFRACTAL: {
|
||||
return noise_multi_fractal(p, detail, roughness, lacunarity);
|
||||
}
|
||||
case NODE_NOISE_FBM: {
|
||||
return noise_fbm(p, detail, roughness, lacunarity, normalize);
|
||||
}
|
||||
case NODE_NOISE_HYBRID_MULTIFRACTAL: {
|
||||
return noise_hybrid_multi_fractal(p, detail, roughness, lacunarity, offset, gain);
|
||||
}
|
||||
case NODE_NOISE_RIDGED_MULTIFRACTAL: {
|
||||
return noise_ridged_multi_fractal(p, detail, roughness, lacunarity, offset, gain);
|
||||
}
|
||||
case NODE_NOISE_HETERO_TERRAIN: {
|
||||
return noise_hetero_terrain(p, detail, roughness, lacunarity, offset);
|
||||
}
|
||||
default: {
|
||||
kernel_assert(0);
|
||||
return 0.0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ccl_device void noise_texture_1d(float co,
|
||||
float detail,
|
||||
float roughness,
|
||||
float lacunarity,
|
||||
float offset,
|
||||
float gain,
|
||||
float distortion,
|
||||
int type,
|
||||
bool normalize,
|
||||
bool color_is_needed,
|
||||
ccl_private float *value,
|
||||
@@ -57,12 +93,25 @@ ccl_device void noise_texture_1d(float co,
|
||||
p += snoise_1d(p + random_float_offset(0.0f)) * distortion;
|
||||
}
|
||||
|
||||
*value = fractal_noise_1d(p, detail, roughness, lacunarity, normalize);
|
||||
*value = noise_select(p, detail, roughness, lacunarity, offset, gain, type, normalize);
|
||||
if (color_is_needed) {
|
||||
*color = make_float3(
|
||||
*value,
|
||||
fractal_noise_1d(p + random_float_offset(1.0f), detail, roughness, lacunarity, normalize),
|
||||
fractal_noise_1d(p + random_float_offset(2.0f), detail, roughness, lacunarity, normalize));
|
||||
*color = make_float3(*value,
|
||||
noise_select(p + random_float_offset(1.0f),
|
||||
detail,
|
||||
roughness,
|
||||
lacunarity,
|
||||
offset,
|
||||
gain,
|
||||
type,
|
||||
normalize),
|
||||
noise_select(p + random_float_offset(2.0f),
|
||||
detail,
|
||||
roughness,
|
||||
lacunarity,
|
||||
offset,
|
||||
gain,
|
||||
type,
|
||||
normalize));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -70,7 +119,10 @@ ccl_device void noise_texture_2d(float2 co,
|
||||
float detail,
|
||||
float roughness,
|
||||
float lacunarity,
|
||||
float offset,
|
||||
float gain,
|
||||
float distortion,
|
||||
int type,
|
||||
bool normalize,
|
||||
bool color_is_needed,
|
||||
ccl_private float *value,
|
||||
@@ -82,13 +134,25 @@ ccl_device void noise_texture_2d(float2 co,
|
||||
snoise_2d(p + random_float2_offset(1.0f)) * distortion);
|
||||
}
|
||||
|
||||
*value = fractal_noise_2d(p, detail, roughness, lacunarity, normalize);
|
||||
*value = noise_select(p, detail, roughness, lacunarity, offset, gain, type, normalize);
|
||||
if (color_is_needed) {
|
||||
*color = make_float3(
|
||||
*value,
|
||||
fractal_noise_2d(p + random_float2_offset(2.0f), detail, roughness, lacunarity, normalize),
|
||||
fractal_noise_2d(
|
||||
p + random_float2_offset(3.0f), detail, roughness, lacunarity, normalize));
|
||||
*color = make_float3(*value,
|
||||
noise_select(p + random_float2_offset(2.0f),
|
||||
detail,
|
||||
roughness,
|
||||
lacunarity,
|
||||
offset,
|
||||
gain,
|
||||
type,
|
||||
normalize),
|
||||
noise_select(p + random_float2_offset(3.0f),
|
||||
detail,
|
||||
roughness,
|
||||
lacunarity,
|
||||
offset,
|
||||
gain,
|
||||
type,
|
||||
normalize));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -96,7 +160,10 @@ ccl_device void noise_texture_3d(float3 co,
|
||||
float detail,
|
||||
float roughness,
|
||||
float lacunarity,
|
||||
float offset,
|
||||
float gain,
|
||||
float distortion,
|
||||
int type,
|
||||
bool normalize,
|
||||
bool color_is_needed,
|
||||
ccl_private float *value,
|
||||
@@ -109,13 +176,25 @@ ccl_device void noise_texture_3d(float3 co,
|
||||
snoise_3d(p + random_float3_offset(2.0f)) * distortion);
|
||||
}
|
||||
|
||||
*value = fractal_noise_3d(p, detail, roughness, lacunarity, normalize);
|
||||
*value = noise_select(p, detail, roughness, lacunarity, offset, gain, type, normalize);
|
||||
if (color_is_needed) {
|
||||
*color = make_float3(
|
||||
*value,
|
||||
fractal_noise_3d(p + random_float3_offset(3.0f), detail, roughness, lacunarity, normalize),
|
||||
fractal_noise_3d(
|
||||
p + random_float3_offset(4.0f), detail, roughness, lacunarity, normalize));
|
||||
*color = make_float3(*value,
|
||||
noise_select(p + random_float3_offset(3.0f),
|
||||
detail,
|
||||
roughness,
|
||||
lacunarity,
|
||||
offset,
|
||||
gain,
|
||||
type,
|
||||
normalize),
|
||||
noise_select(p + random_float3_offset(4.0f),
|
||||
detail,
|
||||
roughness,
|
||||
lacunarity,
|
||||
offset,
|
||||
gain,
|
||||
type,
|
||||
normalize));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -123,7 +202,10 @@ ccl_device void noise_texture_4d(float4 co,
|
||||
float detail,
|
||||
float roughness,
|
||||
float lacunarity,
|
||||
float offset,
|
||||
float gain,
|
||||
float distortion,
|
||||
int type,
|
||||
bool normalize,
|
||||
bool color_is_needed,
|
||||
ccl_private float *value,
|
||||
@@ -137,13 +219,25 @@ ccl_device void noise_texture_4d(float4 co,
|
||||
snoise_4d(p + random_float4_offset(3.0f)) * distortion);
|
||||
}
|
||||
|
||||
*value = fractal_noise_4d(p, detail, roughness, lacunarity, normalize);
|
||||
*value = noise_select(p, detail, roughness, lacunarity, offset, gain, type, normalize);
|
||||
if (color_is_needed) {
|
||||
*color = make_float3(
|
||||
*value,
|
||||
fractal_noise_4d(p + random_float4_offset(4.0f), detail, roughness, lacunarity, normalize),
|
||||
fractal_noise_4d(
|
||||
p + random_float4_offset(5.0f), detail, roughness, lacunarity, normalize));
|
||||
*color = make_float3(*value,
|
||||
noise_select(p + random_float4_offset(4.0f),
|
||||
detail,
|
||||
roughness,
|
||||
lacunarity,
|
||||
offset,
|
||||
gain,
|
||||
type,
|
||||
normalize),
|
||||
noise_select(p + random_float4_offset(5.0f),
|
||||
detail,
|
||||
roughness,
|
||||
lacunarity,
|
||||
offset,
|
||||
gain,
|
||||
type,
|
||||
normalize));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -153,24 +247,29 @@ ccl_device_noinline int svm_node_tex_noise(KernelGlobals kg,
|
||||
uint offsets1,
|
||||
uint offsets2,
|
||||
uint offsets3,
|
||||
int offset)
|
||||
int node_offset)
|
||||
{
|
||||
uint vector_stack_offset, w_stack_offset, scale_stack_offset, detail_stack_offset;
|
||||
uint roughness_stack_offset, lacunarity_stack_offset, distortion_stack_offset,
|
||||
value_stack_offset;
|
||||
uint color_stack_offset, dimensions, normalize;
|
||||
uint roughness_stack_offset, lacunarity_stack_offset, offset_stack_offset, gain_stack_offset;
|
||||
uint distortion_stack_offset, value_stack_offset, color_stack_offset;
|
||||
|
||||
svm_unpack_node_uchar4(
|
||||
offsets1, &vector_stack_offset, &w_stack_offset, &scale_stack_offset, &detail_stack_offset);
|
||||
svm_unpack_node_uchar4(offsets2,
|
||||
&roughness_stack_offset,
|
||||
&lacunarity_stack_offset,
|
||||
&distortion_stack_offset,
|
||||
&value_stack_offset);
|
||||
svm_unpack_node_uchar3(offsets3, &color_stack_offset, &dimensions, &normalize);
|
||||
&offset_stack_offset,
|
||||
&gain_stack_offset);
|
||||
svm_unpack_node_uchar3(
|
||||
offsets3, &distortion_stack_offset, &value_stack_offset, &color_stack_offset);
|
||||
|
||||
uint4 defaults1 = read_node(kg, &offset);
|
||||
uint4 defaults2 = read_node(kg, &offset);
|
||||
uint4 defaults1 = read_node(kg, &node_offset);
|
||||
uint4 defaults2 = read_node(kg, &node_offset);
|
||||
uint4 properties = read_node(kg, &node_offset);
|
||||
|
||||
uint dimensions = properties.x;
|
||||
uint type = properties.y;
|
||||
uint normalize = properties.z;
|
||||
|
||||
float3 vector = stack_load_float3(stack, vector_stack_offset);
|
||||
float w = stack_load_float_default(stack, w_stack_offset, defaults1.x);
|
||||
@@ -178,7 +277,12 @@ ccl_device_noinline int svm_node_tex_noise(KernelGlobals kg,
|
||||
float detail = stack_load_float_default(stack, detail_stack_offset, defaults1.z);
|
||||
float roughness = stack_load_float_default(stack, roughness_stack_offset, defaults1.w);
|
||||
float lacunarity = stack_load_float_default(stack, lacunarity_stack_offset, defaults2.x);
|
||||
float distortion = stack_load_float_default(stack, distortion_stack_offset, defaults2.y);
|
||||
float offset = stack_load_float_default(stack, offset_stack_offset, defaults2.y);
|
||||
float gain = stack_load_float_default(stack, gain_stack_offset, defaults2.z);
|
||||
float distortion = stack_load_float_default(stack, distortion_stack_offset, defaults2.w);
|
||||
|
||||
detail = clamp(detail, 0.0f, 15.0f);
|
||||
roughness = fmaxf(roughness, 0.0f);
|
||||
|
||||
vector *= scale;
|
||||
w *= scale;
|
||||
@@ -191,7 +295,10 @@ ccl_device_noinline int svm_node_tex_noise(KernelGlobals kg,
|
||||
detail,
|
||||
roughness,
|
||||
lacunarity,
|
||||
offset,
|
||||
gain,
|
||||
distortion,
|
||||
type,
|
||||
normalize,
|
||||
stack_valid(color_stack_offset),
|
||||
&value,
|
||||
@@ -202,7 +309,10 @@ ccl_device_noinline int svm_node_tex_noise(KernelGlobals kg,
|
||||
detail,
|
||||
roughness,
|
||||
lacunarity,
|
||||
offset,
|
||||
gain,
|
||||
distortion,
|
||||
type,
|
||||
normalize,
|
||||
stack_valid(color_stack_offset),
|
||||
&value,
|
||||
@@ -213,7 +323,10 @@ ccl_device_noinline int svm_node_tex_noise(KernelGlobals kg,
|
||||
detail,
|
||||
roughness,
|
||||
lacunarity,
|
||||
offset,
|
||||
gain,
|
||||
distortion,
|
||||
type,
|
||||
normalize,
|
||||
stack_valid(color_stack_offset),
|
||||
&value,
|
||||
@@ -224,7 +337,10 @@ ccl_device_noinline int svm_node_tex_noise(KernelGlobals kg,
|
||||
detail,
|
||||
roughness,
|
||||
lacunarity,
|
||||
offset,
|
||||
gain,
|
||||
distortion,
|
||||
type,
|
||||
normalize,
|
||||
stack_valid(color_stack_offset),
|
||||
&value,
|
||||
@@ -240,7 +356,7 @@ ccl_device_noinline int svm_node_tex_noise(KernelGlobals kg,
|
||||
if (stack_valid(color_stack_offset)) {
|
||||
stack_store_float3(stack, color_stack_offset, color);
|
||||
}
|
||||
return offset;
|
||||
return node_offset;
|
||||
}
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
|
||||
@@ -178,7 +178,6 @@ CCL_NAMESPACE_END
|
||||
#include "kernel/svm/mapping.h"
|
||||
#include "kernel/svm/math.h"
|
||||
#include "kernel/svm/mix.h"
|
||||
#include "kernel/svm/musgrave.h"
|
||||
#include "kernel/svm/noisetex.h"
|
||||
#include "kernel/svm/normal.h"
|
||||
#include "kernel/svm/ramp.h"
|
||||
@@ -481,9 +480,6 @@ ccl_device void svm_eval_nodes(KernelGlobals kg,
|
||||
offset = svm_node_tex_voronoi<node_feature_mask>(
|
||||
kg, sd, stack, node.y, node.z, node.w, offset);
|
||||
break;
|
||||
SVM_CASE(NODE_TEX_MUSGRAVE)
|
||||
offset = svm_node_tex_musgrave(kg, sd, stack, node.y, node.z, node.w, offset);
|
||||
break;
|
||||
SVM_CASE(NODE_TEX_WAVE)
|
||||
offset = svm_node_tex_wave(kg, sd, stack, node, offset);
|
||||
break;
|
||||
|
||||
@@ -268,13 +268,13 @@ typedef enum NodeConvert {
|
||||
NODE_CONVERT_IV
|
||||
} NodeConvert;
|
||||
|
||||
typedef enum NodeMusgraveType {
|
||||
NODE_MUSGRAVE_MULTIFRACTAL,
|
||||
NODE_MUSGRAVE_FBM,
|
||||
NODE_MUSGRAVE_HYBRID_MULTIFRACTAL,
|
||||
NODE_MUSGRAVE_RIDGED_MULTIFRACTAL,
|
||||
NODE_MUSGRAVE_HETERO_TERRAIN
|
||||
} NodeMusgraveType;
|
||||
typedef enum NodeNoiseType {
|
||||
NODE_NOISE_MULTIFRACTAL,
|
||||
NODE_NOISE_FBM,
|
||||
NODE_NOISE_HYBRID_MULTIFRACTAL,
|
||||
NODE_NOISE_RIDGED_MULTIFRACTAL,
|
||||
NODE_NOISE_HETERO_TERRAIN
|
||||
} NodeNoiseType;
|
||||
|
||||
typedef enum NodeWaveType { NODE_WAVE_BANDS, NODE_WAVE_RINGS } NodeWaveType;
|
||||
|
||||
|
||||
@@ -57,7 +57,7 @@ ccl_device_noinline_cpu float svm_wave(NodeWaveType type,
|
||||
n += phase;
|
||||
|
||||
if (distortion != 0.0f) {
|
||||
n += distortion * (fractal_noise_3d(p * dscale, detail, droughness, 2.0f, true) * 2.0f - 1.0f);
|
||||
n += distortion * (noise_fbm(p * dscale, detail, droughness, 2.0f, true) * 2.0f - 1.0f);
|
||||
}
|
||||
|
||||
if (profile == NODE_WAVE_PROFILE_SIN) {
|
||||
|
||||
@@ -1137,6 +1137,14 @@ NODE_DEFINE(NoiseTextureNode)
|
||||
dimensions_enum.insert("4D", 4);
|
||||
SOCKET_ENUM(dimensions, "Dimensions", dimensions_enum, 3);
|
||||
|
||||
static NodeEnum type_enum;
|
||||
type_enum.insert("multifractal", NODE_NOISE_MULTIFRACTAL);
|
||||
type_enum.insert("fBM", NODE_NOISE_FBM);
|
||||
type_enum.insert("hybrid_multifractal", NODE_NOISE_HYBRID_MULTIFRACTAL);
|
||||
type_enum.insert("ridged_multifractal", NODE_NOISE_RIDGED_MULTIFRACTAL);
|
||||
type_enum.insert("hetero_terrain", NODE_NOISE_HETERO_TERRAIN);
|
||||
SOCKET_ENUM(type, "Type", type_enum, NODE_NOISE_FBM);
|
||||
|
||||
SOCKET_BOOLEAN(use_normalize, "Normalize", true);
|
||||
|
||||
SOCKET_IN_POINT(vector, "Vector", zero_float3(), SocketType::LINK_TEXTURE_GENERATED);
|
||||
@@ -1145,6 +1153,8 @@ NODE_DEFINE(NoiseTextureNode)
|
||||
SOCKET_IN_FLOAT(detail, "Detail", 2.0f);
|
||||
SOCKET_IN_FLOAT(roughness, "Roughness", 0.5f);
|
||||
SOCKET_IN_FLOAT(lacunarity, "Lacunarity", 2.0f);
|
||||
SOCKET_IN_FLOAT(offset, "Offset", 0.0f);
|
||||
SOCKET_IN_FLOAT(gain, "Gain", 1.0f);
|
||||
SOCKET_IN_FLOAT(distortion, "Distortion", 0.0f);
|
||||
|
||||
SOCKET_OUT_FLOAT(fac, "Fac");
|
||||
@@ -1163,6 +1173,8 @@ void NoiseTextureNode::compile(SVMCompiler &compiler)
|
||||
ShaderInput *detail_in = input("Detail");
|
||||
ShaderInput *roughness_in = input("Roughness");
|
||||
ShaderInput *lacunarity_in = input("Lacunarity");
|
||||
ShaderInput *offset_in = input("Offset");
|
||||
ShaderInput *gain_in = input("Gain");
|
||||
ShaderInput *distortion_in = input("Distortion");
|
||||
ShaderOutput *fac_out = output("Fac");
|
||||
ShaderOutput *color_out = output("Color");
|
||||
@@ -1173,6 +1185,8 @@ void NoiseTextureNode::compile(SVMCompiler &compiler)
|
||||
int detail_stack_offset = compiler.stack_assign_if_linked(detail_in);
|
||||
int roughness_stack_offset = compiler.stack_assign_if_linked(roughness_in);
|
||||
int lacunarity_stack_offset = compiler.stack_assign_if_linked(lacunarity_in);
|
||||
int offset_stack_offset = compiler.stack_assign_if_linked(offset_in);
|
||||
int gain_stack_offset = compiler.stack_assign_if_linked(gain_in);
|
||||
int distortion_stack_offset = compiler.stack_assign_if_linked(distortion_in);
|
||||
int fac_stack_offset = compiler.stack_assign_if_linked(fac_out);
|
||||
int color_stack_offset = compiler.stack_assign_if_linked(color_out);
|
||||
@@ -1181,19 +1195,18 @@ void NoiseTextureNode::compile(SVMCompiler &compiler)
|
||||
NODE_TEX_NOISE,
|
||||
compiler.encode_uchar4(
|
||||
vector_stack_offset, w_stack_offset, scale_stack_offset, detail_stack_offset),
|
||||
compiler.encode_uchar4(roughness_stack_offset,
|
||||
lacunarity_stack_offset,
|
||||
distortion_stack_offset,
|
||||
fac_stack_offset),
|
||||
compiler.encode_uchar4(color_stack_offset, dimensions, use_normalize));
|
||||
compiler.encode_uchar4(
|
||||
roughness_stack_offset, lacunarity_stack_offset, offset_stack_offset, gain_stack_offset),
|
||||
compiler.encode_uchar4(distortion_stack_offset, fac_stack_offset, color_stack_offset));
|
||||
|
||||
compiler.add_node(
|
||||
__float_as_int(w), __float_as_int(scale), __float_as_int(detail), __float_as_int(roughness));
|
||||
|
||||
compiler.add_node(__float_as_int(lacunarity),
|
||||
__float_as_int(distortion),
|
||||
SVM_STACK_INVALID,
|
||||
SVM_STACK_INVALID);
|
||||
__float_as_int(offset),
|
||||
__float_as_int(gain),
|
||||
__float_as_int(distortion));
|
||||
compiler.add_node(dimensions, type, use_normalize, SVM_STACK_INVALID);
|
||||
|
||||
tex_mapping.compile_end(compiler, vector_in, vector_stack_offset);
|
||||
}
|
||||
@@ -1202,6 +1215,7 @@ void NoiseTextureNode::compile(OSLCompiler &compiler)
|
||||
{
|
||||
tex_mapping.compile(compiler);
|
||||
compiler.parameter(this, "dimensions");
|
||||
compiler.parameter(this, "type");
|
||||
compiler.parameter(this, "use_normalize");
|
||||
compiler.add(this, "node_noise_texture");
|
||||
}
|
||||
@@ -1461,91 +1475,6 @@ void WhiteNoiseTextureNode::compile(OSLCompiler &compiler)
|
||||
compiler.add(this, "node_white_noise_texture");
|
||||
}
|
||||
|
||||
/* Musgrave Texture */
|
||||
|
||||
NODE_DEFINE(MusgraveTextureNode)
|
||||
{
|
||||
NodeType *type = NodeType::add("musgrave_texture", create, NodeType::SHADER);
|
||||
|
||||
TEXTURE_MAPPING_DEFINE(MusgraveTextureNode);
|
||||
|
||||
static NodeEnum dimensions_enum;
|
||||
dimensions_enum.insert("1D", 1);
|
||||
dimensions_enum.insert("2D", 2);
|
||||
dimensions_enum.insert("3D", 3);
|
||||
dimensions_enum.insert("4D", 4);
|
||||
SOCKET_ENUM(dimensions, "Dimensions", dimensions_enum, 3);
|
||||
|
||||
static NodeEnum type_enum;
|
||||
type_enum.insert("multifractal", NODE_MUSGRAVE_MULTIFRACTAL);
|
||||
type_enum.insert("fBM", NODE_MUSGRAVE_FBM);
|
||||
type_enum.insert("hybrid_multifractal", NODE_MUSGRAVE_HYBRID_MULTIFRACTAL);
|
||||
type_enum.insert("ridged_multifractal", NODE_MUSGRAVE_RIDGED_MULTIFRACTAL);
|
||||
type_enum.insert("hetero_terrain", NODE_MUSGRAVE_HETERO_TERRAIN);
|
||||
SOCKET_ENUM(musgrave_type, "Type", type_enum, NODE_MUSGRAVE_FBM);
|
||||
|
||||
SOCKET_IN_POINT(vector, "Vector", zero_float3(), SocketType::LINK_TEXTURE_GENERATED);
|
||||
SOCKET_IN_FLOAT(w, "W", 0.0f);
|
||||
SOCKET_IN_FLOAT(scale, "Scale", 1.0f);
|
||||
SOCKET_IN_FLOAT(detail, "Detail", 2.0f);
|
||||
SOCKET_IN_FLOAT(dimension, "Dimension", 2.0f);
|
||||
SOCKET_IN_FLOAT(lacunarity, "Lacunarity", 2.0f);
|
||||
SOCKET_IN_FLOAT(offset, "Offset", 0.0f);
|
||||
SOCKET_IN_FLOAT(gain, "Gain", 1.0f);
|
||||
|
||||
SOCKET_OUT_FLOAT(fac, "Fac");
|
||||
|
||||
return type;
|
||||
}
|
||||
|
||||
MusgraveTextureNode::MusgraveTextureNode() : TextureNode(get_node_type()) {}
|
||||
|
||||
void MusgraveTextureNode::compile(SVMCompiler &compiler)
|
||||
{
|
||||
ShaderInput *vector_in = input("Vector");
|
||||
ShaderInput *w_in = input("W");
|
||||
ShaderInput *scale_in = input("Scale");
|
||||
ShaderInput *detail_in = input("Detail");
|
||||
ShaderInput *dimension_in = input("Dimension");
|
||||
ShaderInput *lacunarity_in = input("Lacunarity");
|
||||
ShaderInput *offset_in = input("Offset");
|
||||
ShaderInput *gain_in = input("Gain");
|
||||
ShaderOutput *fac_out = output("Fac");
|
||||
|
||||
int vector_stack_offset = tex_mapping.compile_begin(compiler, vector_in);
|
||||
int w_stack_offset = compiler.stack_assign_if_linked(w_in);
|
||||
int scale_stack_offset = compiler.stack_assign_if_linked(scale_in);
|
||||
int detail_stack_offset = compiler.stack_assign_if_linked(detail_in);
|
||||
int dimension_stack_offset = compiler.stack_assign_if_linked(dimension_in);
|
||||
int lacunarity_stack_offset = compiler.stack_assign_if_linked(lacunarity_in);
|
||||
int offset_stack_offset = compiler.stack_assign_if_linked(offset_in);
|
||||
int gain_stack_offset = compiler.stack_assign_if_linked(gain_in);
|
||||
int fac_stack_offset = compiler.stack_assign(fac_out);
|
||||
|
||||
compiler.add_node(
|
||||
NODE_TEX_MUSGRAVE,
|
||||
compiler.encode_uchar4(musgrave_type, dimensions, vector_stack_offset, w_stack_offset),
|
||||
compiler.encode_uchar4(scale_stack_offset,
|
||||
detail_stack_offset,
|
||||
dimension_stack_offset,
|
||||
lacunarity_stack_offset),
|
||||
compiler.encode_uchar4(offset_stack_offset, gain_stack_offset, fac_stack_offset));
|
||||
compiler.add_node(
|
||||
__float_as_int(w), __float_as_int(scale), __float_as_int(detail), __float_as_int(dimension));
|
||||
compiler.add_node(__float_as_int(lacunarity), __float_as_int(offset), __float_as_int(gain));
|
||||
|
||||
tex_mapping.compile_end(compiler, vector_in, vector_stack_offset);
|
||||
}
|
||||
|
||||
void MusgraveTextureNode::compile(OSLCompiler &compiler)
|
||||
{
|
||||
tex_mapping.compile(compiler);
|
||||
|
||||
compiler.parameter(this, "musgrave_type");
|
||||
compiler.parameter(this, "dimensions");
|
||||
compiler.add(this, "node_musgrave_texture");
|
||||
}
|
||||
|
||||
/* Wave Texture */
|
||||
|
||||
NODE_DEFINE(WaveTextureNode)
|
||||
|
||||
@@ -228,12 +228,15 @@ class NoiseTextureNode : public TextureNode {
|
||||
SHADER_NODE_CLASS(NoiseTextureNode)
|
||||
|
||||
NODE_SOCKET_API(int, dimensions)
|
||||
NODE_SOCKET_API(NodeNoiseType, type)
|
||||
NODE_SOCKET_API(bool, use_normalize)
|
||||
NODE_SOCKET_API(float, w)
|
||||
NODE_SOCKET_API(float, scale)
|
||||
NODE_SOCKET_API(float, detail)
|
||||
NODE_SOCKET_API(float, roughness)
|
||||
NODE_SOCKET_API(float, lacunarity)
|
||||
NODE_SOCKET_API(float, offset)
|
||||
NODE_SOCKET_API(float, gain)
|
||||
NODE_SOCKET_API(float, distortion)
|
||||
NODE_SOCKET_API(float3, vector)
|
||||
};
|
||||
@@ -269,22 +272,6 @@ class VoronoiTextureNode : public TextureNode {
|
||||
NODE_SOCKET_API(float3, vector)
|
||||
};
|
||||
|
||||
class MusgraveTextureNode : public TextureNode {
|
||||
public:
|
||||
SHADER_NODE_CLASS(MusgraveTextureNode)
|
||||
|
||||
NODE_SOCKET_API(int, dimensions)
|
||||
NODE_SOCKET_API(NodeMusgraveType, musgrave_type)
|
||||
NODE_SOCKET_API(float, w)
|
||||
NODE_SOCKET_API(float, scale)
|
||||
NODE_SOCKET_API(float, detail)
|
||||
NODE_SOCKET_API(float, dimension)
|
||||
NODE_SOCKET_API(float, lacunarity)
|
||||
NODE_SOCKET_API(float, offset)
|
||||
NODE_SOCKET_API(float, gain)
|
||||
NODE_SOCKET_API(float3, vector)
|
||||
};
|
||||
|
||||
class WaveTextureNode : public TextureNode {
|
||||
public:
|
||||
SHADER_NODE_CLASS(WaveTextureNode)
|
||||
|
||||
@@ -522,7 +522,6 @@ class NODE_MT_category_GEO_TEXTURE(Menu):
|
||||
node_add_menu.add_node_type(layout, "ShaderNodeTexGradient")
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeImageTexture")
|
||||
node_add_menu.add_node_type(layout, "ShaderNodeTexMagic")
|
||||
node_add_menu.add_node_type(layout, "ShaderNodeTexMusgrave")
|
||||
node_add_menu.add_node_type(layout, "ShaderNodeTexNoise")
|
||||
node_add_menu.add_node_type(layout, "ShaderNodeTexVoronoi")
|
||||
node_add_menu.add_node_type(layout, "ShaderNodeTexWave")
|
||||
|
||||
@@ -292,7 +292,6 @@ class NODE_MT_category_shader_texture(Menu):
|
||||
node_add_menu.add_node_type(layout, "ShaderNodeTexIES")
|
||||
node_add_menu.add_node_type(layout, "ShaderNodeTexImage")
|
||||
node_add_menu.add_node_type(layout, "ShaderNodeTexMagic")
|
||||
node_add_menu.add_node_type(layout, "ShaderNodeTexMusgrave")
|
||||
node_add_menu.add_node_type(layout, "ShaderNodeTexNoise")
|
||||
node_add_menu.add_node_type(layout, "ShaderNodeTexPointDensity")
|
||||
node_add_menu.add_node_type(layout, "ShaderNodeTexSky")
|
||||
|
||||
@@ -906,7 +906,7 @@ void BKE_nodetree_remove_layer_n(struct bNodeTree *ntree, struct Scene *scene, i
|
||||
#define SH_NODE_TEX_MAGIC 148
|
||||
#define SH_NODE_TEX_WAVE 149
|
||||
#define SH_NODE_TEX_NOISE 150
|
||||
#define SH_NODE_TEX_MUSGRAVE 152
|
||||
#define SH_NODE_TEX_MUSGRAVE_DEPRECATED 152
|
||||
#define SH_NODE_TEX_COORD 155
|
||||
#define SH_NODE_ADD_SHADER 156
|
||||
#define SH_NODE_TEX_ENVIRONMENT 157
|
||||
|
||||
@@ -72,268 +72,65 @@ float perlin(float2 position);
|
||||
float perlin(float3 position);
|
||||
float perlin(float4 position);
|
||||
|
||||
/* Fractal perlin noise in the range [0, 1]. */
|
||||
/* Perlin fractal Brownian motion. */
|
||||
|
||||
float perlin_fractal(
|
||||
float position, float octaves, float roughness, float lacunarity, bool normalize);
|
||||
float perlin_fractal(
|
||||
float2 position, float octaves, float roughness, float lacunarity, bool normalize);
|
||||
float perlin_fractal(
|
||||
float3 position, float octaves, float roughness, float lacunarity, bool normalize);
|
||||
float perlin_fractal(
|
||||
float4 position, float octaves, float roughness, float lacunarity, bool normalize);
|
||||
template<typename T>
|
||||
float perlin_fbm(T p, float detail, float roughness, float lacunarity, bool normalize);
|
||||
|
||||
/* Positive distorted fractal perlin noise. */
|
||||
/* Distorted fractal perlin noise. */
|
||||
|
||||
float perlin_fractal_distorted(float position,
|
||||
float octaves,
|
||||
float roughness,
|
||||
float lacunarity,
|
||||
float distortion,
|
||||
bool normalize);
|
||||
float perlin_fractal_distorted(float2 position,
|
||||
float octaves,
|
||||
float roughness,
|
||||
float lacunarity,
|
||||
float distortion,
|
||||
bool normalize);
|
||||
float perlin_fractal_distorted(float3 position,
|
||||
float octaves,
|
||||
float roughness,
|
||||
float lacunarity,
|
||||
float distortion,
|
||||
bool normalize);
|
||||
float perlin_fractal_distorted(float4 position,
|
||||
float octaves,
|
||||
template<typename T>
|
||||
float perlin_fractal_distorted(T position,
|
||||
float detail,
|
||||
float roughness,
|
||||
float lacunarity,
|
||||
float offset,
|
||||
float gain,
|
||||
float distortion,
|
||||
int type,
|
||||
bool normalize);
|
||||
|
||||
/* Positive distorted fractal perlin noise that outputs a float3. */
|
||||
/* Distorted fractal perlin noise that outputs a float3. */
|
||||
|
||||
float3 perlin_float3_fractal_distorted(float position,
|
||||
float octaves,
|
||||
float detail,
|
||||
float roughness,
|
||||
float lacunarity,
|
||||
float offset,
|
||||
float gain,
|
||||
float distortion,
|
||||
int type,
|
||||
bool normalize);
|
||||
float3 perlin_float3_fractal_distorted(float2 position,
|
||||
float octaves,
|
||||
float detail,
|
||||
float roughness,
|
||||
float lacunarity,
|
||||
float offset,
|
||||
float gain,
|
||||
float distortion,
|
||||
int type,
|
||||
bool normalize);
|
||||
float3 perlin_float3_fractal_distorted(float3 position,
|
||||
float octaves,
|
||||
float detail,
|
||||
float roughness,
|
||||
float lacunarity,
|
||||
float offset,
|
||||
float gain,
|
||||
float distortion,
|
||||
int type,
|
||||
bool normalize);
|
||||
float3 perlin_float3_fractal_distorted(float4 position,
|
||||
float octaves,
|
||||
float detail,
|
||||
float roughness,
|
||||
float lacunarity,
|
||||
float offset,
|
||||
float gain,
|
||||
float distortion,
|
||||
int type,
|
||||
bool normalize);
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Musgrave Multi Fractal
|
||||
* \{ */
|
||||
|
||||
/**
|
||||
* 1D Ridged Multi-fractal Terrain
|
||||
*
|
||||
* \param H: fractal dimension of the roughest area.
|
||||
* \param lacunarity: gap between successive frequencies.
|
||||
* \param octaves: number of frequencies in the fBm.
|
||||
* \param offset: raises the terrain from `sea level'.
|
||||
*/
|
||||
float musgrave_ridged_multi_fractal(
|
||||
float co, float H, float lacunarity, float octaves, float offset, float gain);
|
||||
/**
|
||||
* 2D Ridged Multi-fractal Terrain
|
||||
*
|
||||
* \param H: fractal dimension of the roughest area.
|
||||
* \param lacunarity: gap between successive frequencies.
|
||||
* \param octaves: number of frequencies in the fBm.
|
||||
* \param offset: raises the terrain from `sea level'.
|
||||
*/
|
||||
float musgrave_ridged_multi_fractal(
|
||||
const float2 co, float H, float lacunarity, float octaves, float offset, float gain);
|
||||
/**
|
||||
* 3D Ridged Multi-fractal Terrain
|
||||
*
|
||||
* \param H: fractal dimension of the roughest area.
|
||||
* \param lacunarity: gap between successive frequencies.
|
||||
* \param octaves: number of frequencies in the fBm.
|
||||
* \param offset: raises the terrain from `sea level'.
|
||||
*/
|
||||
float musgrave_ridged_multi_fractal(
|
||||
const float3 co, float H, float lacunarity, float octaves, float offset, float gain);
|
||||
/**
|
||||
* 4D Ridged Multi-fractal Terrain
|
||||
*
|
||||
* \param H: fractal dimension of the roughest area.
|
||||
* \param lacunarity: gap between successive frequencies.
|
||||
* \param octaves: number of frequencies in the fBm.
|
||||
* \param offset: raises the terrain from `sea level'.
|
||||
*/
|
||||
float musgrave_ridged_multi_fractal(
|
||||
const float4 co, float H, float lacunarity, float octaves, float offset, float gain);
|
||||
|
||||
/**
|
||||
* 1D Hybrid Additive/Multiplicative Multi-fractal Terrain
|
||||
*
|
||||
* \param H: fractal dimension of the roughest area.
|
||||
* \param lacunarity: gap between successive frequencies.
|
||||
* \param octaves: number of frequencies in the fBm.
|
||||
* \param offset: raises the terrain from `sea level'.
|
||||
*/
|
||||
float musgrave_hybrid_multi_fractal(
|
||||
float co, float H, float lacunarity, float octaves, float offset, float gain);
|
||||
/**
|
||||
* 2D Hybrid Additive/Multiplicative Multi-fractal Terrain
|
||||
*
|
||||
* \param H: fractal dimension of the roughest area.
|
||||
* \param lacunarity: gap between successive frequencies.
|
||||
* \param octaves: number of frequencies in the fBm.
|
||||
* \param offset: raises the terrain from `sea level'.
|
||||
*/
|
||||
float musgrave_hybrid_multi_fractal(
|
||||
const float2 co, float H, float lacunarity, float octaves, float offset, float gain);
|
||||
/**
|
||||
* 3D Hybrid Additive/Multiplicative Multi-fractal Terrain
|
||||
*
|
||||
* \param H: fractal dimension of the roughest area.
|
||||
* \param lacunarity: gap between successive frequencies.
|
||||
* \param octaves: number of frequencies in the fBm.
|
||||
* \param offset: raises the terrain from `sea level'.
|
||||
*/
|
||||
float musgrave_hybrid_multi_fractal(
|
||||
const float3 co, float H, float lacunarity, float octaves, float offset, float gain);
|
||||
/**
|
||||
* 4D Hybrid Additive/Multiplicative Multi-fractal Terrain
|
||||
*
|
||||
* \param H: fractal dimension of the roughest area.
|
||||
* \param lacunarity: gap between successive frequencies.
|
||||
* \param octaves: number of frequencies in the fBm.
|
||||
* \param offset: raises the terrain from `sea level'.
|
||||
*/
|
||||
float musgrave_hybrid_multi_fractal(
|
||||
const float4 co, float H, float lacunarity, float octaves, float offset, float gain);
|
||||
|
||||
/**
|
||||
* 1D Musgrave fBm
|
||||
*
|
||||
* \param H: fractal increment parameter.
|
||||
* \param lacunarity: gap between successive frequencies.
|
||||
* \param octaves: number of frequencies in the fBm.
|
||||
*/
|
||||
float musgrave_fBm(float co, float H, float lacunarity, float octaves);
|
||||
|
||||
/**
|
||||
* 2D Musgrave fBm
|
||||
*
|
||||
* \param H: fractal increment parameter.
|
||||
* \param lacunarity: gap between successive frequencies.
|
||||
* \param octaves: number of frequencies in the fBm.
|
||||
*/
|
||||
float musgrave_fBm(const float2 co, float H, float lacunarity, float octaves);
|
||||
/**
|
||||
* 3D Musgrave fBm
|
||||
*
|
||||
* \param H: fractal increment parameter.
|
||||
* \param lacunarity: gap between successive frequencies.
|
||||
* \param octaves: number of frequencies in the fBm.
|
||||
*/
|
||||
float musgrave_fBm(const float3 co, float H, float lacunarity, float octaves);
|
||||
/**
|
||||
* 4D Musgrave fBm
|
||||
*
|
||||
* \param H: fractal increment parameter.
|
||||
* \param lacunarity: gap between successive frequencies.
|
||||
* \param octaves: number of frequencies in the fBm.
|
||||
*/
|
||||
float musgrave_fBm(const float4 co, float H, float lacunarity, float octaves);
|
||||
|
||||
/**
|
||||
* 1D Musgrave Multi-fractal
|
||||
*
|
||||
* \param H: highest fractal dimension.
|
||||
* \param lacunarity: gap between successive frequencies.
|
||||
* \param octaves: number of frequencies in the fBm.
|
||||
*/
|
||||
float musgrave_multi_fractal(float co, float H, float lacunarity, float octaves);
|
||||
/**
|
||||
* 2D Musgrave Multi-fractal
|
||||
*
|
||||
* \param H: highest fractal dimension.
|
||||
* \param lacunarity: gap between successive frequencies.
|
||||
* \param octaves: number of frequencies in the fBm.
|
||||
*/
|
||||
float musgrave_multi_fractal(const float2 co, float H, float lacunarity, float octaves);
|
||||
/**
|
||||
* 3D Musgrave Multi-fractal
|
||||
*
|
||||
* \param H: highest fractal dimension.
|
||||
* \param lacunarity: gap between successive frequencies.
|
||||
* \param octaves: number of frequencies in the fBm.
|
||||
*/
|
||||
float musgrave_multi_fractal(const float3 co, float H, float lacunarity, float octaves);
|
||||
/**
|
||||
* 4D Musgrave Multi-fractal
|
||||
*
|
||||
* \param H: highest fractal dimension.
|
||||
* \param lacunarity: gap between successive frequencies.
|
||||
* \param octaves: number of frequencies in the fBm.
|
||||
*/
|
||||
float musgrave_multi_fractal(const float4 co, float H, float lacunarity, float octaves);
|
||||
|
||||
/**
|
||||
* 1D Musgrave Heterogeneous Terrain
|
||||
*
|
||||
* \param H: fractal dimension of the roughest area.
|
||||
* \param lacunarity: gap between successive frequencies.
|
||||
* \param octaves: number of frequencies in the fBm.
|
||||
* \param offset: raises the terrain from `sea level'.
|
||||
*/
|
||||
float musgrave_hetero_terrain(float co, float H, float lacunarity, float octaves, float offset);
|
||||
/**
|
||||
* 2D Musgrave Heterogeneous Terrain
|
||||
*
|
||||
* \param H: fractal dimension of the roughest area.
|
||||
* \param lacunarity: gap between successive frequencies.
|
||||
* \param octaves: number of frequencies in the fBm.
|
||||
* \param offset: raises the terrain from `sea level'.
|
||||
*/
|
||||
float musgrave_hetero_terrain(
|
||||
const float2 co, float H, float lacunarity, float octaves, float offset);
|
||||
/**
|
||||
* 3D Musgrave Heterogeneous Terrain
|
||||
*
|
||||
* \param H: fractal dimension of the roughest area.
|
||||
* \param lacunarity: gap between successive frequencies.
|
||||
* \param octaves: number of frequencies in the fBm.
|
||||
* \param offset: raises the terrain from `sea level'.
|
||||
*/
|
||||
float musgrave_hetero_terrain(
|
||||
const float3 co, float H, float lacunarity, float octaves, float offset);
|
||||
/**
|
||||
* 4D Musgrave Heterogeneous Terrain
|
||||
*
|
||||
* \param H: fractal dimension of the roughest area.
|
||||
* \param lacunarity: gap between successive frequencies.
|
||||
* \param octaves: number of frequencies in the fBm.
|
||||
* \param offset: raises the terrain from `sea level'.
|
||||
*/
|
||||
float musgrave_hetero_terrain(
|
||||
const float4 co, float H, float lacunarity, float octaves, float offset);
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Voronoi Noise
|
||||
* \{ */
|
||||
|
||||
@@ -530,28 +530,28 @@ float perlin(float4 position)
|
||||
return perlin_signed(position) / 2.0f + 0.5f;
|
||||
}
|
||||
|
||||
/* Positive fractal perlin noise. */
|
||||
/* Fractal perlin noise. */
|
||||
|
||||
/* fBM = Fractal Brownian Motion */
|
||||
template<typename T>
|
||||
float perlin_fractal_template(
|
||||
T position, float octaves, float roughness, float lacunarity, bool normalize)
|
||||
float perlin_fbm(
|
||||
T p, const float detail, const float roughness, const float lacunarity, const bool normalize)
|
||||
{
|
||||
float fscale = 1.0f;
|
||||
float amp = 1.0f;
|
||||
float maxamp = 0.0f;
|
||||
float sum = 0.0f;
|
||||
octaves = CLAMPIS(octaves, 0.0f, 15.0f);
|
||||
int n = int(octaves);
|
||||
for (int i = 0; i <= n; i++) {
|
||||
float t = perlin_signed(fscale * position);
|
||||
|
||||
for (int i = 0; i <= int(detail); i++) {
|
||||
float t = perlin_signed(fscale * p);
|
||||
sum += t * amp;
|
||||
maxamp += amp;
|
||||
amp *= CLAMPIS(roughness, 0.0f, 1.0f);
|
||||
amp *= roughness;
|
||||
fscale *= lacunarity;
|
||||
}
|
||||
float rmd = octaves - std::floor(octaves);
|
||||
float rmd = detail - std::floor(detail);
|
||||
if (rmd != 0.0f) {
|
||||
float t = perlin_signed(fscale * position);
|
||||
float t = perlin_signed(fscale * p);
|
||||
float sum2 = sum + t * amp;
|
||||
return normalize ? mix(0.5f * sum / maxamp + 0.5f, 0.5f * sum2 / (maxamp + amp) + 0.5f, rmd) :
|
||||
mix(sum, sum2, rmd);
|
||||
@@ -561,28 +561,161 @@ float perlin_fractal_template(
|
||||
}
|
||||
}
|
||||
|
||||
float perlin_fractal(
|
||||
float position, float octaves, float roughness, float lacunarity, bool normalize)
|
||||
/* Explicit instantiation for Wave Texture. */
|
||||
template float perlin_fbm<float3>(float3 p,
|
||||
const float detail,
|
||||
const float roughness,
|
||||
const float lacunarity,
|
||||
const bool normalize);
|
||||
|
||||
template<typename T>
|
||||
float perlin_multi_fractal(T p, const float detail, const float roughness, const float lacunarity)
|
||||
{
|
||||
return perlin_fractal_template(position, octaves, roughness, lacunarity, normalize);
|
||||
float value = 1.0f;
|
||||
float pwr = 1.0f;
|
||||
|
||||
for (int i = 0; i <= int(detail); i++) {
|
||||
value *= (pwr * perlin_signed(p) + 1.0f);
|
||||
pwr *= roughness;
|
||||
p *= lacunarity;
|
||||
}
|
||||
|
||||
const float rmd = detail - floorf(detail);
|
||||
if (rmd != 0.0f) {
|
||||
value *= (rmd * pwr * perlin_signed(p) + 1.0f); /* correct? */
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
float perlin_fractal(
|
||||
float2 position, float octaves, float roughness, float lacunarity, bool normalize)
|
||||
template<typename T>
|
||||
float perlin_hetero_terrain(
|
||||
T p, const float detail, const float roughness, const float lacunarity, const float offset)
|
||||
{
|
||||
return perlin_fractal_template(position, octaves, roughness, lacunarity, normalize);
|
||||
float pwr = roughness;
|
||||
|
||||
/* First unscaled octave of function; later octaves are scaled. */
|
||||
float value = offset + perlin_signed(p);
|
||||
p *= lacunarity;
|
||||
|
||||
for (int i = 1; i <= int(detail); i++) {
|
||||
float increment = (perlin_signed(p) + offset) * pwr * value;
|
||||
value += increment;
|
||||
pwr *= roughness;
|
||||
p *= lacunarity;
|
||||
}
|
||||
|
||||
const float rmd = detail - floorf(detail);
|
||||
if (rmd != 0.0f) {
|
||||
float increment = (perlin_signed(p) + offset) * pwr * value;
|
||||
value += rmd * increment;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
float perlin_fractal(
|
||||
float3 position, float octaves, float roughness, float lacunarity, bool normalize)
|
||||
template<typename T>
|
||||
float perlin_hybrid_multi_fractal(T p,
|
||||
const float detail,
|
||||
const float roughness,
|
||||
const float lacunarity,
|
||||
const float offset,
|
||||
const float gain)
|
||||
{
|
||||
return perlin_fractal_template(position, octaves, roughness, lacunarity, normalize);
|
||||
float pwr = 1.0f;
|
||||
float value = 0.0f;
|
||||
float weight = 1.0f;
|
||||
|
||||
for (int i = 0; (weight > 0.001f) && (i <= int(detail)); i++) {
|
||||
if (weight > 1.0f) {
|
||||
weight = 1.0f;
|
||||
}
|
||||
|
||||
float signal = (perlin_signed(p) + offset) * pwr;
|
||||
pwr *= roughness;
|
||||
value += weight * signal;
|
||||
weight *= gain * signal;
|
||||
p *= lacunarity;
|
||||
}
|
||||
|
||||
const float rmd = detail - floorf(detail);
|
||||
if ((rmd != 0.0f) && (weight > 0.001f)) {
|
||||
if (weight > 1.0f) {
|
||||
weight = 1.0f;
|
||||
}
|
||||
float signal = (perlin_signed(p) + offset) * pwr;
|
||||
value += rmd * weight * signal;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
float perlin_fractal(
|
||||
float4 position, float octaves, float roughness, float lacunarity, bool normalize)
|
||||
template<typename T>
|
||||
float perlin_ridged_multi_fractal(T p,
|
||||
const float detail,
|
||||
const float roughness,
|
||||
const float lacunarity,
|
||||
const float offset,
|
||||
const float gain)
|
||||
{
|
||||
return perlin_fractal_template(position, octaves, roughness, lacunarity, normalize);
|
||||
float pwr = roughness;
|
||||
|
||||
float signal = offset - std::abs(perlin_signed(p));
|
||||
signal *= signal;
|
||||
float value = signal;
|
||||
float weight = 1.0f;
|
||||
|
||||
for (int i = 1; i <= int(detail); i++) {
|
||||
p *= lacunarity;
|
||||
weight = CLAMPIS(signal * gain, 0.0f, 1.0f);
|
||||
signal = offset - std::abs(perlin_signed(p));
|
||||
signal *= signal;
|
||||
signal *= weight;
|
||||
value += signal * pwr;
|
||||
pwr *= roughness;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
enum {
|
||||
NOISE_SHD_PERLIN_MULTIFRACTAL = 0,
|
||||
NOISE_SHD_PERLIN_FBM = 1,
|
||||
NOISE_SHD_PERLIN_HYBRID_MULTIFRACTAL = 2,
|
||||
NOISE_SHD_PERLIN_RIDGED_MULTIFRACTAL = 3,
|
||||
NOISE_SHD_PERLIN_HETERO_TERRAIN = 4,
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
float perlin_select(T p,
|
||||
float detail,
|
||||
float roughness,
|
||||
float lacunarity,
|
||||
float offset,
|
||||
float gain,
|
||||
int type,
|
||||
bool normalize)
|
||||
{
|
||||
switch (type) {
|
||||
case NOISE_SHD_PERLIN_MULTIFRACTAL: {
|
||||
return perlin_multi_fractal<T>(p, detail, roughness, lacunarity);
|
||||
}
|
||||
case NOISE_SHD_PERLIN_FBM: {
|
||||
return perlin_fbm<T>(p, detail, roughness, lacunarity, normalize);
|
||||
}
|
||||
case NOISE_SHD_PERLIN_HYBRID_MULTIFRACTAL: {
|
||||
return perlin_hybrid_multi_fractal<T>(p, detail, roughness, lacunarity, offset, gain);
|
||||
}
|
||||
case NOISE_SHD_PERLIN_RIDGED_MULTIFRACTAL: {
|
||||
return perlin_ridged_multi_fractal<T>(p, detail, roughness, lacunarity, offset, gain);
|
||||
}
|
||||
case NOISE_SHD_PERLIN_HETERO_TERRAIN: {
|
||||
return perlin_hetero_terrain<T>(p, detail, roughness, lacunarity, offset);
|
||||
}
|
||||
default: {
|
||||
return 0.0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* The following offset functions generate random offsets to be added to
|
||||
@@ -646,746 +779,185 @@ BLI_INLINE float4 perlin_distortion(float4 position, float strength)
|
||||
perlin_signed(position + random_float4_offset(3.0f)) * strength);
|
||||
}
|
||||
|
||||
/* Positive distorted fractal perlin noise. */
|
||||
/* Distorted fractal perlin noise. */
|
||||
|
||||
float perlin_fractal_distorted(float position,
|
||||
float octaves,
|
||||
template<typename T>
|
||||
float perlin_fractal_distorted(T position,
|
||||
float detail,
|
||||
float roughness,
|
||||
float lacunarity,
|
||||
float offset,
|
||||
float gain,
|
||||
float distortion,
|
||||
int type,
|
||||
bool normalize)
|
||||
{
|
||||
position += perlin_distortion(position, distortion);
|
||||
return perlin_fractal(position, octaves, roughness, lacunarity, normalize);
|
||||
return perlin_select<T>(position, detail, roughness, lacunarity, offset, gain, type, normalize);
|
||||
}
|
||||
|
||||
float perlin_fractal_distorted(float2 position,
|
||||
float octaves,
|
||||
float roughness,
|
||||
float lacunarity,
|
||||
float distortion,
|
||||
bool normalize)
|
||||
{
|
||||
position += perlin_distortion(position, distortion);
|
||||
return perlin_fractal(position, octaves, roughness, lacunarity, normalize);
|
||||
}
|
||||
template float perlin_fractal_distorted<float>(float position,
|
||||
float detail,
|
||||
float roughness,
|
||||
float lacunarity,
|
||||
float offset,
|
||||
float gain,
|
||||
float distortion,
|
||||
int type,
|
||||
bool normalize);
|
||||
template float perlin_fractal_distorted<float2>(float2 position,
|
||||
float detail,
|
||||
float roughness,
|
||||
float lacunarity,
|
||||
float offset,
|
||||
float gain,
|
||||
float distortion,
|
||||
int type,
|
||||
bool normalize);
|
||||
template float perlin_fractal_distorted<float3>(float3 position,
|
||||
float detail,
|
||||
float roughness,
|
||||
float lacunarity,
|
||||
float offset,
|
||||
float gain,
|
||||
float distortion,
|
||||
int type,
|
||||
bool normalize);
|
||||
template float perlin_fractal_distorted<float4>(float4 position,
|
||||
float detail,
|
||||
float roughness,
|
||||
float lacunarity,
|
||||
float offset,
|
||||
float gain,
|
||||
float distortion,
|
||||
int type,
|
||||
bool normalize);
|
||||
|
||||
float perlin_fractal_distorted(float3 position,
|
||||
float octaves,
|
||||
float roughness,
|
||||
float lacunarity,
|
||||
float distortion,
|
||||
bool normalize)
|
||||
{
|
||||
position += perlin_distortion(position, distortion);
|
||||
return perlin_fractal(position, octaves, roughness, lacunarity, normalize);
|
||||
}
|
||||
|
||||
float perlin_fractal_distorted(float4 position,
|
||||
float octaves,
|
||||
float roughness,
|
||||
float lacunarity,
|
||||
float distortion,
|
||||
bool normalize)
|
||||
{
|
||||
position += perlin_distortion(position, distortion);
|
||||
return perlin_fractal(position, octaves, roughness, lacunarity, normalize);
|
||||
}
|
||||
|
||||
/* Positive distorted fractal perlin noise that outputs a float3. The arbitrary seeds are for
|
||||
/* Distorted fractal perlin noise that outputs a float3. The arbitrary seeds are for
|
||||
* compatibility with shading functions. */
|
||||
|
||||
float3 perlin_float3_fractal_distorted(float position,
|
||||
float octaves,
|
||||
float detail,
|
||||
float roughness,
|
||||
float lacunarity,
|
||||
float offset,
|
||||
float gain,
|
||||
float distortion,
|
||||
int type,
|
||||
bool normalize)
|
||||
{
|
||||
position += perlin_distortion(position, distortion);
|
||||
return float3(
|
||||
perlin_fractal(position, octaves, roughness, lacunarity, normalize),
|
||||
perlin_fractal(
|
||||
position + random_float_offset(1.0f), octaves, roughness, lacunarity, normalize),
|
||||
perlin_fractal(
|
||||
position + random_float_offset(2.0f), octaves, roughness, lacunarity, normalize));
|
||||
perlin_select<float>(position, detail, roughness, lacunarity, offset, gain, type, normalize),
|
||||
perlin_select<float>(position + random_float_offset(1.0f),
|
||||
detail,
|
||||
roughness,
|
||||
lacunarity,
|
||||
offset,
|
||||
gain,
|
||||
type,
|
||||
normalize),
|
||||
perlin_select<float>(position + random_float_offset(2.0f),
|
||||
detail,
|
||||
roughness,
|
||||
lacunarity,
|
||||
offset,
|
||||
gain,
|
||||
type,
|
||||
normalize));
|
||||
}
|
||||
|
||||
float3 perlin_float3_fractal_distorted(float2 position,
|
||||
float octaves,
|
||||
float detail,
|
||||
float roughness,
|
||||
float lacunarity,
|
||||
float offset,
|
||||
float gain,
|
||||
float distortion,
|
||||
int type,
|
||||
bool normalize)
|
||||
{
|
||||
position += perlin_distortion(position, distortion);
|
||||
return float3(
|
||||
perlin_fractal(position, octaves, roughness, lacunarity, normalize),
|
||||
perlin_fractal(
|
||||
position + random_float2_offset(2.0f), octaves, roughness, lacunarity, normalize),
|
||||
perlin_fractal(
|
||||
position + random_float2_offset(3.0f), octaves, roughness, lacunarity, normalize));
|
||||
return float3(perlin_select<float2>(
|
||||
position, detail, roughness, lacunarity, offset, gain, type, normalize),
|
||||
perlin_select<float2>(position + random_float2_offset(2.0f),
|
||||
detail,
|
||||
roughness,
|
||||
lacunarity,
|
||||
offset,
|
||||
gain,
|
||||
type,
|
||||
normalize),
|
||||
perlin_select<float2>(position + random_float2_offset(3.0f),
|
||||
detail,
|
||||
roughness,
|
||||
lacunarity,
|
||||
offset,
|
||||
gain,
|
||||
type,
|
||||
normalize));
|
||||
}
|
||||
|
||||
float3 perlin_float3_fractal_distorted(float3 position,
|
||||
float octaves,
|
||||
float detail,
|
||||
float roughness,
|
||||
float lacunarity,
|
||||
float offset,
|
||||
float gain,
|
||||
float distortion,
|
||||
int type,
|
||||
bool normalize)
|
||||
{
|
||||
position += perlin_distortion(position, distortion);
|
||||
return float3(
|
||||
perlin_fractal(position, octaves, roughness, lacunarity, normalize),
|
||||
perlin_fractal(
|
||||
position + random_float3_offset(3.0f), octaves, roughness, lacunarity, normalize),
|
||||
perlin_fractal(
|
||||
position + random_float3_offset(4.0f), octaves, roughness, lacunarity, normalize));
|
||||
return float3(perlin_select<float3>(
|
||||
position, detail, roughness, lacunarity, offset, gain, type, normalize),
|
||||
perlin_select<float3>(position + random_float3_offset(3.0f),
|
||||
detail,
|
||||
roughness,
|
||||
lacunarity,
|
||||
offset,
|
||||
gain,
|
||||
type,
|
||||
normalize),
|
||||
perlin_select<float3>(position + random_float3_offset(4.0f),
|
||||
detail,
|
||||
roughness,
|
||||
lacunarity,
|
||||
offset,
|
||||
gain,
|
||||
type,
|
||||
normalize));
|
||||
}
|
||||
|
||||
float3 perlin_float3_fractal_distorted(float4 position,
|
||||
float octaves,
|
||||
float detail,
|
||||
float roughness,
|
||||
float lacunarity,
|
||||
float offset,
|
||||
float gain,
|
||||
float distortion,
|
||||
int type,
|
||||
bool normalize)
|
||||
{
|
||||
position += perlin_distortion(position, distortion);
|
||||
return float3(
|
||||
perlin_fractal(position, octaves, roughness, lacunarity, normalize),
|
||||
perlin_fractal(
|
||||
position + random_float4_offset(4.0f), octaves, roughness, lacunarity, normalize),
|
||||
perlin_fractal(
|
||||
position + random_float4_offset(5.0f), octaves, roughness, lacunarity, normalize));
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Musgrave Noise
|
||||
* \{ */
|
||||
|
||||
float musgrave_fBm(const float co,
|
||||
const float H,
|
||||
const float lacunarity,
|
||||
const float octaves_unclamped)
|
||||
{
|
||||
/* From "Texturing and Modelling: A procedural approach". */
|
||||
|
||||
float p = co;
|
||||
float value = 0.0f;
|
||||
float pwr = 1.0f;
|
||||
const float pwHL = std::pow(lacunarity, -H);
|
||||
const float octaves = CLAMPIS(octaves_unclamped, 0.0f, 15.0f);
|
||||
|
||||
for (int i = 0; i < int(octaves); i++) {
|
||||
value += perlin_signed(p) * pwr;
|
||||
pwr *= pwHL;
|
||||
p *= lacunarity;
|
||||
}
|
||||
|
||||
float rmd = octaves - floorf(octaves);
|
||||
if (rmd != 0.0f) {
|
||||
value += rmd * perlin_signed(p) * pwr;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
float musgrave_multi_fractal(const float co,
|
||||
const float H,
|
||||
const float lacunarity,
|
||||
const float octaves_unclamped)
|
||||
{
|
||||
float p = co;
|
||||
float value = 1.0f;
|
||||
float pwr = 1.0f;
|
||||
const float pwHL = std::pow(lacunarity, -H);
|
||||
const float octaves = CLAMPIS(octaves_unclamped, 0.0f, 15.0f);
|
||||
|
||||
for (int i = 0; i < int(octaves); i++) {
|
||||
value *= (pwr * perlin_signed(p) + 1.0f);
|
||||
pwr *= pwHL;
|
||||
p *= lacunarity;
|
||||
}
|
||||
|
||||
const float rmd = octaves - floorf(octaves);
|
||||
if (rmd != 0.0f) {
|
||||
value *= (rmd * pwr * perlin_signed(p) + 1.0f); /* correct? */
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
float musgrave_hetero_terrain(const float co,
|
||||
const float H,
|
||||
const float lacunarity,
|
||||
const float octaves_unclamped,
|
||||
const float offset)
|
||||
{
|
||||
float p = co;
|
||||
const float pwHL = std::pow(lacunarity, -H);
|
||||
float pwr = pwHL;
|
||||
const float octaves = CLAMPIS(octaves_unclamped, 0.0f, 15.0f);
|
||||
|
||||
/* First unscaled octave of function; later octaves are scaled. */
|
||||
float value = offset + perlin_signed(p);
|
||||
p *= lacunarity;
|
||||
|
||||
for (int i = 1; i < int(octaves); i++) {
|
||||
float increment = (perlin_signed(p) + offset) * pwr * value;
|
||||
value += increment;
|
||||
pwr *= pwHL;
|
||||
p *= lacunarity;
|
||||
}
|
||||
|
||||
const float rmd = octaves - floorf(octaves);
|
||||
if (rmd != 0.0f) {
|
||||
float increment = (perlin_signed(p) + offset) * pwr * value;
|
||||
value += rmd * increment;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
float musgrave_hybrid_multi_fractal(const float co,
|
||||
const float H,
|
||||
const float lacunarity,
|
||||
const float octaves_unclamped,
|
||||
const float offset,
|
||||
const float gain)
|
||||
{
|
||||
float p = co;
|
||||
const float pwHL = std::pow(lacunarity, -H);
|
||||
|
||||
float pwr = 1.0f;
|
||||
float value = 0.0f;
|
||||
float weight = 1.0f;
|
||||
|
||||
const float octaves = CLAMPIS(octaves_unclamped, 0.0f, 15.0f);
|
||||
|
||||
for (int i = 0; (weight > 0.001f) && (i < int(octaves)); i++) {
|
||||
if (weight > 1.0f) {
|
||||
weight = 1.0f;
|
||||
}
|
||||
|
||||
float signal = (perlin_signed(p) + offset) * pwr;
|
||||
pwr *= pwHL;
|
||||
value += weight * signal;
|
||||
weight *= gain * signal;
|
||||
p *= lacunarity;
|
||||
}
|
||||
|
||||
const float rmd = octaves - floorf(octaves);
|
||||
if ((rmd != 0.0f) && (weight > 0.001f)) {
|
||||
if (weight > 1.0f) {
|
||||
weight = 1.0f;
|
||||
}
|
||||
float signal = (perlin_signed(p) + offset) * pwr;
|
||||
value += rmd * weight * signal;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
float musgrave_ridged_multi_fractal(const float co,
|
||||
const float H,
|
||||
const float lacunarity,
|
||||
const float octaves_unclamped,
|
||||
const float offset,
|
||||
const float gain)
|
||||
{
|
||||
float p = co;
|
||||
const float pwHL = std::pow(lacunarity, -H);
|
||||
float pwr = pwHL;
|
||||
|
||||
float signal = offset - std::abs(perlin_signed(p));
|
||||
signal *= signal;
|
||||
float value = signal;
|
||||
float weight = 1.0f;
|
||||
|
||||
const float octaves = CLAMPIS(octaves_unclamped, 0.0f, 15.0f);
|
||||
|
||||
for (int i = 1; i < int(octaves); i++) {
|
||||
p *= lacunarity;
|
||||
weight = CLAMPIS(signal * gain, 0.0f, 1.0f);
|
||||
signal = offset - std::abs(perlin_signed(p));
|
||||
signal *= signal;
|
||||
signal *= weight;
|
||||
value += signal * pwr;
|
||||
pwr *= pwHL;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
float musgrave_fBm(const float2 co,
|
||||
const float H,
|
||||
const float lacunarity,
|
||||
const float octaves_unclamped)
|
||||
{
|
||||
/* From "Texturing and Modelling: A procedural approach". */
|
||||
|
||||
float2 p = co;
|
||||
float value = 0.0f;
|
||||
float pwr = 1.0f;
|
||||
const float pwHL = std::pow(lacunarity, -H);
|
||||
const float octaves = CLAMPIS(octaves_unclamped, 0.0f, 15.0f);
|
||||
|
||||
for (int i = 0; i < int(octaves); i++) {
|
||||
value += perlin_signed(p) * pwr;
|
||||
pwr *= pwHL;
|
||||
p *= lacunarity;
|
||||
}
|
||||
|
||||
const float rmd = octaves - floorf(octaves);
|
||||
if (rmd != 0.0f) {
|
||||
value += rmd * perlin_signed(p) * pwr;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
float musgrave_multi_fractal(const float2 co,
|
||||
const float H,
|
||||
const float lacunarity,
|
||||
const float octaves_unclamped)
|
||||
{
|
||||
float2 p = co;
|
||||
float value = 1.0f;
|
||||
float pwr = 1.0f;
|
||||
const float pwHL = std::pow(lacunarity, -H);
|
||||
const float octaves = CLAMPIS(octaves_unclamped, 0.0f, 15.0f);
|
||||
|
||||
for (int i = 0; i < int(octaves); i++) {
|
||||
value *= (pwr * perlin_signed(p) + 1.0f);
|
||||
pwr *= pwHL;
|
||||
p *= lacunarity;
|
||||
}
|
||||
|
||||
const float rmd = octaves - floorf(octaves);
|
||||
if (rmd != 0.0f) {
|
||||
value *= (rmd * pwr * perlin_signed(p) + 1.0f); /* correct? */
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
float musgrave_hetero_terrain(const float2 co,
|
||||
const float H,
|
||||
const float lacunarity,
|
||||
const float octaves_unclamped,
|
||||
const float offset)
|
||||
{
|
||||
float2 p = co;
|
||||
const float pwHL = std::pow(lacunarity, -H);
|
||||
float pwr = pwHL;
|
||||
|
||||
/* First unscaled octave of function; later octaves are scaled. */
|
||||
float value = offset + perlin_signed(p);
|
||||
p *= lacunarity;
|
||||
|
||||
const float octaves = CLAMPIS(octaves_unclamped, 0.0f, 15.0f);
|
||||
|
||||
for (int i = 1; i < int(octaves); i++) {
|
||||
float increment = (perlin_signed(p) + offset) * pwr * value;
|
||||
value += increment;
|
||||
pwr *= pwHL;
|
||||
p *= lacunarity;
|
||||
}
|
||||
|
||||
const float rmd = octaves - floorf(octaves);
|
||||
if (rmd != 0.0f) {
|
||||
float increment = (perlin_signed(p) + offset) * pwr * value;
|
||||
value += rmd * increment;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
float musgrave_hybrid_multi_fractal(const float2 co,
|
||||
const float H,
|
||||
const float lacunarity,
|
||||
const float octaves_unclamped,
|
||||
const float offset,
|
||||
const float gain)
|
||||
{
|
||||
float2 p = co;
|
||||
const float pwHL = std::pow(lacunarity, -H);
|
||||
|
||||
float pwr = 1.0f;
|
||||
float value = 0.0f;
|
||||
float weight = 1.0f;
|
||||
|
||||
const float octaves = CLAMPIS(octaves_unclamped, 0.0f, 15.0f);
|
||||
|
||||
for (int i = 0; (weight > 0.001f) && (i < int(octaves)); i++) {
|
||||
if (weight > 1.0f) {
|
||||
weight = 1.0f;
|
||||
}
|
||||
|
||||
float signal = (perlin_signed(p) + offset) * pwr;
|
||||
pwr *= pwHL;
|
||||
value += weight * signal;
|
||||
weight *= gain * signal;
|
||||
p *= lacunarity;
|
||||
}
|
||||
|
||||
const float rmd = octaves - floorf(octaves);
|
||||
if ((rmd != 0.0f) && (weight > 0.001f)) {
|
||||
if (weight > 1.0f) {
|
||||
weight = 1.0f;
|
||||
}
|
||||
float signal = (perlin_signed(p) + offset) * pwr;
|
||||
value += rmd * weight * signal;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
float musgrave_ridged_multi_fractal(const float2 co,
|
||||
const float H,
|
||||
const float lacunarity,
|
||||
const float octaves_unclamped,
|
||||
const float offset,
|
||||
const float gain)
|
||||
{
|
||||
float2 p = co;
|
||||
const float pwHL = std::pow(lacunarity, -H);
|
||||
float pwr = pwHL;
|
||||
|
||||
float signal = offset - std::abs(perlin_signed(p));
|
||||
signal *= signal;
|
||||
float value = signal;
|
||||
float weight = 1.0f;
|
||||
|
||||
const float octaves = CLAMPIS(octaves_unclamped, 0.0f, 15.0f);
|
||||
|
||||
for (int i = 1; i < int(octaves); i++) {
|
||||
p *= lacunarity;
|
||||
weight = CLAMPIS(signal * gain, 0.0f, 1.0f);
|
||||
signal = offset - std::abs(perlin_signed(p));
|
||||
signal *= signal;
|
||||
signal *= weight;
|
||||
value += signal * pwr;
|
||||
pwr *= pwHL;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
float musgrave_fBm(const float3 co,
|
||||
const float H,
|
||||
const float lacunarity,
|
||||
const float octaves_unclamped)
|
||||
{
|
||||
/* From "Texturing and Modelling: A procedural approach". */
|
||||
|
||||
float3 p = co;
|
||||
float value = 0.0f;
|
||||
float pwr = 1.0f;
|
||||
const float pwHL = std::pow(lacunarity, -H);
|
||||
|
||||
const float octaves = CLAMPIS(octaves_unclamped, 0.0f, 15.0f);
|
||||
|
||||
for (int i = 0; i < int(octaves); i++) {
|
||||
value += perlin_signed(p) * pwr;
|
||||
pwr *= pwHL;
|
||||
p *= lacunarity;
|
||||
}
|
||||
|
||||
const float rmd = octaves - floorf(octaves);
|
||||
if (rmd != 0.0f) {
|
||||
value += rmd * perlin_signed(p) * pwr;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
float musgrave_multi_fractal(const float3 co,
|
||||
const float H,
|
||||
const float lacunarity,
|
||||
const float octaves_unclamped)
|
||||
{
|
||||
float3 p = co;
|
||||
float value = 1.0f;
|
||||
float pwr = 1.0f;
|
||||
const float pwHL = std::pow(lacunarity, -H);
|
||||
|
||||
const float octaves = CLAMPIS(octaves_unclamped, 0.0f, 15.0f);
|
||||
|
||||
for (int i = 0; i < int(octaves); i++) {
|
||||
value *= (pwr * perlin_signed(p) + 1.0f);
|
||||
pwr *= pwHL;
|
||||
p *= lacunarity;
|
||||
}
|
||||
|
||||
const float rmd = octaves - floorf(octaves);
|
||||
if (rmd != 0.0f) {
|
||||
value *= (rmd * pwr * perlin_signed(p) + 1.0f); /* correct? */
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
float musgrave_hetero_terrain(const float3 co,
|
||||
const float H,
|
||||
const float lacunarity,
|
||||
const float octaves_unclamped,
|
||||
const float offset)
|
||||
{
|
||||
float3 p = co;
|
||||
const float pwHL = std::pow(lacunarity, -H);
|
||||
float pwr = pwHL;
|
||||
|
||||
/* first unscaled octave of function; later octaves are scaled */
|
||||
float value = offset + perlin_signed(p);
|
||||
p *= lacunarity;
|
||||
|
||||
const float octaves = CLAMPIS(octaves_unclamped, 0.0f, 15.0f);
|
||||
|
||||
for (int i = 1; i < int(octaves); i++) {
|
||||
float increment = (perlin_signed(p) + offset) * pwr * value;
|
||||
value += increment;
|
||||
pwr *= pwHL;
|
||||
p *= lacunarity;
|
||||
}
|
||||
|
||||
const float rmd = octaves - floorf(octaves);
|
||||
if (rmd != 0.0f) {
|
||||
float increment = (perlin_signed(p) + offset) * pwr * value;
|
||||
value += rmd * increment;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
float musgrave_hybrid_multi_fractal(const float3 co,
|
||||
const float H,
|
||||
const float lacunarity,
|
||||
const float octaves_unclamped,
|
||||
const float offset,
|
||||
const float gain)
|
||||
{
|
||||
float3 p = co;
|
||||
const float pwHL = std::pow(lacunarity, -H);
|
||||
|
||||
float pwr = 1.0f;
|
||||
float value = 0.0f;
|
||||
float weight = 1.0f;
|
||||
|
||||
const float octaves = CLAMPIS(octaves_unclamped, 0.0f, 15.0f);
|
||||
|
||||
for (int i = 0; (weight > 0.001f) && (i < int(octaves)); i++) {
|
||||
if (weight > 1.0f) {
|
||||
weight = 1.0f;
|
||||
}
|
||||
|
||||
float signal = (perlin_signed(p) + offset) * pwr;
|
||||
pwr *= pwHL;
|
||||
value += weight * signal;
|
||||
weight *= gain * signal;
|
||||
p *= lacunarity;
|
||||
}
|
||||
|
||||
const float rmd = octaves - floorf(octaves);
|
||||
if ((rmd != 0.0f) && (weight > 0.001f)) {
|
||||
if (weight > 1.0f) {
|
||||
weight = 1.0f;
|
||||
}
|
||||
float signal = (perlin_signed(p) + offset) * pwr;
|
||||
value += rmd * weight * signal;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
float musgrave_ridged_multi_fractal(const float3 co,
|
||||
const float H,
|
||||
const float lacunarity,
|
||||
const float octaves_unclamped,
|
||||
const float offset,
|
||||
const float gain)
|
||||
{
|
||||
float3 p = co;
|
||||
const float pwHL = std::pow(lacunarity, -H);
|
||||
float pwr = pwHL;
|
||||
|
||||
float signal = offset - std::abs(perlin_signed(p));
|
||||
signal *= signal;
|
||||
float value = signal;
|
||||
float weight = 1.0f;
|
||||
|
||||
const float octaves = CLAMPIS(octaves_unclamped, 0.0f, 15.0f);
|
||||
|
||||
for (int i = 1; i < int(octaves); i++) {
|
||||
p *= lacunarity;
|
||||
weight = CLAMPIS(signal * gain, 0.0f, 1.0f);
|
||||
signal = offset - std::abs(perlin_signed(p));
|
||||
signal *= signal;
|
||||
signal *= weight;
|
||||
value += signal * pwr;
|
||||
pwr *= pwHL;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
float musgrave_fBm(const float4 co,
|
||||
const float H,
|
||||
const float lacunarity,
|
||||
const float octaves_unclamped)
|
||||
{
|
||||
/* From "Texturing and Modelling: A procedural approach". */
|
||||
|
||||
float4 p = co;
|
||||
float value = 0.0f;
|
||||
float pwr = 1.0f;
|
||||
const float pwHL = std::pow(lacunarity, -H);
|
||||
|
||||
const float octaves = CLAMPIS(octaves_unclamped, 0.0f, 15.0f);
|
||||
|
||||
for (int i = 0; i < int(octaves); i++) {
|
||||
value += perlin_signed(p) * pwr;
|
||||
pwr *= pwHL;
|
||||
p *= lacunarity;
|
||||
}
|
||||
|
||||
const float rmd = octaves - floorf(octaves);
|
||||
if (rmd != 0.0f) {
|
||||
value += rmd * perlin_signed(p) * pwr;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
float musgrave_multi_fractal(const float4 co,
|
||||
const float H,
|
||||
const float lacunarity,
|
||||
const float octaves_unclamped)
|
||||
{
|
||||
float4 p = co;
|
||||
float value = 1.0f;
|
||||
float pwr = 1.0f;
|
||||
const float pwHL = std::pow(lacunarity, -H);
|
||||
|
||||
const float octaves = CLAMPIS(octaves_unclamped, 0.0f, 15.0f);
|
||||
|
||||
for (int i = 0; i < int(octaves); i++) {
|
||||
value *= (pwr * perlin_signed(p) + 1.0f);
|
||||
pwr *= pwHL;
|
||||
p *= lacunarity;
|
||||
}
|
||||
|
||||
const float rmd = octaves - floorf(octaves);
|
||||
if (rmd != 0.0f) {
|
||||
value *= (rmd * pwr * perlin_signed(p) + 1.0f); /* correct? */
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
float musgrave_hetero_terrain(const float4 co,
|
||||
const float H,
|
||||
const float lacunarity,
|
||||
const float octaves_unclamped,
|
||||
const float offset)
|
||||
{
|
||||
float4 p = co;
|
||||
const float pwHL = std::pow(lacunarity, -H);
|
||||
float pwr = pwHL;
|
||||
|
||||
/* first unscaled octave of function; later octaves are scaled */
|
||||
float value = offset + perlin_signed(p);
|
||||
p *= lacunarity;
|
||||
|
||||
const float octaves = CLAMPIS(octaves_unclamped, 0.0f, 15.0f);
|
||||
|
||||
for (int i = 1; i < int(octaves); i++) {
|
||||
float increment = (perlin_signed(p) + offset) * pwr * value;
|
||||
value += increment;
|
||||
pwr *= pwHL;
|
||||
p *= lacunarity;
|
||||
}
|
||||
|
||||
const float rmd = octaves - floorf(octaves);
|
||||
if (rmd != 0.0f) {
|
||||
float increment = (perlin_signed(p) + offset) * pwr * value;
|
||||
value += rmd * increment;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
float musgrave_hybrid_multi_fractal(const float4 co,
|
||||
const float H,
|
||||
const float lacunarity,
|
||||
const float octaves_unclamped,
|
||||
const float offset,
|
||||
const float gain)
|
||||
{
|
||||
float4 p = co;
|
||||
const float pwHL = std::pow(lacunarity, -H);
|
||||
|
||||
float pwr = 1.0f;
|
||||
float value = 0.0f;
|
||||
float weight = 1.0f;
|
||||
|
||||
const float octaves = CLAMPIS(octaves_unclamped, 0.0f, 15.0f);
|
||||
|
||||
for (int i = 0; (weight > 0.001f) && (i < int(octaves)); i++) {
|
||||
if (weight > 1.0f) {
|
||||
weight = 1.0f;
|
||||
}
|
||||
|
||||
float signal = (perlin_signed(p) + offset) * pwr;
|
||||
pwr *= pwHL;
|
||||
value += weight * signal;
|
||||
weight *= gain * signal;
|
||||
p *= lacunarity;
|
||||
}
|
||||
|
||||
const float rmd = octaves - floorf(octaves);
|
||||
if ((rmd != 0.0f) && (weight > 0.001f)) {
|
||||
if (weight > 1.0f) {
|
||||
weight = 1.0f;
|
||||
}
|
||||
float signal = (perlin_signed(p) + offset) * pwr;
|
||||
value += rmd * weight * signal;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
float musgrave_ridged_multi_fractal(const float4 co,
|
||||
const float H,
|
||||
const float lacunarity,
|
||||
const float octaves_unclamped,
|
||||
const float offset,
|
||||
const float gain)
|
||||
{
|
||||
float4 p = co;
|
||||
const float pwHL = std::pow(lacunarity, -H);
|
||||
float pwr = pwHL;
|
||||
|
||||
float signal = offset - std::abs(perlin_signed(p));
|
||||
signal *= signal;
|
||||
float value = signal;
|
||||
float weight = 1.0f;
|
||||
|
||||
const float octaves = CLAMPIS(octaves_unclamped, 0.0f, 15.0f);
|
||||
|
||||
for (int i = 1; i < int(octaves); i++) {
|
||||
p *= lacunarity;
|
||||
weight = CLAMPIS(signal * gain, 0.0f, 1.0f);
|
||||
signal = offset - std::abs(perlin_signed(p));
|
||||
signal *= signal;
|
||||
signal *= weight;
|
||||
value += signal * pwr;
|
||||
pwr *= pwHL;
|
||||
}
|
||||
|
||||
return value;
|
||||
return float3(perlin_select<float4>(
|
||||
position, detail, roughness, lacunarity, offset, gain, type, normalize),
|
||||
perlin_select<float4>(position + random_float4_offset(4.0f),
|
||||
detail,
|
||||
roughness,
|
||||
lacunarity,
|
||||
offset,
|
||||
gain,
|
||||
type,
|
||||
normalize),
|
||||
perlin_select<float4>(position + random_float4_offset(5.0f),
|
||||
detail,
|
||||
roughness,
|
||||
lacunarity,
|
||||
offset,
|
||||
gain,
|
||||
type,
|
||||
normalize));
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
@@ -614,7 +614,7 @@ static const char *node_get_static_idname(int type, int treetype)
|
||||
return "ShaderNodeTexMagic";
|
||||
case SH_NODE_TEX_WAVE:
|
||||
return "ShaderNodeTexWave";
|
||||
case SH_NODE_TEX_MUSGRAVE:
|
||||
case SH_NODE_TEX_MUSGRAVE_DEPRECATED:
|
||||
return "ShaderNodeTexMusgrave";
|
||||
case SH_NODE_TEX_VORONOI:
|
||||
return "ShaderNodeTexVoronoi";
|
||||
|
||||
@@ -1853,7 +1853,7 @@ static void update_mapping_node_inputs_and_properties(bNodeTree *ntree)
|
||||
static void update_musgrave_node_dimensions(bNodeTree *ntree)
|
||||
{
|
||||
LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
|
||||
if (node->type == SH_NODE_TEX_MUSGRAVE && node->storage) {
|
||||
if (node->type == SH_NODE_TEX_MUSGRAVE_DEPRECATED && node->storage) {
|
||||
NodeTexMusgrave *tex = (NodeTexMusgrave *)node->storage;
|
||||
tex->dimensions = 3;
|
||||
}
|
||||
@@ -1867,7 +1867,7 @@ static void update_musgrave_node_dimensions(bNodeTree *ntree)
|
||||
static void update_musgrave_node_color_output(bNodeTree *ntree)
|
||||
{
|
||||
LISTBASE_FOREACH (bNodeLink *, link, &ntree->links) {
|
||||
if (link->fromnode && link->fromnode->type == SH_NODE_TEX_MUSGRAVE) {
|
||||
if (link->fromnode && link->fromnode->type == SH_NODE_TEX_MUSGRAVE_DEPRECATED) {
|
||||
if (link->fromsock->type == SOCK_RGBA) {
|
||||
link->fromsock = link->fromsock->next;
|
||||
}
|
||||
|
||||
@@ -692,6 +692,447 @@ static void version_principled_bsdf_sheen(bNodeTree *ntree)
|
||||
}
|
||||
}
|
||||
|
||||
static void versioning_update_noise_texture_node(bNodeTree *ntree)
|
||||
{
|
||||
LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
|
||||
if (node->type != SH_NODE_TEX_NOISE) {
|
||||
continue;
|
||||
}
|
||||
|
||||
(static_cast<NodeTexNoise *>(node->storage))->type = SHD_NOISE_FBM;
|
||||
|
||||
bNodeSocket *roughness_socket = nodeFindSocket(node, SOCK_IN, "Roughness");
|
||||
if (roughness_socket == nullptr) {
|
||||
/* Noise Texture node was created before the Roughness input was added. */
|
||||
continue;
|
||||
}
|
||||
|
||||
float *roughness = version_cycles_node_socket_float_value(roughness_socket);
|
||||
|
||||
bNodeLink *roughness_link = nullptr;
|
||||
bNode *roughness_from_node = nullptr;
|
||||
bNodeSocket *roughness_from_socket = nullptr;
|
||||
|
||||
LISTBASE_FOREACH (bNodeLink *, link, &ntree->links) {
|
||||
/* Find links, nodes and sockets. */
|
||||
if (link->tosock == roughness_socket) {
|
||||
roughness_link = link;
|
||||
roughness_from_node = link->fromnode;
|
||||
roughness_from_socket = link->fromsock;
|
||||
}
|
||||
}
|
||||
|
||||
if (roughness_link != nullptr) {
|
||||
/* Add Clamp node before Roughness input. */
|
||||
|
||||
bNode *clamp_node = nodeAddStaticNode(nullptr, ntree, SH_NODE_CLAMP);
|
||||
clamp_node->parent = node->parent;
|
||||
clamp_node->custom1 = NODE_CLAMP_MINMAX;
|
||||
clamp_node->locx = node->locx;
|
||||
clamp_node->locy = node->locy - 300.0f;
|
||||
clamp_node->flag |= NODE_HIDDEN;
|
||||
bNodeSocket *clamp_socket_value = nodeFindSocket(clamp_node, SOCK_IN, "Value");
|
||||
bNodeSocket *clamp_socket_min = nodeFindSocket(clamp_node, SOCK_IN, "Min");
|
||||
bNodeSocket *clamp_socket_max = nodeFindSocket(clamp_node, SOCK_IN, "Max");
|
||||
bNodeSocket *clamp_socket_out = nodeFindSocket(clamp_node, SOCK_OUT, "Result");
|
||||
|
||||
*version_cycles_node_socket_float_value(clamp_socket_min) = 0.0f;
|
||||
*version_cycles_node_socket_float_value(clamp_socket_max) = 1.0f;
|
||||
|
||||
nodeRemLink(ntree, roughness_link);
|
||||
nodeAddLink(
|
||||
ntree, roughness_from_node, roughness_from_socket, clamp_node, clamp_socket_value);
|
||||
nodeAddLink(ntree, clamp_node, clamp_socket_out, node, roughness_socket);
|
||||
}
|
||||
else {
|
||||
*roughness = std::clamp(*roughness, 0.0f, 1.0f);
|
||||
}
|
||||
}
|
||||
|
||||
version_socket_update_is_used(ntree);
|
||||
}
|
||||
|
||||
static void versioning_replace_musgrave_texture_node(bNodeTree *ntree)
|
||||
{
|
||||
version_node_input_socket_name(ntree, SH_NODE_TEX_MUSGRAVE_DEPRECATED, "Dimension", "Roughness");
|
||||
LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
|
||||
if (node->type != SH_NODE_TEX_MUSGRAVE_DEPRECATED) {
|
||||
continue;
|
||||
}
|
||||
|
||||
STRNCPY(node->idname, "ShaderNodeTexNoise");
|
||||
node->type = SH_NODE_TEX_NOISE;
|
||||
NodeTexNoise *data = MEM_cnew<NodeTexNoise>(__func__);
|
||||
data->base = (static_cast<NodeTexMusgrave *>(node->storage))->base;
|
||||
data->dimensions = (static_cast<NodeTexMusgrave *>(node->storage))->dimensions;
|
||||
data->normalize = false;
|
||||
data->type = (static_cast<NodeTexMusgrave *>(node->storage))->musgrave_type;
|
||||
MEM_freeN(node->storage);
|
||||
node->storage = data;
|
||||
|
||||
bNodeLink *detail_link = nullptr;
|
||||
bNode *detail_from_node = nullptr;
|
||||
bNodeSocket *detail_from_socket = nullptr;
|
||||
|
||||
bNodeLink *roughness_link = nullptr;
|
||||
bNode *roughness_from_node = nullptr;
|
||||
bNodeSocket *roughness_from_socket = nullptr;
|
||||
|
||||
bNodeLink *lacunarity_link = nullptr;
|
||||
bNode *lacunarity_from_node = nullptr;
|
||||
bNodeSocket *lacunarity_from_socket = nullptr;
|
||||
|
||||
LISTBASE_FOREACH (bNodeLink *, link, &ntree->links) {
|
||||
/* Find links, nodes and sockets. */
|
||||
if (link->tonode == node) {
|
||||
if (STREQ(link->tosock->identifier, "Detail")) {
|
||||
detail_link = link;
|
||||
detail_from_node = link->fromnode;
|
||||
detail_from_socket = link->fromsock;
|
||||
}
|
||||
if (STREQ(link->tosock->identifier, "Roughness")) {
|
||||
roughness_link = link;
|
||||
roughness_from_node = link->fromnode;
|
||||
roughness_from_socket = link->fromsock;
|
||||
}
|
||||
if (STREQ(link->tosock->identifier, "Lacunarity")) {
|
||||
lacunarity_link = link;
|
||||
lacunarity_from_node = link->fromnode;
|
||||
lacunarity_from_socket = link->fromsock;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t noise_type = (static_cast<NodeTexNoise *>(node->storage))->type;
|
||||
float locy_offset = 0.0f;
|
||||
|
||||
bNodeSocket *fac_socket = nodeFindSocket(node, SOCK_OUT, "Fac");
|
||||
/* Clear label because Musgrave output socket label is set to "Height" instead of "Fac". */
|
||||
fac_socket->label[0] = '\0';
|
||||
|
||||
bNodeSocket *detail_socket = nodeFindSocket(node, SOCK_IN, "Detail");
|
||||
float *detail = version_cycles_node_socket_float_value(detail_socket);
|
||||
|
||||
if (detail_link != nullptr) {
|
||||
locy_offset -= 80.0f;
|
||||
|
||||
/* Add Minimum Math node and Subtract Math node before Detail input. */
|
||||
|
||||
bNode *min_node = nodeAddStaticNode(nullptr, ntree, SH_NODE_MATH);
|
||||
min_node->parent = node->parent;
|
||||
min_node->custom1 = NODE_MATH_MINIMUM;
|
||||
min_node->locx = node->locx;
|
||||
min_node->locy = node->locy - 320.0f;
|
||||
min_node->flag |= NODE_HIDDEN;
|
||||
bNodeSocket *min_socket_A = static_cast<bNodeSocket *>(BLI_findlink(&min_node->inputs, 0));
|
||||
bNodeSocket *min_socket_B = static_cast<bNodeSocket *>(BLI_findlink(&min_node->inputs, 1));
|
||||
bNodeSocket *min_socket_out = nodeFindSocket(min_node, SOCK_OUT, "Value");
|
||||
|
||||
bNode *sub1_node = nodeAddStaticNode(nullptr, ntree, SH_NODE_MATH);
|
||||
sub1_node->parent = node->parent;
|
||||
sub1_node->custom1 = NODE_MATH_SUBTRACT;
|
||||
sub1_node->locx = node->locx;
|
||||
sub1_node->locy = node->locy - 360.0f;
|
||||
sub1_node->flag |= NODE_HIDDEN;
|
||||
bNodeSocket *sub1_socket_A = static_cast<bNodeSocket *>(BLI_findlink(&sub1_node->inputs, 0));
|
||||
bNodeSocket *sub1_socket_B = static_cast<bNodeSocket *>(BLI_findlink(&sub1_node->inputs, 1));
|
||||
bNodeSocket *sub1_socket_out = nodeFindSocket(sub1_node, SOCK_OUT, "Value");
|
||||
|
||||
*version_cycles_node_socket_float_value(min_socket_B) = 14.0f;
|
||||
*version_cycles_node_socket_float_value(sub1_socket_B) = 1.0f;
|
||||
|
||||
nodeRemLink(ntree, detail_link);
|
||||
nodeAddLink(ntree, detail_from_node, detail_from_socket, sub1_node, sub1_socket_A);
|
||||
nodeAddLink(ntree, sub1_node, sub1_socket_out, min_node, min_socket_A);
|
||||
nodeAddLink(ntree, min_node, min_socket_out, node, detail_socket);
|
||||
|
||||
if ((noise_type == SHD_NOISE_RIDGED_MULTIFRACTAL) ||
|
||||
(noise_type == SHD_NOISE_HETERO_TERRAIN)) {
|
||||
locy_offset -= 40.0f;
|
||||
|
||||
/* Add Greater Than Math node before Subtract Math node. */
|
||||
|
||||
bNode *greater_node = nodeAddStaticNode(nullptr, ntree, SH_NODE_MATH);
|
||||
greater_node->parent = node->parent;
|
||||
greater_node->custom1 = NODE_MATH_GREATER_THAN;
|
||||
greater_node->locx = node->locx;
|
||||
greater_node->locy = node->locy - 400.0f;
|
||||
greater_node->flag |= NODE_HIDDEN;
|
||||
bNodeSocket *greater_socket_A = static_cast<bNodeSocket *>(
|
||||
BLI_findlink(&greater_node->inputs, 0));
|
||||
bNodeSocket *greater_socket_B = static_cast<bNodeSocket *>(
|
||||
BLI_findlink(&greater_node->inputs, 1));
|
||||
bNodeSocket *greater_socket_out = nodeFindSocket(greater_node, SOCK_OUT, "Value");
|
||||
|
||||
*version_cycles_node_socket_float_value(greater_socket_B) = 1.0f;
|
||||
|
||||
nodeAddLink(ntree, detail_from_node, detail_from_socket, greater_node, greater_socket_A);
|
||||
nodeAddLink(ntree, greater_node, greater_socket_out, sub1_node, sub1_socket_B);
|
||||
}
|
||||
else {
|
||||
/* Add Clamp node and Multiply Math node behind Fac output. */
|
||||
|
||||
bNode *clamp_node = nodeAddStaticNode(nullptr, ntree, SH_NODE_CLAMP);
|
||||
clamp_node->parent = node->parent;
|
||||
clamp_node->custom1 = NODE_CLAMP_MINMAX;
|
||||
clamp_node->locx = node->locx;
|
||||
clamp_node->locy = node->locy + 40.0f;
|
||||
clamp_node->flag |= NODE_HIDDEN;
|
||||
bNodeSocket *clamp_socket_value = nodeFindSocket(clamp_node, SOCK_IN, "Value");
|
||||
bNodeSocket *clamp_socket_min = nodeFindSocket(clamp_node, SOCK_IN, "Min");
|
||||
bNodeSocket *clamp_socket_max = nodeFindSocket(clamp_node, SOCK_IN, "Max");
|
||||
bNodeSocket *clamp_socket_out = nodeFindSocket(clamp_node, SOCK_OUT, "Result");
|
||||
|
||||
bNode *mul_node = nodeAddStaticNode(nullptr, ntree, SH_NODE_MATH);
|
||||
mul_node->parent = node->parent;
|
||||
mul_node->custom1 = NODE_MATH_MULTIPLY;
|
||||
mul_node->locx = node->locx;
|
||||
mul_node->locy = node->locy + 80.0f;
|
||||
mul_node->flag |= NODE_HIDDEN;
|
||||
bNodeSocket *mul_socket_A = static_cast<bNodeSocket *>(BLI_findlink(&mul_node->inputs, 0));
|
||||
bNodeSocket *mul_socket_B = static_cast<bNodeSocket *>(BLI_findlink(&mul_node->inputs, 1));
|
||||
bNodeSocket *mul_socket_out = nodeFindSocket(mul_node, SOCK_OUT, "Value");
|
||||
|
||||
*version_cycles_node_socket_float_value(clamp_socket_min) = 0.0f;
|
||||
*version_cycles_node_socket_float_value(clamp_socket_max) = 1.0f;
|
||||
|
||||
if (noise_type == SHD_NOISE_MULTIFRACTAL) {
|
||||
/* Add Subtract Math node and Add Math node after Multiply Math node. */
|
||||
|
||||
bNode *sub2_node = nodeAddStaticNode(nullptr, ntree, SH_NODE_MATH);
|
||||
sub2_node->parent = node->parent;
|
||||
sub2_node->custom1 = NODE_MATH_SUBTRACT;
|
||||
sub2_node->custom2 = SHD_MATH_CLAMP;
|
||||
sub2_node->locx = node->locx;
|
||||
sub2_node->locy = node->locy + 120.0f;
|
||||
sub2_node->flag |= NODE_HIDDEN;
|
||||
bNodeSocket *sub2_socket_A = static_cast<bNodeSocket *>(
|
||||
BLI_findlink(&sub2_node->inputs, 0));
|
||||
bNodeSocket *sub2_socket_B = static_cast<bNodeSocket *>(
|
||||
BLI_findlink(&sub2_node->inputs, 1));
|
||||
bNodeSocket *sub2_socket_out = nodeFindSocket(sub2_node, SOCK_OUT, "Value");
|
||||
|
||||
bNode *add_node = nodeAddStaticNode(nullptr, ntree, SH_NODE_MATH);
|
||||
add_node->parent = node->parent;
|
||||
add_node->custom1 = NODE_MATH_ADD;
|
||||
add_node->locx = node->locx;
|
||||
add_node->locy = node->locy + 160.0f;
|
||||
add_node->flag |= NODE_HIDDEN;
|
||||
bNodeSocket *add_socket_A = static_cast<bNodeSocket *>(
|
||||
BLI_findlink(&add_node->inputs, 0));
|
||||
bNodeSocket *add_socket_B = static_cast<bNodeSocket *>(
|
||||
BLI_findlink(&add_node->inputs, 1));
|
||||
bNodeSocket *add_socket_out = nodeFindSocket(add_node, SOCK_OUT, "Value");
|
||||
|
||||
*version_cycles_node_socket_float_value(sub2_socket_A) = 1.0f;
|
||||
|
||||
LISTBASE_FOREACH_BACKWARD_MUTABLE (bNodeLink *, link, &ntree->links) {
|
||||
if (link->fromsock == fac_socket) {
|
||||
nodeAddLink(ntree, add_node, add_socket_out, link->tonode, link->tosock);
|
||||
nodeRemLink(ntree, link);
|
||||
}
|
||||
}
|
||||
|
||||
nodeAddLink(ntree, mul_node, mul_socket_out, add_node, add_socket_A);
|
||||
nodeAddLink(ntree, detail_from_node, detail_from_socket, sub2_node, sub2_socket_B);
|
||||
nodeAddLink(ntree, sub2_node, sub2_socket_out, add_node, add_socket_B);
|
||||
}
|
||||
else {
|
||||
LISTBASE_FOREACH_BACKWARD_MUTABLE (bNodeLink *, link, &ntree->links) {
|
||||
if (link->fromsock == fac_socket) {
|
||||
nodeAddLink(ntree, mul_node, mul_socket_out, link->tonode, link->tosock);
|
||||
nodeRemLink(ntree, link);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nodeAddLink(ntree, node, fac_socket, mul_node, mul_socket_A);
|
||||
nodeAddLink(ntree, detail_from_node, detail_from_socket, clamp_node, clamp_socket_value);
|
||||
nodeAddLink(ntree, clamp_node, clamp_socket_out, mul_node, mul_socket_B);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (*detail < 1.0f) {
|
||||
if ((noise_type != SHD_NOISE_RIDGED_MULTIFRACTAL) &&
|
||||
(noise_type != SHD_NOISE_HETERO_TERRAIN)) {
|
||||
/* Add Multiply Math node behind Fac output. */
|
||||
|
||||
bNode *mul_node = nodeAddStaticNode(nullptr, ntree, SH_NODE_MATH);
|
||||
mul_node->parent = node->parent;
|
||||
mul_node->custom1 = NODE_MATH_MULTIPLY;
|
||||
mul_node->locx = node->locx;
|
||||
mul_node->locy = node->locy + 40.0f;
|
||||
mul_node->flag |= NODE_HIDDEN;
|
||||
bNodeSocket *mul_socket_A = static_cast<bNodeSocket *>(
|
||||
BLI_findlink(&mul_node->inputs, 0));
|
||||
bNodeSocket *mul_socket_B = static_cast<bNodeSocket *>(
|
||||
BLI_findlink(&mul_node->inputs, 1));
|
||||
bNodeSocket *mul_socket_out = nodeFindSocket(mul_node, SOCK_OUT, "Value");
|
||||
|
||||
*version_cycles_node_socket_float_value(mul_socket_B) = *detail;
|
||||
|
||||
if (noise_type == SHD_NOISE_MULTIFRACTAL) {
|
||||
/* Add Add Math node after Multiply Math node. */
|
||||
|
||||
bNode *add_node = nodeAddStaticNode(nullptr, ntree, SH_NODE_MATH);
|
||||
add_node->parent = node->parent;
|
||||
add_node->custom1 = NODE_MATH_ADD;
|
||||
add_node->locx = node->locx;
|
||||
add_node->locy = node->locy + 80.0f;
|
||||
add_node->flag |= NODE_HIDDEN;
|
||||
bNodeSocket *add_socket_A = static_cast<bNodeSocket *>(
|
||||
BLI_findlink(&add_node->inputs, 0));
|
||||
bNodeSocket *add_socket_B = static_cast<bNodeSocket *>(
|
||||
BLI_findlink(&add_node->inputs, 1));
|
||||
bNodeSocket *add_socket_out = nodeFindSocket(add_node, SOCK_OUT, "Value");
|
||||
|
||||
*version_cycles_node_socket_float_value(add_socket_B) = 1.0f - *detail;
|
||||
|
||||
LISTBASE_FOREACH_BACKWARD_MUTABLE (bNodeLink *, link, &ntree->links) {
|
||||
if (link->fromsock == fac_socket) {
|
||||
nodeAddLink(ntree, add_node, add_socket_out, link->tonode, link->tosock);
|
||||
nodeRemLink(ntree, link);
|
||||
}
|
||||
}
|
||||
|
||||
nodeAddLink(ntree, mul_node, mul_socket_out, add_node, add_socket_A);
|
||||
}
|
||||
else {
|
||||
LISTBASE_FOREACH_BACKWARD_MUTABLE (bNodeLink *, link, &ntree->links) {
|
||||
if (link->fromsock == fac_socket) {
|
||||
nodeAddLink(ntree, mul_node, mul_socket_out, link->tonode, link->tosock);
|
||||
nodeRemLink(ntree, link);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nodeAddLink(ntree, node, fac_socket, mul_node, mul_socket_A);
|
||||
|
||||
*detail = 0.0f;
|
||||
}
|
||||
}
|
||||
else {
|
||||
*detail = std::fminf(*detail - 1.0f, 14.0f);
|
||||
}
|
||||
}
|
||||
|
||||
bNodeSocket *roughness_socket = nodeFindSocket(node, SOCK_IN, "Roughness");
|
||||
float *roughness = version_cycles_node_socket_float_value(roughness_socket);
|
||||
bNodeSocket *lacunarity_socket = nodeFindSocket(node, SOCK_IN, "Lacunarity");
|
||||
float *lacunarity = version_cycles_node_socket_float_value(lacunarity_socket);
|
||||
|
||||
*roughness = std::fmaxf(*roughness, 1e-5f);
|
||||
*lacunarity = std::fmaxf(*lacunarity, 1e-5f);
|
||||
|
||||
if (roughness_link != nullptr) {
|
||||
/* Add Maximum Math node after output of roughness_from_node. Add Multiply Math node and
|
||||
* Power Math node before Roughness input. */
|
||||
|
||||
bNode *max1_node = nodeAddStaticNode(nullptr, ntree, SH_NODE_MATH);
|
||||
max1_node->parent = node->parent;
|
||||
max1_node->custom1 = NODE_MATH_MAXIMUM;
|
||||
max1_node->locx = node->locx;
|
||||
max1_node->locy = node->locy - 400.0f + locy_offset;
|
||||
max1_node->flag |= NODE_HIDDEN;
|
||||
bNodeSocket *max1_socket_A = static_cast<bNodeSocket *>(BLI_findlink(&max1_node->inputs, 0));
|
||||
bNodeSocket *max1_socket_B = static_cast<bNodeSocket *>(BLI_findlink(&max1_node->inputs, 1));
|
||||
bNodeSocket *max1_socket_out = nodeFindSocket(max1_node, SOCK_OUT, "Value");
|
||||
|
||||
bNode *mul_node = nodeAddStaticNode(nullptr, ntree, SH_NODE_MATH);
|
||||
mul_node->parent = node->parent;
|
||||
mul_node->custom1 = NODE_MATH_MULTIPLY;
|
||||
mul_node->locx = node->locx;
|
||||
mul_node->locy = node->locy - 360.0f + locy_offset;
|
||||
mul_node->flag |= NODE_HIDDEN;
|
||||
bNodeSocket *mul_socket_A = static_cast<bNodeSocket *>(BLI_findlink(&mul_node->inputs, 0));
|
||||
bNodeSocket *mul_socket_B = static_cast<bNodeSocket *>(BLI_findlink(&mul_node->inputs, 1));
|
||||
bNodeSocket *mul_socket_out = nodeFindSocket(mul_node, SOCK_OUT, "Value");
|
||||
|
||||
bNode *pow_node = nodeAddStaticNode(nullptr, ntree, SH_NODE_MATH);
|
||||
pow_node->parent = node->parent;
|
||||
pow_node->custom1 = NODE_MATH_POWER;
|
||||
pow_node->locx = node->locx;
|
||||
pow_node->locy = node->locy - 320.0f + locy_offset;
|
||||
pow_node->flag |= NODE_HIDDEN;
|
||||
bNodeSocket *pow_socket_A = static_cast<bNodeSocket *>(BLI_findlink(&pow_node->inputs, 0));
|
||||
bNodeSocket *pow_socket_B = static_cast<bNodeSocket *>(BLI_findlink(&pow_node->inputs, 1));
|
||||
bNodeSocket *pow_socket_out = nodeFindSocket(pow_node, SOCK_OUT, "Value");
|
||||
|
||||
*version_cycles_node_socket_float_value(max1_socket_B) = -1e-5f;
|
||||
*version_cycles_node_socket_float_value(mul_socket_B) = -1.0f;
|
||||
*version_cycles_node_socket_float_value(pow_socket_A) = *lacunarity;
|
||||
|
||||
nodeRemLink(ntree, roughness_link);
|
||||
nodeAddLink(ntree, roughness_from_node, roughness_from_socket, max1_node, max1_socket_A);
|
||||
nodeAddLink(ntree, max1_node, max1_socket_out, mul_node, mul_socket_A);
|
||||
nodeAddLink(ntree, mul_node, mul_socket_out, pow_node, pow_socket_B);
|
||||
nodeAddLink(ntree, pow_node, pow_socket_out, node, roughness_socket);
|
||||
|
||||
if (lacunarity_link != nullptr) {
|
||||
/* Add Maximum Math node after output of lacunarity_from_node. */
|
||||
|
||||
bNode *max2_node = nodeAddStaticNode(nullptr, ntree, SH_NODE_MATH);
|
||||
max2_node->parent = node->parent;
|
||||
max2_node->custom1 = NODE_MATH_MAXIMUM;
|
||||
max2_node->locx = node->locx;
|
||||
max2_node->locy = node->locy - 440.0f + locy_offset;
|
||||
max2_node->flag |= NODE_HIDDEN;
|
||||
bNodeSocket *max2_socket_A = static_cast<bNodeSocket *>(
|
||||
BLI_findlink(&max2_node->inputs, 0));
|
||||
bNodeSocket *max2_socket_B = static_cast<bNodeSocket *>(
|
||||
BLI_findlink(&max2_node->inputs, 1));
|
||||
bNodeSocket *max2_socket_out = nodeFindSocket(max2_node, SOCK_OUT, "Value");
|
||||
|
||||
*version_cycles_node_socket_float_value(max2_socket_B) = -1e-5f;
|
||||
|
||||
nodeRemLink(ntree, lacunarity_link);
|
||||
nodeAddLink(ntree, lacunarity_from_node, lacunarity_from_socket, max2_node, max2_socket_A);
|
||||
nodeAddLink(ntree, max2_node, max2_socket_out, pow_node, pow_socket_A);
|
||||
nodeAddLink(ntree, max2_node, max2_socket_out, node, lacunarity_socket);
|
||||
}
|
||||
}
|
||||
else if ((lacunarity_link != nullptr) && (roughness_link == nullptr)) {
|
||||
/* Add Maximum Math node after output of lacunarity_from_node. Add Power Math node before
|
||||
* Roughness input. */
|
||||
|
||||
bNode *max2_node = nodeAddStaticNode(nullptr, ntree, SH_NODE_MATH);
|
||||
max2_node->parent = node->parent;
|
||||
max2_node->custom1 = NODE_MATH_MAXIMUM;
|
||||
max2_node->locx = node->locx;
|
||||
max2_node->locy = node->locy - 360.0f + locy_offset;
|
||||
max2_node->flag |= NODE_HIDDEN;
|
||||
bNodeSocket *max2_socket_A = static_cast<bNodeSocket *>(BLI_findlink(&max2_node->inputs, 0));
|
||||
bNodeSocket *max2_socket_B = static_cast<bNodeSocket *>(BLI_findlink(&max2_node->inputs, 1));
|
||||
bNodeSocket *max2_socket_out = nodeFindSocket(max2_node, SOCK_OUT, "Value");
|
||||
|
||||
bNode *pow_node = nodeAddStaticNode(nullptr, ntree, SH_NODE_MATH);
|
||||
pow_node->parent = node->parent;
|
||||
pow_node->custom1 = NODE_MATH_POWER;
|
||||
pow_node->locx = node->locx;
|
||||
pow_node->locy = node->locy - 320.0f + locy_offset;
|
||||
pow_node->flag |= NODE_HIDDEN;
|
||||
bNodeSocket *pow_socket_A = static_cast<bNodeSocket *>(BLI_findlink(&pow_node->inputs, 0));
|
||||
bNodeSocket *pow_socket_B = static_cast<bNodeSocket *>(BLI_findlink(&pow_node->inputs, 1));
|
||||
bNodeSocket *pow_socket_out = nodeFindSocket(pow_node, SOCK_OUT, "Value");
|
||||
|
||||
*version_cycles_node_socket_float_value(max2_socket_B) = -1e-5f;
|
||||
*version_cycles_node_socket_float_value(pow_socket_A) = *lacunarity;
|
||||
*version_cycles_node_socket_float_value(pow_socket_B) = -(*roughness);
|
||||
|
||||
nodeRemLink(ntree, lacunarity_link);
|
||||
nodeAddLink(ntree, lacunarity_from_node, lacunarity_from_socket, max2_node, max2_socket_A);
|
||||
nodeAddLink(ntree, max2_node, max2_socket_out, pow_node, pow_socket_A);
|
||||
nodeAddLink(ntree, max2_node, max2_socket_out, node, lacunarity_socket);
|
||||
nodeAddLink(ntree, pow_node, pow_socket_out, node, roughness_socket);
|
||||
}
|
||||
else {
|
||||
*roughness = std::pow(*lacunarity, -(*roughness));
|
||||
}
|
||||
}
|
||||
|
||||
version_socket_update_is_used(ntree);
|
||||
}
|
||||
|
||||
/* Convert subsurface inputs on the Principled BSDF. */
|
||||
static void version_principled_bsdf_subsurface(bNodeTree *ntree)
|
||||
{
|
||||
@@ -1943,6 +2384,20 @@ void blo_do_versions_400(FileData *fd, Library * /*lib*/, Main *bmain)
|
||||
}
|
||||
}
|
||||
|
||||
if (!MAIN_VERSION_FILE_ATLEAST(bmain, 401, 4)) {
|
||||
FOREACH_NODETREE_BEGIN (bmain, ntree, id) {
|
||||
if (ntree->type != NTREE_CUSTOM) {
|
||||
/* versioning_update_noise_texture_node must be done before
|
||||
* versioning_replace_musgrave_texture_node. */
|
||||
versioning_update_noise_texture_node(ntree);
|
||||
|
||||
/* Convert Musgrave Texture nodes to Noise Texture nodes. */
|
||||
versioning_replace_musgrave_texture_node(ntree);
|
||||
}
|
||||
}
|
||||
FOREACH_NODETREE_END;
|
||||
}
|
||||
|
||||
if (!MAIN_VERSION_FILE_ATLEAST(bmain, 401, 5)) {
|
||||
/* Unify Material::blend_shadow and Cycles.use_transparent_shadows into the
|
||||
* Material::blend_flag. */
|
||||
|
||||
@@ -553,7 +553,6 @@ set(GLSL_SRC
|
||||
shaders/material/gpu_shader_material_tex_gradient.glsl
|
||||
shaders/material/gpu_shader_material_tex_image.glsl
|
||||
shaders/material/gpu_shader_material_tex_magic.glsl
|
||||
shaders/material/gpu_shader_material_tex_musgrave.glsl
|
||||
shaders/material/gpu_shader_material_tex_noise.glsl
|
||||
shaders/material/gpu_shader_material_tex_sky.glsl
|
||||
shaders/material/gpu_shader_material_texture_coordinates.glsl
|
||||
|
||||
@@ -5,114 +5,198 @@
|
||||
#pragma BLENDER_REQUIRE(gpu_shader_common_hash.glsl)
|
||||
#pragma BLENDER_REQUIRE(gpu_shader_material_noise.glsl)
|
||||
|
||||
/* The fractal_noise functions are all exactly the same except for the input type. */
|
||||
float fractal_noise(float p, float octaves, float roughness, float lacunarity, bool normalize)
|
||||
{
|
||||
float fscale = 1.0;
|
||||
float amp = 1.0;
|
||||
float maxamp = 0.0;
|
||||
float sum = 0.0;
|
||||
octaves = clamp(octaves, 0.0, 15.0);
|
||||
int n = int(octaves);
|
||||
for (int i = 0; i <= n; i++) {
|
||||
float t = snoise(fscale * p);
|
||||
sum += t * amp;
|
||||
maxamp += amp;
|
||||
amp *= clamp(roughness, 0.0, 1.0);
|
||||
fscale *= lacunarity;
|
||||
#define NOISE_FBM(T) \
|
||||
float noise_fbm(T co, \
|
||||
float detail, \
|
||||
float roughness, \
|
||||
float lacunarity, \
|
||||
float offset, \
|
||||
float gain, \
|
||||
bool normalize) \
|
||||
{ \
|
||||
T p = co; \
|
||||
float fscale = 1.0; \
|
||||
float amp = 1.0; \
|
||||
float maxamp = 0.0; \
|
||||
float sum = 0.0; \
|
||||
\
|
||||
for (int i = 0; i <= int(detail); i++) { \
|
||||
float t = snoise(fscale * p); \
|
||||
sum += t * amp; \
|
||||
maxamp += amp; \
|
||||
amp *= roughness; \
|
||||
fscale *= lacunarity; \
|
||||
} \
|
||||
float rmd = detail - floor(detail); \
|
||||
if (rmd != 0.0) { \
|
||||
float t = snoise(fscale * p); \
|
||||
float sum2 = sum + t * amp; \
|
||||
return normalize ? mix(0.5 * sum / maxamp + 0.5, 0.5 * sum2 / (maxamp + amp) + 0.5, rmd) : \
|
||||
mix(sum, sum2, rmd); \
|
||||
} \
|
||||
else { \
|
||||
return normalize ? 0.5 * sum / maxamp + 0.5 : sum; \
|
||||
} \
|
||||
}
|
||||
float rmd = octaves - floor(octaves);
|
||||
if (rmd != 0.0) {
|
||||
float t = snoise(fscale * p);
|
||||
float sum2 = sum + t * amp;
|
||||
return normalize ? mix(0.5 * sum / maxamp + 0.5, 0.5 * sum2 / (maxamp + amp) + 0.5, rmd) :
|
||||
mix(sum, sum2, rmd);
|
||||
}
|
||||
else {
|
||||
return normalize ? 0.5 * sum / maxamp + 0.5 : sum;
|
||||
}
|
||||
}
|
||||
|
||||
/* The fractal_noise functions are all exactly the same except for the input type. */
|
||||
float fractal_noise(vec2 p, float octaves, float roughness, float lacunarity, bool normalize)
|
||||
{
|
||||
float fscale = 1.0;
|
||||
float amp = 1.0;
|
||||
float maxamp = 0.0;
|
||||
float sum = 0.0;
|
||||
octaves = clamp(octaves, 0.0, 15.0);
|
||||
int n = int(octaves);
|
||||
for (int i = 0; i <= n; i++) {
|
||||
float t = snoise(fscale * p);
|
||||
sum += t * amp;
|
||||
maxamp += amp;
|
||||
amp *= clamp(roughness, 0.0, 1.0);
|
||||
fscale *= lacunarity;
|
||||
#define NOISE_MULTI_FRACTAL(T) \
|
||||
float noise_multi_fractal(T co, \
|
||||
float detail, \
|
||||
float roughness, \
|
||||
float lacunarity, \
|
||||
float offset, \
|
||||
float gain, \
|
||||
bool normalize) \
|
||||
{ \
|
||||
T p = co; \
|
||||
float value = 1.0; \
|
||||
float pwr = 1.0; \
|
||||
\
|
||||
for (int i = 0; i <= int(detail); i++) { \
|
||||
value *= (pwr * snoise(p) + 1.0); \
|
||||
pwr *= roughness; \
|
||||
p *= lacunarity; \
|
||||
} \
|
||||
\
|
||||
float rmd = detail - floor(detail); \
|
||||
if (rmd != 0.0) { \
|
||||
value *= (rmd * pwr * snoise(p) + 1.0); /* correct? */ \
|
||||
} \
|
||||
\
|
||||
return value; \
|
||||
}
|
||||
float rmd = octaves - floor(octaves);
|
||||
if (rmd != 0.0) {
|
||||
float t = snoise(fscale * p);
|
||||
float sum2 = sum + t * amp;
|
||||
return normalize ? mix(0.5 * sum / maxamp + 0.5, 0.5 * sum2 / (maxamp + amp) + 0.5, rmd) :
|
||||
mix(sum, sum2, rmd);
|
||||
}
|
||||
else {
|
||||
return normalize ? 0.5 * sum / maxamp + 0.5 : sum;
|
||||
}
|
||||
}
|
||||
|
||||
/* The fractal_noise functions are all exactly the same except for the input type. */
|
||||
float fractal_noise(vec3 p, float octaves, float roughness, float lacunarity, bool normalize)
|
||||
{
|
||||
float fscale = 1.0;
|
||||
float amp = 1.0;
|
||||
float maxamp = 0.0;
|
||||
float sum = 0.0;
|
||||
octaves = clamp(octaves, 0.0, 15.0);
|
||||
int n = int(octaves);
|
||||
for (int i = 0; i <= n; i++) {
|
||||
float t = snoise(fscale * p);
|
||||
sum += t * amp;
|
||||
maxamp += amp;
|
||||
amp *= clamp(roughness, 0.0, 1.0);
|
||||
fscale *= lacunarity;
|
||||
#define NOISE_HETERO_TERRAIN(T) \
|
||||
float noise_hetero_terrain(T co, \
|
||||
float detail, \
|
||||
float roughness, \
|
||||
float lacunarity, \
|
||||
float offset, \
|
||||
float gain, \
|
||||
bool normalize) \
|
||||
{ \
|
||||
T p = co; \
|
||||
float pwr = roughness; \
|
||||
\
|
||||
/* first unscaled octave of function; later octaves are scaled */ \
|
||||
float value = offset + snoise(p); \
|
||||
p *= lacunarity; \
|
||||
\
|
||||
for (int i = 1; i <= int(detail); i++) { \
|
||||
float increment = (snoise(p) + offset) * pwr * value; \
|
||||
value += increment; \
|
||||
pwr *= roughness; \
|
||||
p *= lacunarity; \
|
||||
} \
|
||||
\
|
||||
float rmd = detail - floor(detail); \
|
||||
if (rmd != 0.0) { \
|
||||
float increment = (snoise(p) + offset) * pwr * value; \
|
||||
value += rmd * increment; \
|
||||
} \
|
||||
\
|
||||
return value; \
|
||||
}
|
||||
float rmd = octaves - floor(octaves);
|
||||
if (rmd != 0.0) {
|
||||
float t = snoise(fscale * p);
|
||||
float sum2 = sum + t * amp;
|
||||
return normalize ? mix(0.5 * sum / maxamp + 0.5, 0.5 * sum2 / (maxamp + amp) + 0.5, rmd) :
|
||||
mix(sum, sum2, rmd);
|
||||
}
|
||||
else {
|
||||
return normalize ? 0.5 * sum / maxamp + 0.5 : sum;
|
||||
}
|
||||
}
|
||||
|
||||
/* The fractal_noise functions are all exactly the same except for the input type. */
|
||||
float fractal_noise(vec4 p, float octaves, float roughness, float lacunarity, bool normalize)
|
||||
{
|
||||
float fscale = 1.0;
|
||||
float amp = 1.0;
|
||||
float maxamp = 0.0;
|
||||
float sum = 0.0;
|
||||
octaves = clamp(octaves, 0.0, 15.0);
|
||||
int n = int(octaves);
|
||||
for (int i = 0; i <= n; i++) {
|
||||
float t = snoise(fscale * p);
|
||||
sum += t * amp;
|
||||
maxamp += amp;
|
||||
amp *= clamp(roughness, 0.0, 1.0);
|
||||
fscale *= lacunarity;
|
||||
#define NOISE_HYBRID_MULTI_FRACTAL(T) \
|
||||
float noise_hybrid_multi_fractal(T co, \
|
||||
float detail, \
|
||||
float roughness, \
|
||||
float lacunarity, \
|
||||
float offset, \
|
||||
float gain, \
|
||||
bool normalize) \
|
||||
{ \
|
||||
T p = co; \
|
||||
float pwr = 1.0; \
|
||||
float value = 0.0; \
|
||||
float weight = 1.0; \
|
||||
\
|
||||
for (int i = 0; (weight > 0.001) && (i <= int(detail)); i++) { \
|
||||
if (weight > 1.0) { \
|
||||
weight = 1.0; \
|
||||
} \
|
||||
\
|
||||
float signal = (snoise(p) + offset) * pwr; \
|
||||
pwr *= roughness; \
|
||||
value += weight * signal; \
|
||||
weight *= gain * signal; \
|
||||
p *= lacunarity; \
|
||||
} \
|
||||
\
|
||||
float rmd = detail - floor(detail); \
|
||||
if ((rmd != 0.0) && (weight > 0.001)) { \
|
||||
if (weight > 1.0) { \
|
||||
weight = 1.0; \
|
||||
} \
|
||||
float signal = (snoise(p) + offset) * pwr; \
|
||||
value += rmd * weight * signal; \
|
||||
} \
|
||||
\
|
||||
return value; \
|
||||
}
|
||||
float rmd = octaves - floor(octaves);
|
||||
if (rmd != 0.0) {
|
||||
float t = snoise(fscale * p);
|
||||
float sum2 = sum + t * amp;
|
||||
return normalize ? mix(0.5 * sum / maxamp + 0.5, 0.5 * sum2 / (maxamp + amp) + 0.5, rmd) :
|
||||
mix(sum, sum2, rmd);
|
||||
|
||||
#define NOISE_RIDGED_MULTI_FRACTAL(T) \
|
||||
float noise_ridged_multi_fractal(T co, \
|
||||
float detail, \
|
||||
float roughness, \
|
||||
float lacunarity, \
|
||||
float offset, \
|
||||
float gain, \
|
||||
bool normalize) \
|
||||
{ \
|
||||
T p = co; \
|
||||
float pwr = roughness; \
|
||||
\
|
||||
float signal = offset - abs(snoise(p)); \
|
||||
signal *= signal; \
|
||||
float value = signal; \
|
||||
float weight = 1.0; \
|
||||
\
|
||||
for (int i = 1; i <= int(detail); i++) { \
|
||||
p *= lacunarity; \
|
||||
weight = clamp(signal * gain, 0.0, 1.0); \
|
||||
signal = offset - abs(snoise(p)); \
|
||||
signal *= signal; \
|
||||
signal *= weight; \
|
||||
value += signal * pwr; \
|
||||
pwr *= roughness; \
|
||||
} \
|
||||
\
|
||||
return value; \
|
||||
}
|
||||
else {
|
||||
return normalize ? 0.5 * sum / maxamp + 0.5 : sum;
|
||||
}
|
||||
}
|
||||
|
||||
/* Noise fBM */
|
||||
|
||||
NOISE_FBM(float)
|
||||
NOISE_FBM(vec2)
|
||||
NOISE_FBM(vec3)
|
||||
NOISE_FBM(vec4)
|
||||
|
||||
/* Noise Multifractal */
|
||||
|
||||
NOISE_MULTI_FRACTAL(float)
|
||||
NOISE_MULTI_FRACTAL(vec2)
|
||||
NOISE_MULTI_FRACTAL(vec3)
|
||||
NOISE_MULTI_FRACTAL(vec4)
|
||||
|
||||
/* Noise Hetero Terrain */
|
||||
|
||||
NOISE_HETERO_TERRAIN(float)
|
||||
NOISE_HETERO_TERRAIN(vec2)
|
||||
NOISE_HETERO_TERRAIN(vec3)
|
||||
NOISE_HETERO_TERRAIN(vec4)
|
||||
|
||||
/* Noise Hybrid Multifractal */
|
||||
|
||||
NOISE_HYBRID_MULTI_FRACTAL(float)
|
||||
NOISE_HYBRID_MULTI_FRACTAL(vec2)
|
||||
NOISE_HYBRID_MULTI_FRACTAL(vec3)
|
||||
NOISE_HYBRID_MULTI_FRACTAL(vec4)
|
||||
|
||||
/* Noise Ridged Multifractal */
|
||||
|
||||
NOISE_RIDGED_MULTI_FRACTAL(float)
|
||||
NOISE_RIDGED_MULTI_FRACTAL(vec2)
|
||||
NOISE_RIDGED_MULTI_FRACTAL(vec3)
|
||||
NOISE_RIDGED_MULTI_FRACTAL(vec4)
|
||||
|
||||
@@ -1,906 +0,0 @@
|
||||
/* SPDX-FileCopyrightText: 2019-2022 Blender Authors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/* 1D Musgrave fBm
|
||||
*
|
||||
* H: fractal increment parameter
|
||||
* lacunarity: gap between successive frequencies
|
||||
* octaves: number of frequencies in the fBm
|
||||
*
|
||||
* from "Texturing and Modelling: A procedural approach"
|
||||
*/
|
||||
|
||||
#pragma BLENDER_REQUIRE(gpu_shader_common_hash.glsl)
|
||||
#pragma BLENDER_REQUIRE(gpu_shader_material_noise.glsl)
|
||||
|
||||
void node_tex_musgrave_fBm_1d(vec3 co,
|
||||
float w,
|
||||
float scale,
|
||||
float detail,
|
||||
float dimension,
|
||||
float lac,
|
||||
float offset,
|
||||
float gain,
|
||||
out float fac)
|
||||
{
|
||||
float p = w * scale;
|
||||
float H = max(dimension, 1e-5);
|
||||
float octaves = clamp(detail, 0.0, 15.0);
|
||||
float lacunarity = max(lac, 1e-5);
|
||||
|
||||
float value = 0.0;
|
||||
float pwr = 1.0;
|
||||
float pwHL = pow(lacunarity, -H);
|
||||
|
||||
for (int i = 0; i < int(octaves); i++) {
|
||||
value += snoise(p) * pwr;
|
||||
pwr *= pwHL;
|
||||
p *= lacunarity;
|
||||
}
|
||||
|
||||
float rmd = octaves - floor(octaves);
|
||||
if (rmd != 0.0) {
|
||||
value += rmd * snoise(p) * pwr;
|
||||
}
|
||||
|
||||
fac = value;
|
||||
}
|
||||
|
||||
/* 1D Musgrave Multi-fractal
|
||||
*
|
||||
* H: highest fractal dimension
|
||||
* lacunarity: gap between successive frequencies
|
||||
* octaves: number of frequencies in the fBm
|
||||
*/
|
||||
|
||||
void node_tex_musgrave_multi_fractal_1d(vec3 co,
|
||||
float w,
|
||||
float scale,
|
||||
float detail,
|
||||
float dimension,
|
||||
float lac,
|
||||
float offset,
|
||||
float gain,
|
||||
out float fac)
|
||||
{
|
||||
float p = w * scale;
|
||||
float H = max(dimension, 1e-5);
|
||||
float octaves = clamp(detail, 0.0, 15.0);
|
||||
float lacunarity = max(lac, 1e-5);
|
||||
|
||||
float value = 1.0;
|
||||
float pwr = 1.0;
|
||||
float pwHL = pow(lacunarity, -H);
|
||||
|
||||
for (int i = 0; i < int(octaves); i++) {
|
||||
value *= (pwr * snoise(p) + 1.0);
|
||||
pwr *= pwHL;
|
||||
p *= lacunarity;
|
||||
}
|
||||
|
||||
float rmd = octaves - floor(octaves);
|
||||
if (rmd != 0.0) {
|
||||
value *= (rmd * pwr * snoise(p) + 1.0); /* correct? */
|
||||
}
|
||||
|
||||
fac = value;
|
||||
}
|
||||
|
||||
/* 1D Musgrave Heterogeneous Terrain
|
||||
*
|
||||
* H: fractal dimension of the roughest area
|
||||
* lacunarity: gap between successive frequencies
|
||||
* octaves: number of frequencies in the fBm
|
||||
* offset: raises the terrain from `sea level'
|
||||
*/
|
||||
|
||||
void node_tex_musgrave_hetero_terrain_1d(vec3 co,
|
||||
float w,
|
||||
float scale,
|
||||
float detail,
|
||||
float dimension,
|
||||
float lac,
|
||||
float offset,
|
||||
float gain,
|
||||
out float fac)
|
||||
{
|
||||
float p = w * scale;
|
||||
float H = max(dimension, 1e-5);
|
||||
float octaves = clamp(detail, 0.0, 15.0);
|
||||
float lacunarity = max(lac, 1e-5);
|
||||
|
||||
float pwHL = pow(lacunarity, -H);
|
||||
float pwr = pwHL;
|
||||
|
||||
/* first unscaled octave of function; later octaves are scaled */
|
||||
float value = offset + snoise(p);
|
||||
p *= lacunarity;
|
||||
|
||||
for (int i = 1; i < int(octaves); i++) {
|
||||
float increment = (snoise(p) + offset) * pwr * value;
|
||||
value += increment;
|
||||
pwr *= pwHL;
|
||||
p *= lacunarity;
|
||||
}
|
||||
|
||||
float rmd = octaves - floor(octaves);
|
||||
if (rmd != 0.0) {
|
||||
float increment = (snoise(p) + offset) * pwr * value;
|
||||
value += rmd * increment;
|
||||
}
|
||||
|
||||
fac = value;
|
||||
}
|
||||
|
||||
/* 1D Hybrid Additive/Multiplicative Multi-fractal Terrain
|
||||
*
|
||||
* H: fractal dimension of the roughest area
|
||||
* lacunarity: gap between successive frequencies
|
||||
* octaves: number of frequencies in the fBm
|
||||
* offset: raises the terrain from `sea level'
|
||||
*/
|
||||
|
||||
void node_tex_musgrave_hybrid_multi_fractal_1d(vec3 co,
|
||||
float w,
|
||||
float scale,
|
||||
float detail,
|
||||
float dimension,
|
||||
float lac,
|
||||
float offset,
|
||||
float gain,
|
||||
out float fac)
|
||||
{
|
||||
float p = w * scale;
|
||||
float H = max(dimension, 1e-5);
|
||||
float octaves = clamp(detail, 0.0, 15.0);
|
||||
float lacunarity = max(lac, 1e-5);
|
||||
|
||||
float pwHL = pow(lacunarity, -H);
|
||||
|
||||
float pwr = 1.0;
|
||||
float value = 0.0;
|
||||
float weight = 1.0;
|
||||
|
||||
for (int i = 0; (weight > 0.001f) && (i < int(octaves)); i++) {
|
||||
if (weight > 1.0) {
|
||||
weight = 1.0;
|
||||
}
|
||||
|
||||
float signal = (snoise(p) + offset) * pwr;
|
||||
pwr *= pwHL;
|
||||
value += weight * signal;
|
||||
weight *= gain * signal;
|
||||
p *= lacunarity;
|
||||
}
|
||||
|
||||
float rmd = octaves - floor(octaves);
|
||||
if ((rmd != 0.0) && (weight > 0.001f)) {
|
||||
if (weight > 1.0) {
|
||||
weight = 1.0;
|
||||
}
|
||||
float signal = (snoise(p) + offset) * pwr;
|
||||
value += rmd * weight * signal;
|
||||
}
|
||||
|
||||
fac = value;
|
||||
}
|
||||
|
||||
/* 1D Ridged Multi-fractal Terrain
|
||||
*
|
||||
* H: fractal dimension of the roughest area
|
||||
* lacunarity: gap between successive frequencies
|
||||
* octaves: number of frequencies in the fBm
|
||||
* offset: raises the terrain from `sea level'
|
||||
*/
|
||||
|
||||
void node_tex_musgrave_ridged_multi_fractal_1d(vec3 co,
|
||||
float w,
|
||||
float scale,
|
||||
float detail,
|
||||
float dimension,
|
||||
float lac,
|
||||
float offset,
|
||||
float gain,
|
||||
out float fac)
|
||||
{
|
||||
float p = w * scale;
|
||||
float H = max(dimension, 1e-5);
|
||||
float octaves = clamp(detail, 0.0, 15.0);
|
||||
float lacunarity = max(lac, 1e-5);
|
||||
|
||||
float pwHL = pow(lacunarity, -H);
|
||||
float pwr = pwHL;
|
||||
|
||||
float signal = offset - abs(snoise(p));
|
||||
signal *= signal;
|
||||
float value = signal;
|
||||
float weight = 1.0;
|
||||
|
||||
for (int i = 1; i < int(octaves); i++) {
|
||||
p *= lacunarity;
|
||||
weight = clamp(signal * gain, 0.0, 1.0);
|
||||
signal = offset - abs(snoise(p));
|
||||
signal *= signal;
|
||||
signal *= weight;
|
||||
value += signal * pwr;
|
||||
pwr *= pwHL;
|
||||
}
|
||||
|
||||
fac = value;
|
||||
}
|
||||
|
||||
/* 2D Musgrave fBm
|
||||
*
|
||||
* H: fractal increment parameter
|
||||
* lacunarity: gap between successive frequencies
|
||||
* octaves: number of frequencies in the fBm
|
||||
*
|
||||
* from "Texturing and Modelling: A procedural approach"
|
||||
*/
|
||||
|
||||
void node_tex_musgrave_fBm_2d(vec3 co,
|
||||
float w,
|
||||
float scale,
|
||||
float detail,
|
||||
float dimension,
|
||||
float lac,
|
||||
float offset,
|
||||
float gain,
|
||||
out float fac)
|
||||
{
|
||||
vec2 p = co.xy * scale;
|
||||
float H = max(dimension, 1e-5);
|
||||
float octaves = clamp(detail, 0.0, 15.0);
|
||||
float lacunarity = max(lac, 1e-5);
|
||||
|
||||
float value = 0.0;
|
||||
float pwr = 1.0;
|
||||
float pwHL = pow(lacunarity, -H);
|
||||
|
||||
for (int i = 0; i < int(octaves); i++) {
|
||||
value += snoise(p) * pwr;
|
||||
pwr *= pwHL;
|
||||
p *= lacunarity;
|
||||
}
|
||||
|
||||
float rmd = octaves - floor(octaves);
|
||||
if (rmd != 0.0) {
|
||||
value += rmd * snoise(p) * pwr;
|
||||
}
|
||||
|
||||
fac = value;
|
||||
}
|
||||
|
||||
/* 2D Musgrave Multi-fractal
|
||||
*
|
||||
* H: highest fractal dimension
|
||||
* lacunarity: gap between successive frequencies
|
||||
* octaves: number of frequencies in the fBm
|
||||
*/
|
||||
|
||||
void node_tex_musgrave_multi_fractal_2d(vec3 co,
|
||||
float w,
|
||||
float scale,
|
||||
float detail,
|
||||
float dimension,
|
||||
float lac,
|
||||
float offset,
|
||||
float gain,
|
||||
out float fac)
|
||||
{
|
||||
vec2 p = co.xy * scale;
|
||||
float H = max(dimension, 1e-5);
|
||||
float octaves = clamp(detail, 0.0, 15.0);
|
||||
float lacunarity = max(lac, 1e-5);
|
||||
|
||||
float value = 1.0;
|
||||
float pwr = 1.0;
|
||||
float pwHL = pow(lacunarity, -H);
|
||||
|
||||
for (int i = 0; i < int(octaves); i++) {
|
||||
value *= (pwr * snoise(p) + 1.0);
|
||||
pwr *= pwHL;
|
||||
p *= lacunarity;
|
||||
}
|
||||
|
||||
float rmd = octaves - floor(octaves);
|
||||
if (rmd != 0.0) {
|
||||
value *= (rmd * pwr * snoise(p) + 1.0); /* correct? */
|
||||
}
|
||||
|
||||
fac = value;
|
||||
}
|
||||
|
||||
/* 2D Musgrave Heterogeneous Terrain
|
||||
*
|
||||
* H: fractal dimension of the roughest area
|
||||
* lacunarity: gap between successive frequencies
|
||||
* octaves: number of frequencies in the fBm
|
||||
* offset: raises the terrain from `sea level'
|
||||
*/
|
||||
|
||||
void node_tex_musgrave_hetero_terrain_2d(vec3 co,
|
||||
float w,
|
||||
float scale,
|
||||
float detail,
|
||||
float dimension,
|
||||
float lac,
|
||||
float offset,
|
||||
float gain,
|
||||
out float fac)
|
||||
{
|
||||
vec2 p = co.xy * scale;
|
||||
float H = max(dimension, 1e-5);
|
||||
float octaves = clamp(detail, 0.0, 15.0);
|
||||
float lacunarity = max(lac, 1e-5);
|
||||
|
||||
float pwHL = pow(lacunarity, -H);
|
||||
float pwr = pwHL;
|
||||
|
||||
/* first unscaled octave of function; later octaves are scaled */
|
||||
float value = offset + snoise(p);
|
||||
p *= lacunarity;
|
||||
|
||||
for (int i = 1; i < int(octaves); i++) {
|
||||
float increment = (snoise(p) + offset) * pwr * value;
|
||||
value += increment;
|
||||
pwr *= pwHL;
|
||||
p *= lacunarity;
|
||||
}
|
||||
|
||||
float rmd = octaves - floor(octaves);
|
||||
if (rmd != 0.0) {
|
||||
float increment = (snoise(p) + offset) * pwr * value;
|
||||
value += rmd * increment;
|
||||
}
|
||||
|
||||
fac = value;
|
||||
}
|
||||
|
||||
/* 2D Hybrid Additive/Multiplicative Multi-fractal Terrain
|
||||
*
|
||||
* H: fractal dimension of the roughest area
|
||||
* lacunarity: gap between successive frequencies
|
||||
* octaves: number of frequencies in the fBm
|
||||
* offset: raises the terrain from `sea level'
|
||||
*/
|
||||
|
||||
void node_tex_musgrave_hybrid_multi_fractal_2d(vec3 co,
|
||||
float w,
|
||||
float scale,
|
||||
float detail,
|
||||
float dimension,
|
||||
float lac,
|
||||
float offset,
|
||||
float gain,
|
||||
out float fac)
|
||||
{
|
||||
vec2 p = co.xy * scale;
|
||||
float H = max(dimension, 1e-5);
|
||||
float octaves = clamp(detail, 0.0, 15.0);
|
||||
float lacunarity = max(lac, 1e-5);
|
||||
|
||||
float pwHL = pow(lacunarity, -H);
|
||||
|
||||
float pwr = 1.0;
|
||||
float value = 0.0;
|
||||
float weight = 1.0;
|
||||
|
||||
for (int i = 0; (weight > 0.001f) && (i < int(octaves)); i++) {
|
||||
if (weight > 1.0) {
|
||||
weight = 1.0;
|
||||
}
|
||||
|
||||
float signal = (snoise(p) + offset) * pwr;
|
||||
pwr *= pwHL;
|
||||
value += weight * signal;
|
||||
weight *= gain * signal;
|
||||
p *= lacunarity;
|
||||
}
|
||||
|
||||
float rmd = octaves - floor(octaves);
|
||||
if ((rmd != 0.0) && (weight > 0.001f)) {
|
||||
if (weight > 1.0) {
|
||||
weight = 1.0;
|
||||
}
|
||||
float signal = (snoise(p) + offset) * pwr;
|
||||
value += rmd * weight * signal;
|
||||
}
|
||||
|
||||
fac = value;
|
||||
}
|
||||
|
||||
/* 2D Ridged Multi-fractal Terrain
|
||||
*
|
||||
* H: fractal dimension of the roughest area
|
||||
* lacunarity: gap between successive frequencies
|
||||
* octaves: number of frequencies in the fBm
|
||||
* offset: raises the terrain from `sea level'
|
||||
*/
|
||||
|
||||
void node_tex_musgrave_ridged_multi_fractal_2d(vec3 co,
|
||||
float w,
|
||||
float scale,
|
||||
float detail,
|
||||
float dimension,
|
||||
float lac,
|
||||
float offset,
|
||||
float gain,
|
||||
out float fac)
|
||||
{
|
||||
vec2 p = co.xy * scale;
|
||||
float H = max(dimension, 1e-5);
|
||||
float octaves = clamp(detail, 0.0, 15.0);
|
||||
float lacunarity = max(lac, 1e-5);
|
||||
|
||||
float pwHL = pow(lacunarity, -H);
|
||||
float pwr = pwHL;
|
||||
|
||||
float signal = offset - abs(snoise(p));
|
||||
signal *= signal;
|
||||
float value = signal;
|
||||
float weight = 1.0;
|
||||
|
||||
for (int i = 1; i < int(octaves); i++) {
|
||||
p *= lacunarity;
|
||||
weight = clamp(signal * gain, 0.0, 1.0);
|
||||
signal = offset - abs(snoise(p));
|
||||
signal *= signal;
|
||||
signal *= weight;
|
||||
value += signal * pwr;
|
||||
pwr *= pwHL;
|
||||
}
|
||||
|
||||
fac = value;
|
||||
}
|
||||
|
||||
/* 3D Musgrave fBm
|
||||
*
|
||||
* H: fractal increment parameter
|
||||
* lacunarity: gap between successive frequencies
|
||||
* octaves: number of frequencies in the fBm
|
||||
*
|
||||
* from "Texturing and Modelling: A procedural approach"
|
||||
*/
|
||||
|
||||
void node_tex_musgrave_fBm_3d(vec3 co,
|
||||
float w,
|
||||
float scale,
|
||||
float detail,
|
||||
float dimension,
|
||||
float lac,
|
||||
float offset,
|
||||
float gain,
|
||||
out float fac)
|
||||
{
|
||||
vec3 p = co * scale;
|
||||
float H = max(dimension, 1e-5);
|
||||
float octaves = clamp(detail, 0.0, 15.0);
|
||||
float lacunarity = max(lac, 1e-5);
|
||||
|
||||
float value = 0.0;
|
||||
float pwr = 1.0;
|
||||
float pwHL = pow(lacunarity, -H);
|
||||
|
||||
for (int i = 0; i < int(octaves); i++) {
|
||||
value += snoise(p) * pwr;
|
||||
pwr *= pwHL;
|
||||
p *= lacunarity;
|
||||
}
|
||||
|
||||
float rmd = octaves - floor(octaves);
|
||||
if (rmd != 0.0) {
|
||||
value += rmd * snoise(p) * pwr;
|
||||
}
|
||||
|
||||
fac = value;
|
||||
}
|
||||
|
||||
/* 3D Musgrave Multi-fractal
|
||||
*
|
||||
* H: highest fractal dimension
|
||||
* lacunarity: gap between successive frequencies
|
||||
* octaves: number of frequencies in the fBm
|
||||
*/
|
||||
|
||||
void node_tex_musgrave_multi_fractal_3d(vec3 co,
|
||||
float w,
|
||||
float scale,
|
||||
float detail,
|
||||
float dimension,
|
||||
float lac,
|
||||
float offset,
|
||||
float gain,
|
||||
out float fac)
|
||||
{
|
||||
vec3 p = co * scale;
|
||||
float H = max(dimension, 1e-5);
|
||||
float octaves = clamp(detail, 0.0, 15.0);
|
||||
float lacunarity = max(lac, 1e-5);
|
||||
|
||||
float value = 1.0;
|
||||
float pwr = 1.0;
|
||||
float pwHL = pow(lacunarity, -H);
|
||||
|
||||
for (int i = 0; i < int(octaves); i++) {
|
||||
value *= (pwr * snoise(p) + 1.0);
|
||||
pwr *= pwHL;
|
||||
p *= lacunarity;
|
||||
}
|
||||
|
||||
float rmd = octaves - floor(octaves);
|
||||
if (rmd != 0.0) {
|
||||
value *= (rmd * pwr * snoise(p) + 1.0); /* correct? */
|
||||
}
|
||||
|
||||
fac = value;
|
||||
}
|
||||
|
||||
/* 3D Musgrave Heterogeneous Terrain
|
||||
*
|
||||
* H: fractal dimension of the roughest area
|
||||
* lacunarity: gap between successive frequencies
|
||||
* octaves: number of frequencies in the fBm
|
||||
* offset: raises the terrain from `sea level'
|
||||
*/
|
||||
|
||||
void node_tex_musgrave_hetero_terrain_3d(vec3 co,
|
||||
float w,
|
||||
float scale,
|
||||
float detail,
|
||||
float dimension,
|
||||
float lac,
|
||||
float offset,
|
||||
float gain,
|
||||
out float fac)
|
||||
{
|
||||
vec3 p = co * scale;
|
||||
float H = max(dimension, 1e-5);
|
||||
float octaves = clamp(detail, 0.0, 15.0);
|
||||
float lacunarity = max(lac, 1e-5);
|
||||
|
||||
float pwHL = pow(lacunarity, -H);
|
||||
float pwr = pwHL;
|
||||
|
||||
/* first unscaled octave of function; later octaves are scaled */
|
||||
float value = offset + snoise(p);
|
||||
p *= lacunarity;
|
||||
|
||||
for (int i = 1; i < int(octaves); i++) {
|
||||
float increment = (snoise(p) + offset) * pwr * value;
|
||||
value += increment;
|
||||
pwr *= pwHL;
|
||||
p *= lacunarity;
|
||||
}
|
||||
|
||||
float rmd = octaves - floor(octaves);
|
||||
if (rmd != 0.0) {
|
||||
float increment = (snoise(p) + offset) * pwr * value;
|
||||
value += rmd * increment;
|
||||
}
|
||||
|
||||
fac = value;
|
||||
}
|
||||
|
||||
/* 3D Hybrid Additive/Multiplicative Multi-fractal Terrain
|
||||
*
|
||||
* H: fractal dimension of the roughest area
|
||||
* lacunarity: gap between successive frequencies
|
||||
* octaves: number of frequencies in the fBm
|
||||
* offset: raises the terrain from `sea level'
|
||||
*/
|
||||
|
||||
void node_tex_musgrave_hybrid_multi_fractal_3d(vec3 co,
|
||||
float w,
|
||||
float scale,
|
||||
float detail,
|
||||
float dimension,
|
||||
float lac,
|
||||
float offset,
|
||||
float gain,
|
||||
out float fac)
|
||||
{
|
||||
vec3 p = co * scale;
|
||||
float H = max(dimension, 1e-5);
|
||||
float octaves = clamp(detail, 0.0, 15.0);
|
||||
float lacunarity = max(lac, 1e-5);
|
||||
|
||||
float pwHL = pow(lacunarity, -H);
|
||||
|
||||
float pwr = 1.0;
|
||||
float value = 0.0;
|
||||
float weight = 1.0;
|
||||
|
||||
for (int i = 0; (weight > 0.001f) && (i < int(octaves)); i++) {
|
||||
if (weight > 1.0) {
|
||||
weight = 1.0;
|
||||
}
|
||||
|
||||
float signal = (snoise(p) + offset) * pwr;
|
||||
pwr *= pwHL;
|
||||
value += weight * signal;
|
||||
weight *= gain * signal;
|
||||
p *= lacunarity;
|
||||
}
|
||||
|
||||
float rmd = octaves - floor(octaves);
|
||||
if ((rmd != 0.0) && (weight > 0.001f)) {
|
||||
if (weight > 1.0) {
|
||||
weight = 1.0;
|
||||
}
|
||||
float signal = (snoise(p) + offset) * pwr;
|
||||
value += rmd * weight * signal;
|
||||
}
|
||||
|
||||
fac = value;
|
||||
}
|
||||
|
||||
/* 3D Ridged Multi-fractal Terrain
|
||||
*
|
||||
* H: fractal dimension of the roughest area
|
||||
* lacunarity: gap between successive frequencies
|
||||
* octaves: number of frequencies in the fBm
|
||||
* offset: raises the terrain from `sea level'
|
||||
*/
|
||||
|
||||
void node_tex_musgrave_ridged_multi_fractal_3d(vec3 co,
|
||||
float w,
|
||||
float scale,
|
||||
float detail,
|
||||
float dimension,
|
||||
float lac,
|
||||
float offset,
|
||||
float gain,
|
||||
out float fac)
|
||||
{
|
||||
vec3 p = co * scale;
|
||||
float H = max(dimension, 1e-5);
|
||||
float octaves = clamp(detail, 0.0, 15.0);
|
||||
float lacunarity = max(lac, 1e-5);
|
||||
|
||||
float pwHL = pow(lacunarity, -H);
|
||||
float pwr = pwHL;
|
||||
|
||||
float signal = offset - abs(snoise(p));
|
||||
signal *= signal;
|
||||
float value = signal;
|
||||
float weight = 1.0;
|
||||
|
||||
for (int i = 1; i < int(octaves); i++) {
|
||||
p *= lacunarity;
|
||||
weight = clamp(signal * gain, 0.0, 1.0);
|
||||
signal = offset - abs(snoise(p));
|
||||
signal *= signal;
|
||||
signal *= weight;
|
||||
value += signal * pwr;
|
||||
pwr *= pwHL;
|
||||
}
|
||||
|
||||
fac = value;
|
||||
}
|
||||
|
||||
/* 4D Musgrave fBm
|
||||
*
|
||||
* H: fractal increment parameter
|
||||
* lacunarity: gap between successive frequencies
|
||||
* octaves: number of frequencies in the fBm
|
||||
*
|
||||
* from "Texturing and Modelling: A procedural approach"
|
||||
*/
|
||||
|
||||
void node_tex_musgrave_fBm_4d(vec3 co,
|
||||
float w,
|
||||
float scale,
|
||||
float detail,
|
||||
float dimension,
|
||||
float lac,
|
||||
float offset,
|
||||
float gain,
|
||||
out float fac)
|
||||
{
|
||||
vec4 p = vec4(co, w) * scale;
|
||||
float H = max(dimension, 1e-5);
|
||||
float octaves = clamp(detail, 0.0, 15.0);
|
||||
float lacunarity = max(lac, 1e-5);
|
||||
|
||||
float value = 0.0;
|
||||
float pwr = 1.0;
|
||||
float pwHL = pow(lacunarity, -H);
|
||||
|
||||
for (int i = 0; i < int(octaves); i++) {
|
||||
value += snoise(p) * pwr;
|
||||
pwr *= pwHL;
|
||||
p *= lacunarity;
|
||||
}
|
||||
|
||||
float rmd = octaves - floor(octaves);
|
||||
if (rmd != 0.0) {
|
||||
value += rmd * snoise(p) * pwr;
|
||||
}
|
||||
|
||||
fac = value;
|
||||
}
|
||||
|
||||
/* 4D Musgrave Multi-fractal
|
||||
*
|
||||
* H: highest fractal dimension
|
||||
* lacunarity: gap between successive frequencies
|
||||
* octaves: number of frequencies in the fBm
|
||||
*/
|
||||
|
||||
void node_tex_musgrave_multi_fractal_4d(vec3 co,
|
||||
float w,
|
||||
float scale,
|
||||
float detail,
|
||||
float dimension,
|
||||
float lac,
|
||||
float offset,
|
||||
float gain,
|
||||
out float fac)
|
||||
{
|
||||
vec4 p = vec4(co, w) * scale;
|
||||
float H = max(dimension, 1e-5);
|
||||
float octaves = clamp(detail, 0.0, 15.0);
|
||||
float lacunarity = max(lac, 1e-5);
|
||||
|
||||
float value = 1.0;
|
||||
float pwr = 1.0;
|
||||
float pwHL = pow(lacunarity, -H);
|
||||
|
||||
for (int i = 0; i < int(octaves); i++) {
|
||||
value *= (pwr * snoise(p) + 1.0);
|
||||
pwr *= pwHL;
|
||||
p *= lacunarity;
|
||||
}
|
||||
|
||||
float rmd = octaves - floor(octaves);
|
||||
if (rmd != 0.0) {
|
||||
value *= (rmd * pwr * snoise(p) + 1.0); /* correct? */
|
||||
}
|
||||
|
||||
fac = value;
|
||||
}
|
||||
|
||||
/* 4D Musgrave Heterogeneous Terrain
|
||||
*
|
||||
* H: fractal dimension of the roughest area
|
||||
* lacunarity: gap between successive frequencies
|
||||
* octaves: number of frequencies in the fBm
|
||||
* offset: raises the terrain from `sea level'
|
||||
*/
|
||||
|
||||
void node_tex_musgrave_hetero_terrain_4d(vec3 co,
|
||||
float w,
|
||||
float scale,
|
||||
float detail,
|
||||
float dimension,
|
||||
float lac,
|
||||
float offset,
|
||||
float gain,
|
||||
out float fac)
|
||||
{
|
||||
vec4 p = vec4(co, w) * scale;
|
||||
float H = max(dimension, 1e-5);
|
||||
float octaves = clamp(detail, 0.0, 15.0);
|
||||
float lacunarity = max(lac, 1e-5);
|
||||
|
||||
float pwHL = pow(lacunarity, -H);
|
||||
float pwr = pwHL;
|
||||
|
||||
/* first unscaled octave of function; later octaves are scaled */
|
||||
float value = offset + snoise(p);
|
||||
p *= lacunarity;
|
||||
|
||||
for (int i = 1; i < int(octaves); i++) {
|
||||
float increment = (snoise(p) + offset) * pwr * value;
|
||||
value += increment;
|
||||
pwr *= pwHL;
|
||||
p *= lacunarity;
|
||||
}
|
||||
|
||||
float rmd = octaves - floor(octaves);
|
||||
if (rmd != 0.0) {
|
||||
float increment = (snoise(p) + offset) * pwr * value;
|
||||
value += rmd * increment;
|
||||
}
|
||||
|
||||
fac = value;
|
||||
}
|
||||
|
||||
/* 4D Hybrid Additive/Multiplicative Multi-fractal Terrain
|
||||
*
|
||||
* H: fractal dimension of the roughest area
|
||||
* lacunarity: gap between successive frequencies
|
||||
* octaves: number of frequencies in the fBm
|
||||
* offset: raises the terrain from `sea level'
|
||||
*/
|
||||
|
||||
void node_tex_musgrave_hybrid_multi_fractal_4d(vec3 co,
|
||||
float w,
|
||||
float scale,
|
||||
float detail,
|
||||
float dimension,
|
||||
float lac,
|
||||
float offset,
|
||||
float gain,
|
||||
out float fac)
|
||||
{
|
||||
vec4 p = vec4(co, w) * scale;
|
||||
float H = max(dimension, 1e-5);
|
||||
float octaves = clamp(detail, 0.0, 15.0);
|
||||
float lacunarity = max(lac, 1e-5);
|
||||
|
||||
float pwHL = pow(lacunarity, -H);
|
||||
|
||||
float pwr = 1.0;
|
||||
float value = 0.0;
|
||||
float weight = 1.0;
|
||||
|
||||
for (int i = 0; (weight > 0.001f) && (i < int(octaves)); i++) {
|
||||
if (weight > 1.0) {
|
||||
weight = 1.0;
|
||||
}
|
||||
|
||||
float signal = (snoise(p) + offset) * pwr;
|
||||
pwr *= pwHL;
|
||||
value += weight * signal;
|
||||
weight *= gain * signal;
|
||||
p *= lacunarity;
|
||||
}
|
||||
|
||||
float rmd = octaves - floor(octaves);
|
||||
if ((rmd != 0.0) && (weight > 0.001f)) {
|
||||
if (weight > 1.0) {
|
||||
weight = 1.0;
|
||||
}
|
||||
float signal = (snoise(p) + offset) * pwr;
|
||||
value += rmd * weight * signal;
|
||||
}
|
||||
|
||||
fac = value;
|
||||
}
|
||||
|
||||
/* 4D Ridged Multi-fractal Terrain
|
||||
*
|
||||
* H: fractal dimension of the roughest area
|
||||
* lacunarity: gap between successive frequencies
|
||||
* octaves: number of frequencies in the fBm
|
||||
* offset: raises the terrain from `sea level'
|
||||
*/
|
||||
|
||||
void node_tex_musgrave_ridged_multi_fractal_4d(vec3 co,
|
||||
float w,
|
||||
float scale,
|
||||
float detail,
|
||||
float dimension,
|
||||
float lac,
|
||||
float offset,
|
||||
float gain,
|
||||
out float fac)
|
||||
{
|
||||
vec4 p = vec4(co, w) * scale;
|
||||
float H = max(dimension, 1e-5);
|
||||
float octaves = clamp(detail, 0.0, 15.0);
|
||||
float lacunarity = max(lac, 1e-5);
|
||||
|
||||
float pwHL = pow(lacunarity, -H);
|
||||
float pwr = pwHL;
|
||||
|
||||
float signal = offset - abs(snoise(p));
|
||||
signal *= signal;
|
||||
float value = signal;
|
||||
float weight = 1.0;
|
||||
|
||||
for (int i = 1; i < int(octaves); i++) {
|
||||
p *= lacunarity;
|
||||
weight = clamp(signal * gain, 0.0, 1.0);
|
||||
signal = offset - abs(snoise(p));
|
||||
signal *= signal;
|
||||
signal *= weight;
|
||||
value += signal * pwr;
|
||||
pwr *= pwHL;
|
||||
}
|
||||
|
||||
fac = value;
|
||||
}
|
||||
@@ -14,6 +14,104 @@
|
||||
#pragma BLENDER_REQUIRE(gpu_shader_material_noise.glsl)
|
||||
#pragma BLENDER_REQUIRE(gpu_shader_material_fractal_noise.glsl)
|
||||
|
||||
#define NOISE_FRACTAL_DISTORTED_1D(NOISE_TYPE) \
|
||||
if (distortion != 0.0) { \
|
||||
p += snoise(p + random_float_offset(0.0)) * distortion; \
|
||||
} \
|
||||
\
|
||||
value = NOISE_TYPE(p, detail, roughness, lacunarity, offset, gain, normalize != 0.0); \
|
||||
color = vec4(value, \
|
||||
NOISE_TYPE(p + random_float_offset(1.0), \
|
||||
detail, \
|
||||
roughness, \
|
||||
lacunarity, \
|
||||
offset, \
|
||||
gain, \
|
||||
normalize != 0.0), \
|
||||
NOISE_TYPE(p + random_float_offset(2.0), \
|
||||
detail, \
|
||||
roughness, \
|
||||
lacunarity, \
|
||||
offset, \
|
||||
gain, \
|
||||
normalize != 0.0), \
|
||||
1.0);
|
||||
|
||||
#define NOISE_FRACTAL_DISTORTED_2D(NOISE_TYPE) \
|
||||
if (distortion != 0.0) { \
|
||||
p += vec2(snoise(p + random_vec2_offset(0.0)) * distortion, \
|
||||
snoise(p + random_vec2_offset(1.0)) * distortion); \
|
||||
} \
|
||||
\
|
||||
value = NOISE_TYPE(p, detail, roughness, lacunarity, offset, gain, normalize != 0.0); \
|
||||
color = vec4(value, \
|
||||
NOISE_TYPE(p + random_vec2_offset(2.0), \
|
||||
detail, \
|
||||
roughness, \
|
||||
lacunarity, \
|
||||
offset, \
|
||||
gain, \
|
||||
normalize != 0.0), \
|
||||
NOISE_TYPE(p + random_vec2_offset(3.0), \
|
||||
detail, \
|
||||
roughness, \
|
||||
lacunarity, \
|
||||
offset, \
|
||||
gain, \
|
||||
normalize != 0.0), \
|
||||
1.0);
|
||||
|
||||
#define NOISE_FRACTAL_DISTORTED_3D(NOISE_TYPE) \
|
||||
if (distortion != 0.0) { \
|
||||
p += vec3(snoise(p + random_vec3_offset(0.0)) * distortion, \
|
||||
snoise(p + random_vec3_offset(1.0)) * distortion, \
|
||||
snoise(p + random_vec3_offset(2.0)) * distortion); \
|
||||
} \
|
||||
\
|
||||
value = NOISE_TYPE(p, detail, roughness, lacunarity, offset, gain, normalize != 0.0); \
|
||||
color = vec4(value, \
|
||||
NOISE_TYPE(p + random_vec3_offset(3.0), \
|
||||
detail, \
|
||||
roughness, \
|
||||
lacunarity, \
|
||||
offset, \
|
||||
gain, \
|
||||
normalize != 0.0), \
|
||||
NOISE_TYPE(p + random_vec3_offset(4.0), \
|
||||
detail, \
|
||||
roughness, \
|
||||
lacunarity, \
|
||||
offset, \
|
||||
gain, \
|
||||
normalize != 0.0), \
|
||||
1.0);
|
||||
|
||||
#define NOISE_FRACTAL_DISTORTED_4D(NOISE_TYPE) \
|
||||
if (distortion != 0.0) { \
|
||||
p += vec4(snoise(p + random_vec4_offset(0.0)) * distortion, \
|
||||
snoise(p + random_vec4_offset(1.0)) * distortion, \
|
||||
snoise(p + random_vec4_offset(2.0)) * distortion, \
|
||||
snoise(p + random_vec4_offset(3.0)) * distortion); \
|
||||
} \
|
||||
\
|
||||
value = NOISE_TYPE(p, detail, roughness, lacunarity, offset, gain, normalize != 0.0); \
|
||||
color = vec4(value, \
|
||||
NOISE_TYPE(p + random_vec4_offset(4.0), \
|
||||
detail, \
|
||||
roughness, \
|
||||
lacunarity, \
|
||||
offset, \
|
||||
gain, \
|
||||
normalize != 0.0), \
|
||||
NOISE_TYPE(p + random_vec4_offset(5.0), \
|
||||
detail, \
|
||||
roughness, \
|
||||
lacunarity, \
|
||||
offset, \
|
||||
gain, \
|
||||
normalize != 0.0), \
|
||||
1.0);
|
||||
|
||||
float random_float_offset(float seed)
|
||||
{
|
||||
return 100.0 + hash_float_to_float(seed) * 100.0;
|
||||
@@ -40,104 +138,432 @@ vec4 random_vec4_offset(float seed)
|
||||
100.0 + hash_vec2_to_float(vec2(seed, 3.0)) * 100.0);
|
||||
}
|
||||
|
||||
void node_noise_texture_1d(vec3 co,
|
||||
/* Noise fBM */
|
||||
|
||||
void node_noise_tex_fbm_1d(vec3 co,
|
||||
float w,
|
||||
float scale,
|
||||
float detail,
|
||||
float roughness,
|
||||
float lacunarity,
|
||||
float offset,
|
||||
float gain,
|
||||
float distortion,
|
||||
float normalize,
|
||||
out float value,
|
||||
out vec4 color)
|
||||
{
|
||||
detail = clamp(detail, 0.0, 15.0);
|
||||
roughness = max(roughness, 0.0);
|
||||
|
||||
float p = w * scale;
|
||||
if (distortion != 0.0) {
|
||||
p += snoise(p + random_float_offset(0.0)) * distortion;
|
||||
}
|
||||
|
||||
value = fractal_noise(p, detail, roughness, lacunarity, normalize != 0.0);
|
||||
color = vec4(
|
||||
value,
|
||||
fractal_noise(p + random_float_offset(1.0), detail, roughness, lacunarity, normalize != 0.0),
|
||||
fractal_noise(p + random_float_offset(2.0), detail, roughness, lacunarity, normalize != 0.0),
|
||||
1.0);
|
||||
NOISE_FRACTAL_DISTORTED_1D(noise_fbm)
|
||||
}
|
||||
|
||||
void node_noise_texture_2d(vec3 co,
|
||||
void node_noise_tex_fbm_2d(vec3 co,
|
||||
float w,
|
||||
float scale,
|
||||
float detail,
|
||||
float roughness,
|
||||
float lacunarity,
|
||||
float offset,
|
||||
float gain,
|
||||
float distortion,
|
||||
float normalize,
|
||||
out float value,
|
||||
out vec4 color)
|
||||
{
|
||||
detail = clamp(detail, 0.0, 15.0);
|
||||
roughness = max(roughness, 0.0);
|
||||
|
||||
vec2 p = co.xy * scale;
|
||||
if (distortion != 0.0) {
|
||||
p += vec2(snoise(p + random_vec2_offset(0.0)) * distortion,
|
||||
snoise(p + random_vec2_offset(1.0)) * distortion);
|
||||
}
|
||||
|
||||
value = fractal_noise(p, detail, roughness, lacunarity, normalize != 0.0);
|
||||
color = vec4(
|
||||
value,
|
||||
fractal_noise(p + random_vec2_offset(2.0), detail, roughness, lacunarity, normalize != 0.0),
|
||||
fractal_noise(p + random_vec2_offset(3.0), detail, roughness, lacunarity, normalize != 0.0),
|
||||
1.0);
|
||||
NOISE_FRACTAL_DISTORTED_2D(noise_fbm)
|
||||
}
|
||||
|
||||
void node_noise_texture_3d(vec3 co,
|
||||
void node_noise_tex_fbm_3d(vec3 co,
|
||||
float w,
|
||||
float scale,
|
||||
float detail,
|
||||
float roughness,
|
||||
float lacunarity,
|
||||
float offset,
|
||||
float gain,
|
||||
float distortion,
|
||||
float normalize,
|
||||
out float value,
|
||||
out vec4 color)
|
||||
{
|
||||
detail = clamp(detail, 0.0, 15.0);
|
||||
roughness = max(roughness, 0.0);
|
||||
|
||||
vec3 p = co * scale;
|
||||
if (distortion != 0.0) {
|
||||
p += vec3(snoise(p + random_vec3_offset(0.0)) * distortion,
|
||||
snoise(p + random_vec3_offset(1.0)) * distortion,
|
||||
snoise(p + random_vec3_offset(2.0)) * distortion);
|
||||
}
|
||||
|
||||
value = fractal_noise(p, detail, roughness, lacunarity, normalize != 0.0);
|
||||
color = vec4(
|
||||
value,
|
||||
fractal_noise(p + random_vec3_offset(3.0), detail, roughness, lacunarity, normalize != 0.0),
|
||||
fractal_noise(p + random_vec3_offset(4.0), detail, roughness, lacunarity, normalize != 0.0),
|
||||
1.0);
|
||||
NOISE_FRACTAL_DISTORTED_3D(noise_fbm)
|
||||
}
|
||||
|
||||
void node_noise_texture_4d(vec3 co,
|
||||
void node_noise_tex_fbm_4d(vec3 co,
|
||||
float w,
|
||||
float scale,
|
||||
float detail,
|
||||
float roughness,
|
||||
float lacunarity,
|
||||
float offset,
|
||||
float gain,
|
||||
float distortion,
|
||||
float normalize,
|
||||
out float value,
|
||||
out vec4 color)
|
||||
{
|
||||
vec4 p = vec4(co, w) * scale;
|
||||
if (distortion != 0.0) {
|
||||
p += vec4(snoise(p + random_vec4_offset(0.0)) * distortion,
|
||||
snoise(p + random_vec4_offset(1.0)) * distortion,
|
||||
snoise(p + random_vec4_offset(2.0)) * distortion,
|
||||
snoise(p + random_vec4_offset(3.0)) * distortion);
|
||||
}
|
||||
detail = clamp(detail, 0.0, 15.0);
|
||||
roughness = max(roughness, 0.0);
|
||||
|
||||
value = fractal_noise(p, detail, roughness, lacunarity, normalize != 0.0);
|
||||
color = vec4(
|
||||
value,
|
||||
fractal_noise(p + random_vec4_offset(4.0), detail, roughness, lacunarity, normalize != 0.0),
|
||||
fractal_noise(p + random_vec4_offset(5.0), detail, roughness, lacunarity, normalize != 0.0),
|
||||
1.0);
|
||||
vec4 p = vec4(co, w) * scale;
|
||||
|
||||
NOISE_FRACTAL_DISTORTED_4D(noise_fbm)
|
||||
}
|
||||
|
||||
/* Noise Multifractal */
|
||||
|
||||
void node_noise_tex_multi_fractal_1d(vec3 co,
|
||||
float w,
|
||||
float scale,
|
||||
float detail,
|
||||
float roughness,
|
||||
float lacunarity,
|
||||
float offset,
|
||||
float gain,
|
||||
float distortion,
|
||||
float normalize,
|
||||
out float value,
|
||||
out vec4 color)
|
||||
{
|
||||
detail = clamp(detail, 0.0, 15.0);
|
||||
roughness = max(roughness, 0.0);
|
||||
|
||||
float p = w * scale;
|
||||
|
||||
NOISE_FRACTAL_DISTORTED_1D(noise_multi_fractal)
|
||||
}
|
||||
|
||||
void node_noise_tex_multi_fractal_2d(vec3 co,
|
||||
float w,
|
||||
float scale,
|
||||
float detail,
|
||||
float roughness,
|
||||
float lacunarity,
|
||||
float offset,
|
||||
float gain,
|
||||
float distortion,
|
||||
float normalize,
|
||||
out float value,
|
||||
out vec4 color)
|
||||
{
|
||||
detail = clamp(detail, 0.0, 15.0);
|
||||
roughness = max(roughness, 0.0);
|
||||
|
||||
vec2 p = co.xy * scale;
|
||||
|
||||
NOISE_FRACTAL_DISTORTED_2D(noise_multi_fractal)
|
||||
}
|
||||
|
||||
void node_noise_tex_multi_fractal_3d(vec3 co,
|
||||
float w,
|
||||
float scale,
|
||||
float detail,
|
||||
float roughness,
|
||||
float lacunarity,
|
||||
float offset,
|
||||
float gain,
|
||||
float distortion,
|
||||
float normalize,
|
||||
out float value,
|
||||
out vec4 color)
|
||||
{
|
||||
detail = clamp(detail, 0.0, 15.0);
|
||||
roughness = max(roughness, 0.0);
|
||||
|
||||
vec3 p = co * scale;
|
||||
|
||||
NOISE_FRACTAL_DISTORTED_3D(noise_multi_fractal)
|
||||
}
|
||||
|
||||
void node_noise_tex_multi_fractal_4d(vec3 co,
|
||||
float w,
|
||||
float scale,
|
||||
float detail,
|
||||
float roughness,
|
||||
float lacunarity,
|
||||
float offset,
|
||||
float gain,
|
||||
float distortion,
|
||||
float normalize,
|
||||
out float value,
|
||||
out vec4 color)
|
||||
{
|
||||
detail = clamp(detail, 0.0, 15.0);
|
||||
roughness = max(roughness, 0.0);
|
||||
|
||||
vec4 p = vec4(co, w) * scale;
|
||||
|
||||
NOISE_FRACTAL_DISTORTED_4D(noise_multi_fractal)
|
||||
}
|
||||
|
||||
/* Noise Hetero Terrain */
|
||||
|
||||
void node_noise_tex_hetero_terrain_1d(vec3 co,
|
||||
float w,
|
||||
float scale,
|
||||
float detail,
|
||||
float roughness,
|
||||
float lacunarity,
|
||||
float offset,
|
||||
float gain,
|
||||
float distortion,
|
||||
float normalize,
|
||||
out float value,
|
||||
out vec4 color)
|
||||
{
|
||||
detail = clamp(detail, 0.0, 15.0);
|
||||
roughness = max(roughness, 0.0);
|
||||
|
||||
float p = w * scale;
|
||||
|
||||
NOISE_FRACTAL_DISTORTED_1D(noise_hetero_terrain)
|
||||
}
|
||||
|
||||
void node_noise_tex_hetero_terrain_2d(vec3 co,
|
||||
float w,
|
||||
float scale,
|
||||
float detail,
|
||||
float roughness,
|
||||
float lacunarity,
|
||||
float offset,
|
||||
float gain,
|
||||
float distortion,
|
||||
float normalize,
|
||||
out float value,
|
||||
out vec4 color)
|
||||
{
|
||||
detail = clamp(detail, 0.0, 15.0);
|
||||
roughness = max(roughness, 0.0);
|
||||
|
||||
vec2 p = co.xy * scale;
|
||||
|
||||
NOISE_FRACTAL_DISTORTED_2D(noise_hetero_terrain)
|
||||
}
|
||||
|
||||
void node_noise_tex_hetero_terrain_3d(vec3 co,
|
||||
float w,
|
||||
float scale,
|
||||
float detail,
|
||||
float roughness,
|
||||
float lacunarity,
|
||||
float offset,
|
||||
float gain,
|
||||
float distortion,
|
||||
float normalize,
|
||||
out float value,
|
||||
out vec4 color)
|
||||
{
|
||||
detail = clamp(detail, 0.0, 15.0);
|
||||
roughness = max(roughness, 0.0);
|
||||
|
||||
vec3 p = co * scale;
|
||||
|
||||
NOISE_FRACTAL_DISTORTED_3D(noise_hetero_terrain)
|
||||
}
|
||||
|
||||
void node_noise_tex_hetero_terrain_4d(vec3 co,
|
||||
float w,
|
||||
float scale,
|
||||
float detail,
|
||||
float roughness,
|
||||
float lacunarity,
|
||||
float offset,
|
||||
float gain,
|
||||
float distortion,
|
||||
float normalize,
|
||||
out float value,
|
||||
out vec4 color)
|
||||
{
|
||||
detail = clamp(detail, 0.0, 15.0);
|
||||
roughness = max(roughness, 0.0);
|
||||
|
||||
vec4 p = vec4(co, w) * scale;
|
||||
|
||||
NOISE_FRACTAL_DISTORTED_4D(noise_hetero_terrain)
|
||||
}
|
||||
|
||||
/* Noise Hybrid Multifractal */
|
||||
|
||||
void node_noise_tex_hybrid_multi_fractal_1d(vec3 co,
|
||||
float w,
|
||||
float scale,
|
||||
float detail,
|
||||
float roughness,
|
||||
float lacunarity,
|
||||
float offset,
|
||||
float gain,
|
||||
float distortion,
|
||||
float normalize,
|
||||
out float value,
|
||||
out vec4 color)
|
||||
{
|
||||
detail = clamp(detail, 0.0, 15.0);
|
||||
roughness = max(roughness, 0.0);
|
||||
|
||||
float p = w * scale;
|
||||
|
||||
NOISE_FRACTAL_DISTORTED_1D(noise_hybrid_multi_fractal)
|
||||
}
|
||||
|
||||
void node_noise_tex_hybrid_multi_fractal_2d(vec3 co,
|
||||
float w,
|
||||
float scale,
|
||||
float detail,
|
||||
float roughness,
|
||||
float lacunarity,
|
||||
float offset,
|
||||
float gain,
|
||||
float distortion,
|
||||
float normalize,
|
||||
out float value,
|
||||
out vec4 color)
|
||||
{
|
||||
detail = clamp(detail, 0.0, 15.0);
|
||||
roughness = max(roughness, 0.0);
|
||||
|
||||
vec2 p = co.xy * scale;
|
||||
|
||||
NOISE_FRACTAL_DISTORTED_2D(noise_hybrid_multi_fractal)
|
||||
}
|
||||
|
||||
void node_noise_tex_hybrid_multi_fractal_3d(vec3 co,
|
||||
float w,
|
||||
float scale,
|
||||
float detail,
|
||||
float roughness,
|
||||
float lacunarity,
|
||||
float offset,
|
||||
float gain,
|
||||
float distortion,
|
||||
float normalize,
|
||||
out float value,
|
||||
out vec4 color)
|
||||
{
|
||||
detail = clamp(detail, 0.0, 15.0);
|
||||
roughness = max(roughness, 0.0);
|
||||
|
||||
vec3 p = co * scale;
|
||||
|
||||
NOISE_FRACTAL_DISTORTED_3D(noise_hybrid_multi_fractal)
|
||||
}
|
||||
|
||||
void node_noise_tex_hybrid_multi_fractal_4d(vec3 co,
|
||||
float w,
|
||||
float scale,
|
||||
float detail,
|
||||
float roughness,
|
||||
float lacunarity,
|
||||
float offset,
|
||||
float gain,
|
||||
float distortion,
|
||||
float normalize,
|
||||
out float value,
|
||||
out vec4 color)
|
||||
{
|
||||
detail = clamp(detail, 0.0, 15.0);
|
||||
roughness = max(roughness, 0.0);
|
||||
|
||||
vec4 p = vec4(co, w) * scale;
|
||||
|
||||
NOISE_FRACTAL_DISTORTED_4D(noise_hybrid_multi_fractal)
|
||||
}
|
||||
|
||||
/* Noise Ridged Multifractal */
|
||||
|
||||
void node_noise_tex_ridged_multi_fractal_1d(vec3 co,
|
||||
float w,
|
||||
float scale,
|
||||
float detail,
|
||||
float roughness,
|
||||
float lacunarity,
|
||||
float offset,
|
||||
float gain,
|
||||
float distortion,
|
||||
float normalize,
|
||||
out float value,
|
||||
out vec4 color)
|
||||
{
|
||||
detail = clamp(detail, 0.0, 15.0);
|
||||
roughness = max(roughness, 0.0);
|
||||
|
||||
float p = w * scale;
|
||||
|
||||
NOISE_FRACTAL_DISTORTED_1D(noise_ridged_multi_fractal)
|
||||
}
|
||||
|
||||
void node_noise_tex_ridged_multi_fractal_2d(vec3 co,
|
||||
float w,
|
||||
float scale,
|
||||
float detail,
|
||||
float roughness,
|
||||
float lacunarity,
|
||||
float offset,
|
||||
float gain,
|
||||
float distortion,
|
||||
float normalize,
|
||||
out float value,
|
||||
out vec4 color)
|
||||
{
|
||||
detail = clamp(detail, 0.0, 15.0);
|
||||
roughness = max(roughness, 0.0);
|
||||
|
||||
vec2 p = co.xy * scale;
|
||||
|
||||
NOISE_FRACTAL_DISTORTED_2D(noise_ridged_multi_fractal)
|
||||
}
|
||||
|
||||
void node_noise_tex_ridged_multi_fractal_3d(vec3 co,
|
||||
float w,
|
||||
float scale,
|
||||
float detail,
|
||||
float roughness,
|
||||
float lacunarity,
|
||||
float offset,
|
||||
float gain,
|
||||
float distortion,
|
||||
float normalize,
|
||||
out float value,
|
||||
out vec4 color)
|
||||
{
|
||||
detail = clamp(detail, 0.0, 15.0);
|
||||
roughness = max(roughness, 0.0);
|
||||
|
||||
vec3 p = co * scale;
|
||||
|
||||
NOISE_FRACTAL_DISTORTED_3D(noise_ridged_multi_fractal)
|
||||
}
|
||||
|
||||
void node_noise_tex_ridged_multi_fractal_4d(vec3 co,
|
||||
float w,
|
||||
float scale,
|
||||
float detail,
|
||||
float roughness,
|
||||
float lacunarity,
|
||||
float offset,
|
||||
float gain,
|
||||
float distortion,
|
||||
float normalize,
|
||||
out float value,
|
||||
out vec4 color)
|
||||
{
|
||||
detail = clamp(detail, 0.0, 15.0);
|
||||
roughness = max(roughness, 0.0);
|
||||
|
||||
vec4 p = vec4(co, w) * scale;
|
||||
|
||||
NOISE_FRACTAL_DISTORTED_4D(noise_ridged_multi_fractal)
|
||||
}
|
||||
|
||||
@@ -56,7 +56,7 @@ float calc_wave(vec3 p,
|
||||
|
||||
if (distortion != 0.0) {
|
||||
n += distortion *
|
||||
(fractal_noise(p * detail_scale, detail, detail_roughness, 2.0, true) * 2.0 - 1.0);
|
||||
(noise_fbm(p * detail_scale, detail, detail_roughness, 2.0, 0.0, 0.0, true) * 2.0 - 1.0);
|
||||
}
|
||||
|
||||
if (wave_profile == 0) { /* profile sin */
|
||||
|
||||
@@ -1282,8 +1282,9 @@ typedef struct NodeTexGradient {
|
||||
typedef struct NodeTexNoise {
|
||||
NodeTexBase base;
|
||||
int dimensions;
|
||||
uint8_t type;
|
||||
uint8_t normalize;
|
||||
char _pad[3];
|
||||
char _pad[2];
|
||||
} NodeTexNoise;
|
||||
|
||||
typedef struct NodeTexVoronoi {
|
||||
@@ -1297,9 +1298,9 @@ typedef struct NodeTexVoronoi {
|
||||
} NodeTexVoronoi;
|
||||
|
||||
typedef struct NodeTexMusgrave {
|
||||
NodeTexBase base;
|
||||
int musgrave_type;
|
||||
int dimensions;
|
||||
NodeTexBase base DNA_DEPRECATED;
|
||||
int musgrave_type DNA_DEPRECATED;
|
||||
int dimensions DNA_DEPRECATED;
|
||||
} NodeTexMusgrave;
|
||||
|
||||
typedef struct NodeTexWave {
|
||||
@@ -2039,7 +2040,7 @@ enum {
|
||||
SHD_VORONOI_N_SPHERE_RADIUS = 4,
|
||||
};
|
||||
|
||||
/* musgrave texture */
|
||||
/* Deprecated Musgrave Texture. Keep for Versioning */
|
||||
enum {
|
||||
SHD_MUSGRAVE_MULTIFRACTAL = 0,
|
||||
SHD_MUSGRAVE_FBM = 1,
|
||||
@@ -2048,6 +2049,15 @@ enum {
|
||||
SHD_MUSGRAVE_HETERO_TERRAIN = 4,
|
||||
};
|
||||
|
||||
/* Noise Texture */
|
||||
enum {
|
||||
SHD_NOISE_MULTIFRACTAL = 0,
|
||||
SHD_NOISE_FBM = 1,
|
||||
SHD_NOISE_HYBRID_MULTIFRACTAL = 2,
|
||||
SHD_NOISE_RIDGED_MULTIFRACTAL = 3,
|
||||
SHD_NOISE_HETERO_TERRAIN = 4,
|
||||
};
|
||||
|
||||
/* wave texture */
|
||||
enum {
|
||||
SHD_WAVE_BANDS = 0,
|
||||
|
||||
@@ -4864,6 +4864,32 @@ static void def_sh_tex_gradient(StructRNA *srna)
|
||||
|
||||
static void def_sh_tex_noise(StructRNA *srna)
|
||||
{
|
||||
static const EnumPropertyItem prop_noise_type[] = {
|
||||
{SHD_NOISE_MULTIFRACTAL,
|
||||
"MULTIFRACTAL",
|
||||
0,
|
||||
"Multifractal",
|
||||
"More uneven result (varies with location), more similar to a real terrain"},
|
||||
{SHD_NOISE_RIDGED_MULTIFRACTAL,
|
||||
"RIDGED_MULTIFRACTAL",
|
||||
0,
|
||||
"Ridged Multifractal",
|
||||
"Create sharp peaks"},
|
||||
{SHD_NOISE_HYBRID_MULTIFRACTAL,
|
||||
"HYBRID_MULTIFRACTAL",
|
||||
0,
|
||||
"Hybrid Multifractal",
|
||||
"Create peaks and valleys with different roughness values"},
|
||||
{SHD_NOISE_FBM, "FBM", 0, "fBM", "The standard fractal Perlin noise"},
|
||||
{SHD_NOISE_HETERO_TERRAIN,
|
||||
"HETERO_TERRAIN",
|
||||
0,
|
||||
"Hetero Terrain",
|
||||
"Similar to Hybrid Multifractal creates a heterogeneous terrain, but with the likeness of "
|
||||
"river channels"},
|
||||
{0, nullptr, 0, nullptr, nullptr},
|
||||
};
|
||||
|
||||
PropertyRNA *prop;
|
||||
|
||||
RNA_def_struct_sdna_from(srna, "NodeTexNoise", "storage");
|
||||
@@ -4875,6 +4901,12 @@ static void def_sh_tex_noise(StructRNA *srna)
|
||||
RNA_def_property_ui_text(prop, "Dimensions", "Number of dimensions to output noise for");
|
||||
RNA_def_property_update(prop, 0, "rna_ShaderNode_socket_update");
|
||||
|
||||
prop = RNA_def_property(srna, "type", PROP_ENUM, PROP_NONE);
|
||||
RNA_def_property_enum_sdna(prop, nullptr, "type");
|
||||
RNA_def_property_enum_items(prop, prop_noise_type);
|
||||
RNA_def_property_ui_text(prop, "Type", "Type of the Noise texture");
|
||||
RNA_def_property_update(prop, 0, "rna_ShaderNode_socket_update");
|
||||
|
||||
prop = RNA_def_property(srna, "normalize", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, nullptr, "normalize", 0);
|
||||
RNA_def_property_ui_text(prop, "Normalize", "Normalize outputs to 0.0 to 1.0 range");
|
||||
@@ -4937,52 +4969,6 @@ static void def_sh_tex_magic(StructRNA *srna)
|
||||
RNA_def_property_update(prop, 0, "rna_Node_update");
|
||||
}
|
||||
|
||||
static void def_sh_tex_musgrave(StructRNA *srna)
|
||||
{
|
||||
static const EnumPropertyItem prop_musgrave_type[] = {
|
||||
{SHD_MUSGRAVE_MULTIFRACTAL,
|
||||
"MULTIFRACTAL",
|
||||
0,
|
||||
"Multifractal",
|
||||
"More uneven result (varies with location), more similar to a real terrain"},
|
||||
{SHD_MUSGRAVE_RIDGED_MULTIFRACTAL,
|
||||
"RIDGED_MULTIFRACTAL",
|
||||
0,
|
||||
"Ridged Multifractal",
|
||||
"Create sharp peaks"},
|
||||
{SHD_MUSGRAVE_HYBRID_MULTIFRACTAL,
|
||||
"HYBRID_MULTIFRACTAL",
|
||||
0,
|
||||
"Hybrid Multifractal",
|
||||
"Create peaks and valleys with different roughness values"},
|
||||
{SHD_MUSGRAVE_FBM, "FBM", 0, "fBM", "Produce an unnatural homogeneous and isotropic result"},
|
||||
{SHD_MUSGRAVE_HETERO_TERRAIN,
|
||||
"HETERO_TERRAIN",
|
||||
0,
|
||||
"Hetero Terrain",
|
||||
"Similar to Hybrid Multifractal creates a heterogeneous terrain, but with the likeness of "
|
||||
"river channels"},
|
||||
{0, nullptr, 0, nullptr, nullptr},
|
||||
};
|
||||
|
||||
PropertyRNA *prop;
|
||||
|
||||
RNA_def_struct_sdna_from(srna, "NodeTexMusgrave", "storage");
|
||||
def_sh_tex(srna);
|
||||
|
||||
prop = RNA_def_property(srna, "musgrave_dimensions", PROP_ENUM, PROP_NONE);
|
||||
RNA_def_property_enum_sdna(prop, nullptr, "dimensions");
|
||||
RNA_def_property_enum_items(prop, rna_enum_node_tex_dimensions_items);
|
||||
RNA_def_property_ui_text(prop, "Dimensions", "Number of dimensions to output noise for");
|
||||
RNA_def_property_update(prop, 0, "rna_ShaderNode_socket_update");
|
||||
|
||||
prop = RNA_def_property(srna, "musgrave_type", PROP_ENUM, PROP_NONE);
|
||||
RNA_def_property_enum_sdna(prop, nullptr, "musgrave_type");
|
||||
RNA_def_property_enum_items(prop, prop_musgrave_type);
|
||||
RNA_def_property_ui_text(prop, "Type", "Type of the Musgrave texture");
|
||||
RNA_def_property_update(prop, 0, "rna_ShaderNode_socket_update");
|
||||
}
|
||||
|
||||
static void def_sh_tex_voronoi(StructRNA *srna)
|
||||
{
|
||||
static EnumPropertyItem prop_distance_items[] = {
|
||||
|
||||
@@ -99,7 +99,6 @@ DefNode(ShaderNode, SH_NODE_TEX_GRADIENT, def_sh_tex_gradient, "TEX
|
||||
DefNode(ShaderNode, SH_NODE_TEX_NOISE, def_sh_tex_noise, "TEX_NOISE", TexNoise, "Noise Texture", "Generate fractal Perlin noise")
|
||||
DefNode(ShaderNode, SH_NODE_TEX_MAGIC, def_sh_tex_magic, "TEX_MAGIC", TexMagic, "Magic Texture", "Generate a psychedelic color texture")
|
||||
DefNode(ShaderNode, SH_NODE_TEX_WAVE, def_sh_tex_wave, "TEX_WAVE", TexWave, "Wave Texture", "Generate procedural bands or rings with noise")
|
||||
DefNode(ShaderNode, SH_NODE_TEX_MUSGRAVE, def_sh_tex_musgrave, "TEX_MUSGRAVE", TexMusgrave, "Musgrave Texture", "Generate fractal Perlin noise. Allows for greater control over how octaves are combined than the Noise Texture node")
|
||||
DefNode(ShaderNode, SH_NODE_TEX_VORONOI, def_sh_tex_voronoi, "TEX_VORONOI", TexVoronoi, "Voronoi Texture", "Generate Worley noise based on the distance to random points. Typically used to generate textures such as stones, water, or biological cells")
|
||||
DefNode(ShaderNode, SH_NODE_TEX_CHECKER, def_sh_tex_checker, "TEX_CHECKER", TexChecker, "Checker Texture", "Generate a checkerboard texture")
|
||||
DefNode(ShaderNode, SH_NODE_TEX_BRICK, def_sh_tex_brick, "TEX_BRICK", TexBrick, "Brick Texture", "Generate a procedural texture producing bricks")
|
||||
|
||||
@@ -98,7 +98,6 @@ set(SRC
|
||||
nodes/node_shader_tex_gradient.cc
|
||||
nodes/node_shader_tex_image.cc
|
||||
nodes/node_shader_tex_magic.cc
|
||||
nodes/node_shader_tex_musgrave.cc
|
||||
nodes/node_shader_tex_noise.cc
|
||||
nodes/node_shader_tex_pointdensity.cc
|
||||
nodes/node_shader_tex_sky.cc
|
||||
|
||||
@@ -88,7 +88,6 @@ void register_shader_nodes()
|
||||
register_node_type_sh_tex_ies();
|
||||
register_node_type_sh_tex_image();
|
||||
register_node_type_sh_tex_magic();
|
||||
register_node_type_sh_tex_musgrave();
|
||||
register_node_type_sh_tex_noise();
|
||||
register_node_type_sh_tex_pointdensity();
|
||||
register_node_type_sh_tex_sky();
|
||||
|
||||
@@ -87,7 +87,6 @@ void register_node_type_sh_tex_gradient();
|
||||
void register_node_type_sh_tex_ies();
|
||||
void register_node_type_sh_tex_image();
|
||||
void register_node_type_sh_tex_magic();
|
||||
void register_node_type_sh_tex_musgrave();
|
||||
void register_node_type_sh_tex_noise();
|
||||
void register_node_type_sh_tex_pointdensity();
|
||||
void register_node_type_sh_tex_sky();
|
||||
|
||||
@@ -1,553 +0,0 @@
|
||||
/* SPDX-FileCopyrightText: 2005 Blender Authors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
#include "node_shader_util.hh"
|
||||
#include "node_util.hh"
|
||||
|
||||
#include "BKE_texture.h"
|
||||
|
||||
#include "BLI_noise.hh"
|
||||
|
||||
#include "NOD_multi_function.hh"
|
||||
|
||||
#include "UI_interface.hh"
|
||||
#include "UI_resources.hh"
|
||||
|
||||
namespace blender::nodes::node_shader_tex_musgrave_cc {
|
||||
|
||||
NODE_STORAGE_FUNCS(NodeTexMusgrave)
|
||||
|
||||
static void sh_node_tex_musgrave_declare(NodeDeclarationBuilder &b)
|
||||
{
|
||||
b.is_function_node();
|
||||
b.add_input<decl::Vector>("Vector").hide_value().implicit_field(implicit_field_inputs::position);
|
||||
b.add_input<decl::Float>("W").min(-1000.0f).max(1000.0f).make_available([](bNode &node) {
|
||||
/* Default to 1 instead of 4, because it is much faster. */
|
||||
node_storage(node).dimensions = 1;
|
||||
});
|
||||
b.add_input<decl::Float>("Scale").min(-1000.0f).max(1000.0f).default_value(5.0f);
|
||||
b.add_input<decl::Float>("Detail").min(0.0f).max(15.0f).default_value(2.0f);
|
||||
b.add_input<decl::Float>("Dimension").min(0.0f).max(1000.0f).default_value(2.0f);
|
||||
b.add_input<decl::Float>("Lacunarity").min(0.0f).max(1000.0f).default_value(2.0f);
|
||||
b.add_input<decl::Float>("Offset").min(-1000.0f).max(1000.0f);
|
||||
b.add_input<decl::Float>("Gain").min(0.0f).max(1000.0f).default_value(1.0f);
|
||||
b.add_output<decl::Float>("Fac").no_muted_links();
|
||||
}
|
||||
|
||||
static void node_shader_buts_tex_musgrave(uiLayout *layout, bContext * /*C*/, PointerRNA *ptr)
|
||||
{
|
||||
uiItemR(layout, ptr, "musgrave_dimensions", UI_ITEM_R_SPLIT_EMPTY_NAME, "", ICON_NONE);
|
||||
uiItemR(layout, ptr, "musgrave_type", UI_ITEM_R_SPLIT_EMPTY_NAME, "", ICON_NONE);
|
||||
}
|
||||
|
||||
static void node_shader_init_tex_musgrave(bNodeTree * /*ntree*/, bNode *node)
|
||||
{
|
||||
NodeTexMusgrave *tex = MEM_cnew<NodeTexMusgrave>(__func__);
|
||||
BKE_texture_mapping_default(&tex->base.tex_mapping, TEXMAP_TYPE_POINT);
|
||||
BKE_texture_colormapping_default(&tex->base.color_mapping);
|
||||
tex->musgrave_type = SHD_MUSGRAVE_FBM;
|
||||
tex->dimensions = 3;
|
||||
|
||||
node->storage = tex;
|
||||
}
|
||||
|
||||
static const char *gpu_shader_name_get(const int type, const int dimensions)
|
||||
{
|
||||
BLI_assert(type >= 0 && type < 5);
|
||||
BLI_assert(dimensions > 0 && dimensions < 5);
|
||||
|
||||
switch (type) {
|
||||
case SHD_MUSGRAVE_MULTIFRACTAL:
|
||||
return std::array{"node_tex_musgrave_multi_fractal_1d",
|
||||
"node_tex_musgrave_multi_fractal_2d",
|
||||
"node_tex_musgrave_multi_fractal_3d",
|
||||
"node_tex_musgrave_multi_fractal_4d"}[dimensions - 1];
|
||||
case SHD_MUSGRAVE_FBM:
|
||||
return std::array{"node_tex_musgrave_fBm_1d",
|
||||
"node_tex_musgrave_fBm_2d",
|
||||
"node_tex_musgrave_fBm_3d",
|
||||
"node_tex_musgrave_fBm_4d"}[dimensions - 1];
|
||||
case SHD_MUSGRAVE_HYBRID_MULTIFRACTAL:
|
||||
return std::array{"node_tex_musgrave_hybrid_multi_fractal_1d",
|
||||
"node_tex_musgrave_hybrid_multi_fractal_2d",
|
||||
"node_tex_musgrave_hybrid_multi_fractal_3d",
|
||||
"node_tex_musgrave_hybrid_multi_fractal_4d"}[dimensions - 1];
|
||||
case SHD_MUSGRAVE_RIDGED_MULTIFRACTAL:
|
||||
return std::array{"node_tex_musgrave_ridged_multi_fractal_1d",
|
||||
"node_tex_musgrave_ridged_multi_fractal_2d",
|
||||
"node_tex_musgrave_ridged_multi_fractal_3d",
|
||||
"node_tex_musgrave_ridged_multi_fractal_4d"}[dimensions - 1];
|
||||
case SHD_MUSGRAVE_HETERO_TERRAIN:
|
||||
return std::array{"node_tex_musgrave_hetero_terrain_1d",
|
||||
"node_tex_musgrave_hetero_terrain_2d",
|
||||
"node_tex_musgrave_hetero_terrain_3d",
|
||||
"node_tex_musgrave_hetero_terrain_4d"}[dimensions - 1];
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static int node_shader_gpu_tex_musgrave(GPUMaterial *mat,
|
||||
bNode *node,
|
||||
bNodeExecData * /*execdata*/,
|
||||
GPUNodeStack *in,
|
||||
GPUNodeStack *out)
|
||||
{
|
||||
node_shader_gpu_default_tex_coord(mat, node, &in[0].link);
|
||||
node_shader_gpu_tex_mapping(mat, node, in, out);
|
||||
|
||||
NodeTexMusgrave *tex = (NodeTexMusgrave *)node->storage;
|
||||
int dimensions = tex->dimensions;
|
||||
int type = tex->musgrave_type;
|
||||
|
||||
const char *name = gpu_shader_name_get(type, dimensions);
|
||||
|
||||
return GPU_stack_link(mat, node, name, in, out);
|
||||
}
|
||||
|
||||
static void node_shader_update_tex_musgrave(bNodeTree *ntree, bNode *node)
|
||||
{
|
||||
const NodeTexMusgrave &storage = node_storage(*node);
|
||||
|
||||
bNodeSocket *inVectorSock = nodeFindSocket(node, SOCK_IN, "Vector");
|
||||
bNodeSocket *inWSock = nodeFindSocket(node, SOCK_IN, "W");
|
||||
bNodeSocket *inOffsetSock = nodeFindSocket(node, SOCK_IN, "Offset");
|
||||
bNodeSocket *inGainSock = nodeFindSocket(node, SOCK_IN, "Gain");
|
||||
|
||||
bke::nodeSetSocketAvailability(ntree, inVectorSock, storage.dimensions != 1);
|
||||
bke::nodeSetSocketAvailability(
|
||||
ntree, inWSock, storage.dimensions == 1 || storage.dimensions == 4);
|
||||
bke::nodeSetSocketAvailability(ntree,
|
||||
inOffsetSock,
|
||||
storage.musgrave_type != SHD_MUSGRAVE_MULTIFRACTAL &&
|
||||
storage.musgrave_type != SHD_MUSGRAVE_FBM);
|
||||
bke::nodeSetSocketAvailability(ntree,
|
||||
inGainSock,
|
||||
storage.musgrave_type == SHD_MUSGRAVE_HYBRID_MULTIFRACTAL ||
|
||||
storage.musgrave_type == SHD_MUSGRAVE_RIDGED_MULTIFRACTAL);
|
||||
|
||||
bNodeSocket *outFacSock = nodeFindSocket(node, SOCK_OUT, "Fac");
|
||||
node_sock_label(outFacSock, "Height");
|
||||
}
|
||||
|
||||
class MusgraveFunction : public mf::MultiFunction {
|
||||
private:
|
||||
const int dimensions_;
|
||||
const int musgrave_type_;
|
||||
|
||||
public:
|
||||
MusgraveFunction(const int dimensions, const int musgrave_type)
|
||||
: dimensions_(dimensions), musgrave_type_(musgrave_type)
|
||||
{
|
||||
BLI_assert(dimensions >= 1 && dimensions <= 4);
|
||||
BLI_assert(musgrave_type >= 0 && musgrave_type <= 4);
|
||||
static std::array<mf::Signature, 20> signatures{
|
||||
create_signature(1, SHD_MUSGRAVE_MULTIFRACTAL),
|
||||
create_signature(2, SHD_MUSGRAVE_MULTIFRACTAL),
|
||||
create_signature(3, SHD_MUSGRAVE_MULTIFRACTAL),
|
||||
create_signature(4, SHD_MUSGRAVE_MULTIFRACTAL),
|
||||
|
||||
create_signature(1, SHD_MUSGRAVE_FBM),
|
||||
create_signature(2, SHD_MUSGRAVE_FBM),
|
||||
create_signature(3, SHD_MUSGRAVE_FBM),
|
||||
create_signature(4, SHD_MUSGRAVE_FBM),
|
||||
|
||||
create_signature(1, SHD_MUSGRAVE_HYBRID_MULTIFRACTAL),
|
||||
create_signature(2, SHD_MUSGRAVE_HYBRID_MULTIFRACTAL),
|
||||
create_signature(3, SHD_MUSGRAVE_HYBRID_MULTIFRACTAL),
|
||||
create_signature(4, SHD_MUSGRAVE_HYBRID_MULTIFRACTAL),
|
||||
|
||||
create_signature(1, SHD_MUSGRAVE_RIDGED_MULTIFRACTAL),
|
||||
create_signature(2, SHD_MUSGRAVE_RIDGED_MULTIFRACTAL),
|
||||
create_signature(3, SHD_MUSGRAVE_RIDGED_MULTIFRACTAL),
|
||||
create_signature(4, SHD_MUSGRAVE_RIDGED_MULTIFRACTAL),
|
||||
|
||||
create_signature(1, SHD_MUSGRAVE_HETERO_TERRAIN),
|
||||
create_signature(2, SHD_MUSGRAVE_HETERO_TERRAIN),
|
||||
create_signature(3, SHD_MUSGRAVE_HETERO_TERRAIN),
|
||||
create_signature(4, SHD_MUSGRAVE_HETERO_TERRAIN),
|
||||
};
|
||||
this->set_signature(&signatures[dimensions + musgrave_type * 4 - 1]);
|
||||
}
|
||||
|
||||
static mf::Signature create_signature(const int dimensions, const int musgrave_type)
|
||||
{
|
||||
mf::Signature signature;
|
||||
mf::SignatureBuilder builder{"Musgrave", signature};
|
||||
|
||||
if (ELEM(dimensions, 2, 3, 4)) {
|
||||
builder.single_input<float3>("Vector");
|
||||
}
|
||||
if (ELEM(dimensions, 1, 4)) {
|
||||
builder.single_input<float>("W");
|
||||
}
|
||||
builder.single_input<float>("Scale");
|
||||
builder.single_input<float>("Detail");
|
||||
builder.single_input<float>("Dimension");
|
||||
builder.single_input<float>("Lacunarity");
|
||||
if (ELEM(musgrave_type,
|
||||
SHD_MUSGRAVE_RIDGED_MULTIFRACTAL,
|
||||
SHD_MUSGRAVE_HYBRID_MULTIFRACTAL,
|
||||
SHD_MUSGRAVE_HETERO_TERRAIN))
|
||||
{
|
||||
builder.single_input<float>("Offset");
|
||||
}
|
||||
if (ELEM(musgrave_type, SHD_MUSGRAVE_RIDGED_MULTIFRACTAL, SHD_MUSGRAVE_HYBRID_MULTIFRACTAL)) {
|
||||
builder.single_input<float>("Gain");
|
||||
}
|
||||
|
||||
builder.single_output<float>("Fac", mf::ParamFlag::SupportsUnusedOutput);
|
||||
|
||||
return signature;
|
||||
}
|
||||
|
||||
void call(const IndexMask &mask, mf::Params params, mf::Context /*context*/) const override
|
||||
{
|
||||
auto get_vector = [&](int param_index) -> VArray<float3> {
|
||||
return params.readonly_single_input<float3>(param_index, "Vector");
|
||||
};
|
||||
auto get_w = [&](int param_index) -> VArray<float> {
|
||||
return params.readonly_single_input<float>(param_index, "W");
|
||||
};
|
||||
auto get_scale = [&](int param_index) -> VArray<float> {
|
||||
return params.readonly_single_input<float>(param_index, "Scale");
|
||||
};
|
||||
auto get_detail = [&](int param_index) -> VArray<float> {
|
||||
return params.readonly_single_input<float>(param_index, "Detail");
|
||||
};
|
||||
auto get_dimension = [&](int param_index) -> VArray<float> {
|
||||
return params.readonly_single_input<float>(param_index, "Dimension");
|
||||
};
|
||||
auto get_lacunarity = [&](int param_index) -> VArray<float> {
|
||||
return params.readonly_single_input<float>(param_index, "Lacunarity");
|
||||
};
|
||||
auto get_offset = [&](int param_index) -> VArray<float> {
|
||||
return params.readonly_single_input<float>(param_index, "Offset");
|
||||
};
|
||||
auto get_gain = [&](int param_index) -> VArray<float> {
|
||||
return params.readonly_single_input<float>(param_index, "Gain");
|
||||
};
|
||||
|
||||
auto get_r_factor = [&](int param_index) -> MutableSpan<float> {
|
||||
return params.uninitialized_single_output_if_required<float>(param_index, "Fac");
|
||||
};
|
||||
|
||||
int param = ELEM(dimensions_, 2, 3, 4) + ELEM(dimensions_, 1, 4);
|
||||
const VArray<float> &scale = get_scale(param++);
|
||||
const VArray<float> &detail = get_detail(param++);
|
||||
const VArray<float> &dimension = get_dimension(param++);
|
||||
const VArray<float> &lacunarity = get_lacunarity(param++);
|
||||
|
||||
switch (musgrave_type_) {
|
||||
case SHD_MUSGRAVE_MULTIFRACTAL: {
|
||||
MutableSpan<float> r_factor = get_r_factor(param++);
|
||||
const bool compute_factor = !r_factor.is_empty();
|
||||
switch (dimensions_) {
|
||||
case 1: {
|
||||
const VArray<float> &w = get_w(0);
|
||||
if (compute_factor) {
|
||||
mask.foreach_index([&](const int64_t i) {
|
||||
const float position = w[i] * scale[i];
|
||||
r_factor[i] = noise::musgrave_multi_fractal(
|
||||
position, dimension[i], lacunarity[i], detail[i]);
|
||||
});
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 2: {
|
||||
const VArray<float3> &vector = get_vector(0);
|
||||
if (compute_factor) {
|
||||
mask.foreach_index([&](const int64_t i) {
|
||||
const float3 pxyz = vector[i] * scale[i];
|
||||
const float2 position = float2(pxyz[0], pxyz[1]);
|
||||
r_factor[i] = noise::musgrave_multi_fractal(
|
||||
position, dimension[i], lacunarity[i], detail[i]);
|
||||
});
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 3: {
|
||||
const VArray<float3> &vector = get_vector(0);
|
||||
if (compute_factor) {
|
||||
mask.foreach_index([&](const int64_t i) {
|
||||
const float3 position = vector[i] * scale[i];
|
||||
r_factor[i] = noise::musgrave_multi_fractal(
|
||||
position, dimension[i], lacunarity[i], detail[i]);
|
||||
});
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 4: {
|
||||
const VArray<float3> &vector = get_vector(0);
|
||||
const VArray<float> &w = get_w(1);
|
||||
if (compute_factor) {
|
||||
mask.foreach_index([&](const int64_t i) {
|
||||
const float3 pxyz = vector[i] * scale[i];
|
||||
const float pw = w[i] * scale[i];
|
||||
const float4 position{pxyz[0], pxyz[1], pxyz[2], pw};
|
||||
r_factor[i] = noise::musgrave_multi_fractal(
|
||||
position, dimension[i], lacunarity[i], detail[i]);
|
||||
});
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SHD_MUSGRAVE_RIDGED_MULTIFRACTAL: {
|
||||
const VArray<float> &offset = get_offset(param++);
|
||||
const VArray<float> &gain = get_gain(param++);
|
||||
MutableSpan<float> r_factor = get_r_factor(param++);
|
||||
const bool compute_factor = !r_factor.is_empty();
|
||||
switch (dimensions_) {
|
||||
case 1: {
|
||||
const VArray<float> &w = get_w(0);
|
||||
if (compute_factor) {
|
||||
mask.foreach_index([&](const int64_t i) {
|
||||
const float position = w[i] * scale[i];
|
||||
r_factor[i] = noise::musgrave_ridged_multi_fractal(
|
||||
position, dimension[i], lacunarity[i], detail[i], offset[i], gain[i]);
|
||||
});
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 2: {
|
||||
const VArray<float3> &vector = get_vector(0);
|
||||
if (compute_factor) {
|
||||
mask.foreach_index([&](const int64_t i) {
|
||||
const float3 pxyz = vector[i] * scale[i];
|
||||
const float2 position = float2(pxyz[0], pxyz[1]);
|
||||
r_factor[i] = noise::musgrave_ridged_multi_fractal(
|
||||
position, dimension[i], lacunarity[i], detail[i], offset[i], gain[i]);
|
||||
});
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 3: {
|
||||
const VArray<float3> &vector = get_vector(0);
|
||||
if (compute_factor) {
|
||||
mask.foreach_index([&](const int64_t i) {
|
||||
const float3 position = vector[i] * scale[i];
|
||||
r_factor[i] = noise::musgrave_ridged_multi_fractal(
|
||||
position, dimension[i], lacunarity[i], detail[i], offset[i], gain[i]);
|
||||
});
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 4: {
|
||||
const VArray<float3> &vector = get_vector(0);
|
||||
const VArray<float> &w = get_w(1);
|
||||
if (compute_factor) {
|
||||
mask.foreach_index([&](const int64_t i) {
|
||||
const float3 pxyz = vector[i] * scale[i];
|
||||
const float pw = w[i] * scale[i];
|
||||
const float4 position{pxyz[0], pxyz[1], pxyz[2], pw};
|
||||
r_factor[i] = noise::musgrave_ridged_multi_fractal(
|
||||
position, dimension[i], lacunarity[i], detail[i], offset[i], gain[i]);
|
||||
});
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SHD_MUSGRAVE_HYBRID_MULTIFRACTAL: {
|
||||
const VArray<float> &offset = get_offset(param++);
|
||||
const VArray<float> &gain = get_gain(param++);
|
||||
MutableSpan<float> r_factor = get_r_factor(param++);
|
||||
const bool compute_factor = !r_factor.is_empty();
|
||||
switch (dimensions_) {
|
||||
case 1: {
|
||||
const VArray<float> &w = get_w(0);
|
||||
if (compute_factor) {
|
||||
mask.foreach_index([&](const int64_t i) {
|
||||
const float position = w[i] * scale[i];
|
||||
r_factor[i] = noise::musgrave_hybrid_multi_fractal(
|
||||
position, dimension[i], lacunarity[i], detail[i], offset[i], gain[i]);
|
||||
});
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 2: {
|
||||
const VArray<float3> &vector = get_vector(0);
|
||||
if (compute_factor) {
|
||||
mask.foreach_index([&](const int64_t i) {
|
||||
const float3 pxyz = vector[i] * scale[i];
|
||||
const float2 position = float2(pxyz[0], pxyz[1]);
|
||||
r_factor[i] = noise::musgrave_hybrid_multi_fractal(
|
||||
position, dimension[i], lacunarity[i], detail[i], offset[i], gain[i]);
|
||||
});
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 3: {
|
||||
const VArray<float3> &vector = get_vector(0);
|
||||
if (compute_factor) {
|
||||
mask.foreach_index([&](const int64_t i) {
|
||||
const float3 position = vector[i] * scale[i];
|
||||
r_factor[i] = noise::musgrave_hybrid_multi_fractal(
|
||||
position, dimension[i], lacunarity[i], detail[i], offset[i], gain[i]);
|
||||
});
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 4: {
|
||||
const VArray<float3> &vector = get_vector(0);
|
||||
const VArray<float> &w = get_w(1);
|
||||
if (compute_factor) {
|
||||
mask.foreach_index([&](const int64_t i) {
|
||||
const float3 pxyz = vector[i] * scale[i];
|
||||
const float pw = w[i] * scale[i];
|
||||
const float4 position{pxyz[0], pxyz[1], pxyz[2], pw};
|
||||
r_factor[i] = noise::musgrave_hybrid_multi_fractal(
|
||||
position, dimension[i], lacunarity[i], detail[i], offset[i], gain[i]);
|
||||
});
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SHD_MUSGRAVE_FBM: {
|
||||
MutableSpan<float> r_factor = get_r_factor(param++);
|
||||
const bool compute_factor = !r_factor.is_empty();
|
||||
switch (dimensions_) {
|
||||
case 1: {
|
||||
const VArray<float> &w = get_w(0);
|
||||
if (compute_factor) {
|
||||
mask.foreach_index([&](const int64_t i) {
|
||||
const float position = w[i] * scale[i];
|
||||
r_factor[i] = noise::musgrave_fBm(
|
||||
position, dimension[i], lacunarity[i], detail[i]);
|
||||
});
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 2: {
|
||||
const VArray<float3> &vector = get_vector(0);
|
||||
if (compute_factor) {
|
||||
mask.foreach_index([&](const int64_t i) {
|
||||
const float3 pxyz = vector[i] * scale[i];
|
||||
const float2 position = float2(pxyz[0], pxyz[1]);
|
||||
r_factor[i] = noise::musgrave_fBm(
|
||||
position, dimension[i], lacunarity[i], detail[i]);
|
||||
});
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 3: {
|
||||
const VArray<float3> &vector = get_vector(0);
|
||||
if (compute_factor) {
|
||||
mask.foreach_index([&](const int64_t i) {
|
||||
const float3 position = vector[i] * scale[i];
|
||||
r_factor[i] = noise::musgrave_fBm(
|
||||
position, dimension[i], lacunarity[i], detail[i]);
|
||||
});
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 4: {
|
||||
const VArray<float3> &vector = get_vector(0);
|
||||
const VArray<float> &w = get_w(1);
|
||||
if (compute_factor) {
|
||||
mask.foreach_index([&](const int64_t i) {
|
||||
const float3 pxyz = vector[i] * scale[i];
|
||||
const float pw = w[i] * scale[i];
|
||||
const float4 position{pxyz[0], pxyz[1], pxyz[2], pw};
|
||||
r_factor[i] = noise::musgrave_fBm(
|
||||
position, dimension[i], lacunarity[i], detail[i]);
|
||||
});
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SHD_MUSGRAVE_HETERO_TERRAIN: {
|
||||
const VArray<float> &offset = get_offset(param++);
|
||||
MutableSpan<float> r_factor = get_r_factor(param++);
|
||||
const bool compute_factor = !r_factor.is_empty();
|
||||
switch (dimensions_) {
|
||||
case 1: {
|
||||
const VArray<float> &w = get_w(0);
|
||||
if (compute_factor) {
|
||||
mask.foreach_index([&](const int64_t i) {
|
||||
const float position = w[i] * scale[i];
|
||||
r_factor[i] = noise::musgrave_hetero_terrain(
|
||||
position, dimension[i], lacunarity[i], detail[i], offset[i]);
|
||||
});
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 2: {
|
||||
const VArray<float3> &vector = get_vector(0);
|
||||
if (compute_factor) {
|
||||
mask.foreach_index([&](const int64_t i) {
|
||||
const float3 pxyz = vector[i] * scale[i];
|
||||
const float2 position = float2(pxyz[0], pxyz[1]);
|
||||
r_factor[i] = noise::musgrave_hetero_terrain(
|
||||
position, dimension[i], lacunarity[i], detail[i], offset[i]);
|
||||
});
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 3: {
|
||||
const VArray<float3> &vector = get_vector(0);
|
||||
if (compute_factor) {
|
||||
mask.foreach_index([&](const int64_t i) {
|
||||
const float3 position = vector[i] * scale[i];
|
||||
r_factor[i] = noise::musgrave_hetero_terrain(
|
||||
position, dimension[i], lacunarity[i], detail[i], offset[i]);
|
||||
});
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 4: {
|
||||
const VArray<float3> &vector = get_vector(0);
|
||||
const VArray<float> &w = get_w(1);
|
||||
if (compute_factor) {
|
||||
mask.foreach_index([&](const int64_t i) {
|
||||
const float3 pxyz = vector[i] * scale[i];
|
||||
const float pw = w[i] * scale[i];
|
||||
const float4 position{pxyz[0], pxyz[1], pxyz[2], pw};
|
||||
r_factor[i] = noise::musgrave_hetero_terrain(
|
||||
position, dimension[i], lacunarity[i], detail[i], offset[i]);
|
||||
});
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
static void sh_node_musgrave_build_multi_function(NodeMultiFunctionBuilder &builder)
|
||||
{
|
||||
const bNode &node = builder.node();
|
||||
NodeTexMusgrave *tex = (NodeTexMusgrave *)node.storage;
|
||||
builder.construct_and_set_matching_fn<MusgraveFunction>(tex->dimensions, tex->musgrave_type);
|
||||
}
|
||||
|
||||
} // namespace blender::nodes::node_shader_tex_musgrave_cc
|
||||
|
||||
void register_node_type_sh_tex_musgrave()
|
||||
{
|
||||
namespace file_ns = blender::nodes::node_shader_tex_musgrave_cc;
|
||||
|
||||
static bNodeType ntype;
|
||||
|
||||
sh_fn_node_type_base(&ntype, SH_NODE_TEX_MUSGRAVE, "Musgrave Texture", NODE_CLASS_TEXTURE);
|
||||
ntype.declare = file_ns::sh_node_tex_musgrave_declare;
|
||||
ntype.draw_buttons = file_ns::node_shader_buts_tex_musgrave;
|
||||
blender::bke::node_type_size_preset(&ntype, blender::bke::eNodeSizePreset::MIDDLE);
|
||||
ntype.initfunc = file_ns::node_shader_init_tex_musgrave;
|
||||
node_type_storage(
|
||||
&ntype, "NodeTexMusgrave", node_free_standard_storage, node_copy_standard_storage);
|
||||
ntype.gpu_fn = file_ns::node_shader_gpu_tex_musgrave;
|
||||
ntype.updatefunc = file_ns::node_shader_update_tex_musgrave;
|
||||
ntype.build_multi_function = file_ns::sh_node_musgrave_build_multi_function;
|
||||
|
||||
nodeRegisterType(&ntype);
|
||||
}
|
||||
@@ -11,6 +11,8 @@
|
||||
|
||||
#include "NOD_multi_function.hh"
|
||||
|
||||
#include "RNA_access.hh"
|
||||
|
||||
#include "UI_interface.hh"
|
||||
#include "UI_resources.hh"
|
||||
|
||||
@@ -38,6 +40,8 @@ static void sh_node_tex_noise_declare(NodeDeclarationBuilder &b)
|
||||
.max(1000.0f)
|
||||
.default_value(2.0f)
|
||||
.description("The scale of a Perlin noise octave relative to that of the previous octave");
|
||||
b.add_input<decl::Float>("Offset").min(-1000.0f).max(1000.0f).default_value(0.0f);
|
||||
b.add_input<decl::Float>("Gain").min(0.0f).max(1000.0f).default_value(1.0f);
|
||||
b.add_input<decl::Float>("Distortion").min(-1000.0f).max(1000.0f).default_value(0.0f);
|
||||
b.add_output<decl::Float>("Fac").no_muted_links();
|
||||
b.add_output<decl::Color>("Color").no_muted_links();
|
||||
@@ -46,7 +50,10 @@ static void sh_node_tex_noise_declare(NodeDeclarationBuilder &b)
|
||||
static void node_shader_buts_tex_noise(uiLayout *layout, bContext * /*C*/, PointerRNA *ptr)
|
||||
{
|
||||
uiItemR(layout, ptr, "noise_dimensions", UI_ITEM_R_SPLIT_EMPTY_NAME, "", ICON_NONE);
|
||||
uiItemR(layout, ptr, "normalize", UI_ITEM_R_SPLIT_EMPTY_NAME, nullptr, ICON_NONE);
|
||||
uiItemR(layout, ptr, "type", UI_ITEM_R_SPLIT_EMPTY_NAME, "", ICON_NONE);
|
||||
if (ELEM(RNA_enum_get(ptr, "type"), SHD_NOISE_FBM)) {
|
||||
uiItemR(layout, ptr, "normalize", UI_ITEM_R_SPLIT_EMPTY_NAME, nullptr, ICON_NONE);
|
||||
}
|
||||
}
|
||||
|
||||
static void node_shader_init_tex_noise(bNodeTree * /*ntree*/, bNode *node)
|
||||
@@ -55,18 +62,44 @@ static void node_shader_init_tex_noise(bNodeTree * /*ntree*/, bNode *node)
|
||||
BKE_texture_mapping_default(&tex->base.tex_mapping, TEXMAP_TYPE_POINT);
|
||||
BKE_texture_colormapping_default(&tex->base.color_mapping);
|
||||
tex->dimensions = 3;
|
||||
tex->type = SHD_NOISE_FBM;
|
||||
tex->normalize = true;
|
||||
|
||||
node->storage = tex;
|
||||
}
|
||||
|
||||
static const char *gpu_shader_get_name(const int dimensions)
|
||||
static const char *gpu_shader_get_name(const int dimensions, const int type)
|
||||
{
|
||||
BLI_assert(dimensions >= 1 && dimensions <= 4);
|
||||
return std::array{"node_noise_texture_1d",
|
||||
"node_noise_texture_2d",
|
||||
"node_noise_texture_3d",
|
||||
"node_noise_texture_4d"}[dimensions - 1];
|
||||
BLI_assert(dimensions > 0 && dimensions < 5);
|
||||
BLI_assert(type >= 0 && type < 5);
|
||||
|
||||
switch (type) {
|
||||
case SHD_NOISE_MULTIFRACTAL:
|
||||
return std::array{"node_noise_tex_multi_fractal_1d",
|
||||
"node_noise_tex_multi_fractal_2d",
|
||||
"node_noise_tex_multi_fractal_3d",
|
||||
"node_noise_tex_multi_fractal_4d"}[dimensions - 1];
|
||||
case SHD_NOISE_FBM:
|
||||
return std::array{"node_noise_tex_fbm_1d",
|
||||
"node_noise_tex_fbm_2d",
|
||||
"node_noise_tex_fbm_3d",
|
||||
"node_noise_tex_fbm_4d"}[dimensions - 1];
|
||||
case SHD_NOISE_HYBRID_MULTIFRACTAL:
|
||||
return std::array{"node_noise_tex_hybrid_multi_fractal_1d",
|
||||
"node_noise_tex_hybrid_multi_fractal_2d",
|
||||
"node_noise_tex_hybrid_multi_fractal_3d",
|
||||
"node_noise_tex_hybrid_multi_fractal_4d"}[dimensions - 1];
|
||||
case SHD_NOISE_RIDGED_MULTIFRACTAL:
|
||||
return std::array{"node_noise_tex_ridged_multi_fractal_1d",
|
||||
"node_noise_tex_ridged_multi_fractal_2d",
|
||||
"node_noise_tex_ridged_multi_fractal_3d",
|
||||
"node_noise_tex_ridged_multi_fractal_4d"}[dimensions - 1];
|
||||
case SHD_NOISE_HETERO_TERRAIN:
|
||||
return std::array{"node_noise_tex_hetero_terrain_1d",
|
||||
"node_noise_tex_hetero_terrain_2d",
|
||||
"node_noise_tex_hetero_terrain_3d",
|
||||
"node_noise_tex_hetero_terrain_4d"}[dimensions - 1];
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@@ -82,7 +115,7 @@ static int node_shader_gpu_tex_noise(GPUMaterial *mat,
|
||||
const NodeTexNoise &storage = node_storage(*node);
|
||||
float normalize = storage.normalize;
|
||||
|
||||
const char *name = gpu_shader_get_name(storage.dimensions);
|
||||
const char *name = gpu_shader_get_name(storage.dimensions, storage.type);
|
||||
return GPU_stack_link(mat, node, name, in, out, GPU_constant(&normalize));
|
||||
}
|
||||
|
||||
@@ -90,31 +123,64 @@ static void node_shader_update_tex_noise(bNodeTree *ntree, bNode *node)
|
||||
{
|
||||
bNodeSocket *sockVector = nodeFindSocket(node, SOCK_IN, "Vector");
|
||||
bNodeSocket *sockW = nodeFindSocket(node, SOCK_IN, "W");
|
||||
bNodeSocket *inOffsetSock = nodeFindSocket(node, SOCK_IN, "Offset");
|
||||
bNodeSocket *inGainSock = nodeFindSocket(node, SOCK_IN, "Gain");
|
||||
|
||||
const NodeTexNoise &storage = node_storage(*node);
|
||||
bke::nodeSetSocketAvailability(ntree, sockVector, storage.dimensions != 1);
|
||||
bke::nodeSetSocketAvailability(ntree, sockW, storage.dimensions == 1 || storage.dimensions == 4);
|
||||
bke::nodeSetSocketAvailability(ntree,
|
||||
inOffsetSock,
|
||||
storage.type != SHD_NOISE_MULTIFRACTAL &&
|
||||
storage.type != SHD_NOISE_FBM);
|
||||
bke::nodeSetSocketAvailability(ntree,
|
||||
inGainSock,
|
||||
storage.type == SHD_NOISE_HYBRID_MULTIFRACTAL ||
|
||||
storage.type == SHD_NOISE_RIDGED_MULTIFRACTAL);
|
||||
}
|
||||
|
||||
class NoiseFunction : public mf::MultiFunction {
|
||||
private:
|
||||
int dimensions_;
|
||||
int type_;
|
||||
bool normalize_;
|
||||
|
||||
public:
|
||||
NoiseFunction(int dimensions, bool normalize) : dimensions_(dimensions), normalize_(normalize)
|
||||
NoiseFunction(int dimensions, int type, bool normalize)
|
||||
: dimensions_(dimensions), type_(type), normalize_(normalize)
|
||||
{
|
||||
BLI_assert(dimensions >= 1 && dimensions <= 4);
|
||||
static std::array<mf::Signature, 4> signatures{
|
||||
create_signature(1),
|
||||
create_signature(2),
|
||||
create_signature(3),
|
||||
create_signature(4),
|
||||
BLI_assert(type >= 0 && type <= 4);
|
||||
static std::array<mf::Signature, 20> signatures{
|
||||
create_signature(1, SHD_NOISE_MULTIFRACTAL),
|
||||
create_signature(2, SHD_NOISE_MULTIFRACTAL),
|
||||
create_signature(3, SHD_NOISE_MULTIFRACTAL),
|
||||
create_signature(4, SHD_NOISE_MULTIFRACTAL),
|
||||
|
||||
create_signature(1, SHD_NOISE_FBM),
|
||||
create_signature(2, SHD_NOISE_FBM),
|
||||
create_signature(3, SHD_NOISE_FBM),
|
||||
create_signature(4, SHD_NOISE_FBM),
|
||||
|
||||
create_signature(1, SHD_NOISE_HYBRID_MULTIFRACTAL),
|
||||
create_signature(2, SHD_NOISE_HYBRID_MULTIFRACTAL),
|
||||
create_signature(3, SHD_NOISE_HYBRID_MULTIFRACTAL),
|
||||
create_signature(4, SHD_NOISE_HYBRID_MULTIFRACTAL),
|
||||
|
||||
create_signature(1, SHD_NOISE_RIDGED_MULTIFRACTAL),
|
||||
create_signature(2, SHD_NOISE_RIDGED_MULTIFRACTAL),
|
||||
create_signature(3, SHD_NOISE_RIDGED_MULTIFRACTAL),
|
||||
create_signature(4, SHD_NOISE_RIDGED_MULTIFRACTAL),
|
||||
|
||||
create_signature(1, SHD_NOISE_HETERO_TERRAIN),
|
||||
create_signature(2, SHD_NOISE_HETERO_TERRAIN),
|
||||
create_signature(3, SHD_NOISE_HETERO_TERRAIN),
|
||||
create_signature(4, SHD_NOISE_HETERO_TERRAIN),
|
||||
};
|
||||
this->set_signature(&signatures[dimensions - 1]);
|
||||
this->set_signature(&signatures[dimensions + type * 4 - 1]);
|
||||
}
|
||||
|
||||
static mf::Signature create_signature(int dimensions)
|
||||
static mf::Signature create_signature(int dimensions, int type)
|
||||
{
|
||||
mf::Signature signature;
|
||||
mf::SignatureBuilder builder{"Noise", signature};
|
||||
@@ -130,6 +196,16 @@ class NoiseFunction : public mf::MultiFunction {
|
||||
builder.single_input<float>("Detail");
|
||||
builder.single_input<float>("Roughness");
|
||||
builder.single_input<float>("Lacunarity");
|
||||
if (ELEM(type,
|
||||
SHD_NOISE_RIDGED_MULTIFRACTAL,
|
||||
SHD_NOISE_HYBRID_MULTIFRACTAL,
|
||||
SHD_NOISE_HETERO_TERRAIN))
|
||||
{
|
||||
builder.single_input<float>("Offset");
|
||||
}
|
||||
if (ELEM(type, SHD_NOISE_RIDGED_MULTIFRACTAL, SHD_NOISE_HYBRID_MULTIFRACTAL)) {
|
||||
builder.single_input<float>("Gain");
|
||||
}
|
||||
builder.single_input<float>("Distortion");
|
||||
|
||||
builder.single_output<float>("Fac", mf::ParamFlag::SupportsUnusedOutput);
|
||||
@@ -145,6 +221,19 @@ class NoiseFunction : public mf::MultiFunction {
|
||||
const VArray<float> &detail = params.readonly_single_input<float>(param++, "Detail");
|
||||
const VArray<float> &roughness = params.readonly_single_input<float>(param++, "Roughness");
|
||||
const VArray<float> &lacunarity = params.readonly_single_input<float>(param++, "Lacunarity");
|
||||
/* Initialize to any other variable when unused to avoid unnecessary conditionals. */
|
||||
const VArray<float> &offset = ELEM(type_,
|
||||
SHD_NOISE_RIDGED_MULTIFRACTAL,
|
||||
SHD_NOISE_HYBRID_MULTIFRACTAL,
|
||||
SHD_NOISE_HETERO_TERRAIN) ?
|
||||
params.readonly_single_input<float>(param++, "Offset") :
|
||||
scale;
|
||||
/* Initialize to any other variable when unused to avoid unnecessary conditionals. */
|
||||
const VArray<float> &gain = ELEM(type_,
|
||||
SHD_NOISE_RIDGED_MULTIFRACTAL,
|
||||
SHD_NOISE_HYBRID_MULTIFRACTAL) ?
|
||||
params.readonly_single_input<float>(param++, "Gain") :
|
||||
scale;
|
||||
const VArray<float> &distortion = params.readonly_single_input<float>(param++, "Distortion");
|
||||
|
||||
MutableSpan<float> r_factor = params.uninitialized_single_output_if_required<float>(param++,
|
||||
@@ -161,15 +250,30 @@ class NoiseFunction : public mf::MultiFunction {
|
||||
if (compute_factor) {
|
||||
mask.foreach_index([&](const int64_t i) {
|
||||
const float position = w[i] * scale[i];
|
||||
r_factor[i] = noise::perlin_fractal_distorted(
|
||||
position, detail[i], roughness[i], lacunarity[i], distortion[i], normalize_);
|
||||
r_factor[i] = noise::perlin_fractal_distorted(position,
|
||||
math::clamp(detail[i], 0.0f, 15.0f),
|
||||
math::max(roughness[i], 0.0f),
|
||||
lacunarity[i],
|
||||
offset[i],
|
||||
gain[i],
|
||||
distortion[i],
|
||||
type_,
|
||||
normalize_);
|
||||
});
|
||||
}
|
||||
if (compute_color) {
|
||||
mask.foreach_index([&](const int64_t i) {
|
||||
const float position = w[i] * scale[i];
|
||||
const float3 c = noise::perlin_float3_fractal_distorted(
|
||||
position, detail[i], roughness[i], lacunarity[i], distortion[i], normalize_);
|
||||
position,
|
||||
math::clamp(detail[i], 0.0f, 15.0f),
|
||||
math::max(roughness[i], 0.0f),
|
||||
lacunarity[i],
|
||||
offset[i],
|
||||
gain[i],
|
||||
distortion[i],
|
||||
type_,
|
||||
normalize_);
|
||||
r_color[i] = ColorGeometry4f(c[0], c[1], c[2], 1.0f);
|
||||
});
|
||||
}
|
||||
@@ -180,15 +284,30 @@ class NoiseFunction : public mf::MultiFunction {
|
||||
if (compute_factor) {
|
||||
mask.foreach_index([&](const int64_t i) {
|
||||
const float2 position = float2(vector[i] * scale[i]);
|
||||
r_factor[i] = noise::perlin_fractal_distorted(
|
||||
position, detail[i], roughness[i], lacunarity[i], distortion[i], normalize_);
|
||||
r_factor[i] = noise::perlin_fractal_distorted(position,
|
||||
math::clamp(detail[i], 0.0f, 15.0f),
|
||||
math::max(roughness[i], 0.0f),
|
||||
lacunarity[i],
|
||||
offset[i],
|
||||
gain[i],
|
||||
distortion[i],
|
||||
type_,
|
||||
normalize_);
|
||||
});
|
||||
}
|
||||
if (compute_color) {
|
||||
mask.foreach_index([&](const int64_t i) {
|
||||
const float2 position = float2(vector[i] * scale[i]);
|
||||
const float3 c = noise::perlin_float3_fractal_distorted(
|
||||
position, detail[i], roughness[i], lacunarity[i], distortion[i], normalize_);
|
||||
position,
|
||||
math::clamp(detail[i], 0.0f, 15.0f),
|
||||
math::max(roughness[i], 0.0f),
|
||||
lacunarity[i],
|
||||
offset[i],
|
||||
gain[i],
|
||||
distortion[i],
|
||||
type_,
|
||||
normalize_);
|
||||
r_color[i] = ColorGeometry4f(c[0], c[1], c[2], 1.0f);
|
||||
});
|
||||
}
|
||||
@@ -199,15 +318,30 @@ class NoiseFunction : public mf::MultiFunction {
|
||||
if (compute_factor) {
|
||||
mask.foreach_index([&](const int64_t i) {
|
||||
const float3 position = vector[i] * scale[i];
|
||||
r_factor[i] = noise::perlin_fractal_distorted(
|
||||
position, detail[i], roughness[i], lacunarity[i], distortion[i], normalize_);
|
||||
r_factor[i] = noise::perlin_fractal_distorted(position,
|
||||
math::clamp(detail[i], 0.0f, 15.0f),
|
||||
math::max(roughness[i], 0.0f),
|
||||
lacunarity[i],
|
||||
offset[i],
|
||||
gain[i],
|
||||
distortion[i],
|
||||
type_,
|
||||
normalize_);
|
||||
});
|
||||
}
|
||||
if (compute_color) {
|
||||
mask.foreach_index([&](const int64_t i) {
|
||||
const float3 position = vector[i] * scale[i];
|
||||
const float3 c = noise::perlin_float3_fractal_distorted(
|
||||
position, detail[i], roughness[i], lacunarity[i], distortion[i], normalize_);
|
||||
position,
|
||||
math::clamp(detail[i], 0.0f, 15.0f),
|
||||
math::max(roughness[i], 0.0f),
|
||||
lacunarity[i],
|
||||
offset[i],
|
||||
gain[i],
|
||||
distortion[i],
|
||||
type_,
|
||||
normalize_);
|
||||
r_color[i] = ColorGeometry4f(c[0], c[1], c[2], 1.0f);
|
||||
});
|
||||
}
|
||||
@@ -222,8 +356,15 @@ class NoiseFunction : public mf::MultiFunction {
|
||||
const float position_w = w[i] * scale[i];
|
||||
const float4 position{
|
||||
position_vector[0], position_vector[1], position_vector[2], position_w};
|
||||
r_factor[i] = noise::perlin_fractal_distorted(
|
||||
position, detail[i], roughness[i], lacunarity[i], distortion[i], normalize_);
|
||||
r_factor[i] = noise::perlin_fractal_distorted(position,
|
||||
math::clamp(detail[i], 0.0f, 15.0f),
|
||||
math::max(roughness[i], 0.0f),
|
||||
lacunarity[i],
|
||||
offset[i],
|
||||
gain[i],
|
||||
distortion[i],
|
||||
type_,
|
||||
normalize_);
|
||||
});
|
||||
}
|
||||
if (compute_color) {
|
||||
@@ -233,7 +374,15 @@ class NoiseFunction : public mf::MultiFunction {
|
||||
const float4 position{
|
||||
position_vector[0], position_vector[1], position_vector[2], position_w};
|
||||
const float3 c = noise::perlin_float3_fractal_distorted(
|
||||
position, detail[i], roughness[i], lacunarity[i], distortion[i], normalize_);
|
||||
position,
|
||||
math::clamp(detail[i], 0.0f, 15.0f),
|
||||
math::max(roughness[i], 0.0f),
|
||||
lacunarity[i],
|
||||
offset[i],
|
||||
gain[i],
|
||||
distortion[i],
|
||||
type_,
|
||||
normalize_);
|
||||
r_color[i] = ColorGeometry4f(c[0], c[1], c[2], 1.0f);
|
||||
});
|
||||
}
|
||||
@@ -254,7 +403,8 @@ class NoiseFunction : public mf::MultiFunction {
|
||||
static void sh_node_noise_build_multi_function(NodeMultiFunctionBuilder &builder)
|
||||
{
|
||||
const NodeTexNoise &storage = node_storage(builder.node());
|
||||
builder.construct_and_set_matching_fn<NoiseFunction>(storage.dimensions, storage.normalize);
|
||||
builder.construct_and_set_matching_fn<NoiseFunction>(
|
||||
storage.dimensions, storage.type, storage.normalize);
|
||||
}
|
||||
|
||||
NODE_SHADER_MATERIALX_BEGIN
|
||||
|
||||
@@ -183,7 +183,8 @@ class WaveFunction : public mf::MultiFunction {
|
||||
|
||||
if (distortion[i] != 0.0f) {
|
||||
n += distortion[i] *
|
||||
(noise::perlin_fractal(p * dscale[i], detail[i], droughness[i], 2.0f, true) * 2.0f -
|
||||
(noise::perlin_fbm<float3>(p * dscale[i], detail[i], droughness[i], 2.0f, true) *
|
||||
2.0f -
|
||||
1.0f);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user