Shading: Extend Musgrave node to other dimensions.

This patch extends Musgrave noise to operate in 1D, 2D, 3D, and 4D
space. The Color output was also removed because it was identical
to the Fac output.

Reviewed By: brecht

Differential Revision: https://developer.blender.org/D5566
This commit is contained in:
OmarSquircleArt 2019-09-09 21:06:55 +02:00
parent c2d37929b4
commit f2176b3ff3
13 changed files with 2278 additions and 311 deletions

View File

@ -785,11 +785,12 @@ static ShaderNode *add_node(Scene *scene,
}
else if (b_node.is_a(&RNA_ShaderNodeTexMusgrave)) {
BL::ShaderNodeTexMusgrave b_musgrave_node(b_node);
MusgraveTextureNode *musgrave = new MusgraveTextureNode();
musgrave->type = (NodeMusgraveType)b_musgrave_node.musgrave_type();
MusgraveTextureNode *musgrave_node = new MusgraveTextureNode();
musgrave_node->type = (NodeMusgraveType)b_musgrave_node.musgrave_type();
musgrave_node->dimensions = b_musgrave_node.musgrave_dimensions();
BL::TexMapping b_texture_mapping(b_musgrave_node.texture_mapping());
get_tex_mapping(&musgrave->tex_mapping, b_texture_mapping);
node = musgrave;
get_tex_mapping(&musgrave_node->tex_mapping, b_texture_mapping);
node = musgrave_node;
}
else if (b_node.is_a(&RNA_ShaderNodeTexCoord)) {
BL::ShaderNodeTexCoord b_tex_coord_node(b_node);

View File

@ -16,8 +16,12 @@
#include "stdosl.h"
#include "node_noise.h"
#include "vector2.h"
#include "vector4.h"
/* Musgrave fBm
#define vector3 point
/* 1D Musgrave fBm
*
* H: fractal increment parameter
* lacunarity: gap between successive frequencies
@ -26,58 +30,56 @@
* from "Texturing and Modelling: A procedural approach"
*/
float noise_musgrave_fBm(point ip, float H, float lacunarity, float octaves)
float noise_musgrave_fBm_1d(float co, float H, float lacunarity, float octaves)
{
float rmd;
float p = co;
float value = 0.0;
float pwr = 1.0;
float pwHL = pow(lacunarity, -H);
int i;
point p = ip;
for (i = 0; i < (int)octaves; i++) {
value += safe_noise(p) * pwr;
for (int i = 0; i < (int)octaves; i++) {
value += safe_snoise(p) * pwr;
pwr *= pwHL;
p *= lacunarity;
}
rmd = octaves - floor(octaves);
if (rmd != 0.0)
value += rmd * safe_noise(p) * pwr;
float rmd = octaves - floor(octaves);
if (rmd != 0.0) {
value += rmd * safe_snoise(p) * pwr;
}
return value;
}
/* Musgrave Multifractal
/* 1D Musgrave Multifractal
*
* H: highest fractal dimension
* lacunarity: gap between successive frequencies
* octaves: number of frequencies in the fBm
*/
float noise_musgrave_multi_fractal(point ip, float H, float lacunarity, float octaves)
float noise_musgrave_multi_fractal_1d(float co, float H, float lacunarity, float octaves)
{
float rmd;
float p = co;
float value = 1.0;
float pwr = 1.0;
float pwHL = pow(lacunarity, -H);
int i;
point p = ip;
for (i = 0; i < (int)octaves; i++) {
value *= (pwr * safe_noise(p) + 1.0);
for (int i = 0; i < (int)octaves; i++) {
value *= (pwr * safe_snoise(p) + 1.0);
pwr *= pwHL;
p *= lacunarity;
}
rmd = octaves - floor(octaves);
if (rmd != 0.0)
value *= (rmd * pwr * safe_noise(p) + 1.0); /* correct? */
float rmd = octaves - floor(octaves);
if (rmd != 0.0) {
value *= (rmd * pwr * safe_snoise(p) + 1.0); /* correct? */
}
return value;
}
/* Musgrave Heterogeneous Terrain
/* 1D Musgrave Heterogeneous Terrain
*
* H: fractal dimension of the roughest area
* lacunarity: gap between successive frequencies
@ -85,36 +87,34 @@ float noise_musgrave_multi_fractal(point ip, float H, float lacunarity, float oc
* offset: raises the terrain from `sea level'
*/
float noise_musgrave_hetero_terrain(
point ip, float H, float lacunarity, float octaves, float offset)
float noise_musgrave_hetero_terrain_1d(
float co, float H, float lacunarity, float octaves, float offset)
{
float value, increment, rmd;
float p = co;
float pwHL = pow(lacunarity, -H);
float pwr = pwHL;
int i;
point p = ip;
/* first unscaled octave of function; later octaves are scaled */
value = offset + safe_noise(p);
float value = offset + safe_snoise(p);
p *= lacunarity;
for (i = 1; i < (int)octaves; i++) {
increment = (safe_noise(p) + offset) * pwr * value;
for (int i = 1; i < (int)octaves; i++) {
float increment = (safe_snoise(p) + offset) * pwr * value;
value += increment;
pwr *= pwHL;
p *= lacunarity;
}
rmd = octaves - floor(octaves);
float rmd = octaves - floor(octaves);
if (rmd != 0.0) {
increment = (safe_noise(p) + offset) * pwr * value;
float increment = (safe_snoise(p) + offset) * pwr * value;
value += rmd * increment;
}
return value;
}
/* Hybrid Additive/Multiplicative Multifractal Terrain
/* 1D Hybrid Additive/Multiplicative Multifractal Terrain
*
* H: fractal dimension of the roughest area
* lacunarity: gap between successive frequencies
@ -122,38 +122,38 @@ float noise_musgrave_hetero_terrain(
* offset: raises the terrain from `sea level'
*/
float noise_musgrave_hybrid_multi_fractal(
point ip, float H, float lacunarity, float octaves, float offset, float gain)
float noise_musgrave_hybrid_multi_fractal_1d(
float co, float H, float lacunarity, float octaves, float offset, float gain)
{
float result, signal, weight, rmd;
float p = co;
float pwHL = pow(lacunarity, -H);
float pwr = pwHL;
int i;
point p = ip;
result = safe_noise(p) + offset;
weight = gain * result;
float value = safe_snoise(p) + offset;
float weight = gain * value;
p *= lacunarity;
for (i = 1; (weight > 0.001) && (i < (int)octaves); i++) {
if (weight > 1.0)
for (int i = 1; (weight > 0.001) && (i < (int)octaves); i++) {
if (weight > 1.0) {
weight = 1.0;
}
signal = (safe_noise(p) + offset) * pwr;
float signal = (safe_snoise(p) + offset) * pwr;
pwr *= pwHL;
result += weight * signal;
value += weight * signal;
weight *= gain * signal;
p *= lacunarity;
}
rmd = octaves - floor(octaves);
if (rmd != 0.0)
result += rmd * ((safe_noise(p) + offset) * pwr);
float rmd = octaves - floor(octaves);
if (rmd != 0.0) {
value += rmd * ((safe_snoise(p) + offset) * pwr);
}
return result;
return value;
}
/* Ridged Multifractal Terrain
/* 1D Ridged Multifractal Terrain
*
* H: fractal dimension of the roughest area
* lacunarity: gap between successive frequencies
@ -161,73 +161,643 @@ float noise_musgrave_hybrid_multi_fractal(
* offset: raises the terrain from `sea level'
*/
float noise_musgrave_ridged_multi_fractal(
point ip, float H, float lacunarity, float octaves, float offset, float gain)
float noise_musgrave_ridged_multi_fractal_1d(
float co, float H, float lacunarity, float octaves, float offset, float gain)
{
float result, signal, weight;
float p = co;
float pwHL = pow(lacunarity, -H);
float pwr = pwHL;
int i;
point p = ip;
signal = offset - fabs(safe_noise(p));
float signal = offset - fabs(safe_snoise(p));
signal *= signal;
result = signal;
weight = 1.0;
float value = signal;
float weight = 1.0;
for (i = 1; i < (int)octaves; i++) {
for (int i = 1; i < (int)octaves; i++) {
p *= lacunarity;
weight = clamp(signal * gain, 0.0, 1.0);
signal = offset - fabs(safe_noise(p));
signal = offset - fabs(safe_snoise(p));
signal *= signal;
signal *= weight;
result += signal * pwr;
value += signal * pwr;
pwr *= pwHL;
}
return result;
return value;
}
/* Shader */
/* 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 = pwHL;
float value = safe_snoise(p) + offset;
float weight = gain * value;
p *= lacunarity;
for (int i = 1; (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) {
value += rmd * ((safe_snoise(p) + offset) * pwr);
}
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 = pwHL;
float value = safe_snoise(p) + offset;
float weight = gain * value;
p *= lacunarity;
for (int i = 1; (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) {
value += rmd * ((safe_snoise(p) + offset) * pwr);
}
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 = pwHL;
float value = safe_snoise(p) + offset;
float weight = gain * value;
p *= lacunarity;
for (int i = 1; (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) {
value += rmd * ((safe_snoise(p) + offset) * pwr);
}
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 type = "fBM",
string dimensions = "3D",
point Vector = P,
float W = 0.0,
float Dimension = 2.0,
float Lacunarity = 1.0,
float Scale = 5.0,
float Detail = 2.0,
float Lacunarity = 1.0,
float Offset = 0.0,
float Gain = 1.0,
float Scale = 5.0,
point Vector = P,
output float Fac = 0.0,
output color Color = 0.0)
output float Fac = 0.0)
{
float dimension = max(Dimension, 1e-5);
float octaves = clamp(Detail, 0.0, 16.0);
float lacunarity = max(Lacunarity, 1e-5);
float intensity = 1.0;
point p = Vector;
vector3 s = Vector;
if (use_mapping)
p = transform(mapping, p);
s = transform(mapping, s);
p = p * Scale;
if (type == "multifractal")
Fac = intensity * noise_musgrave_multi_fractal(p, dimension, lacunarity, octaves);
else if (type == "fBM")
Fac = intensity * noise_musgrave_fBm(p, dimension, lacunarity, octaves);
else if (type == "hybrid_multifractal")
Fac = intensity *
noise_musgrave_hybrid_multi_fractal(p, dimension, lacunarity, octaves, Offset, Gain);
else if (type == "ridged_multifractal")
Fac = intensity *
noise_musgrave_ridged_multi_fractal(p, dimension, lacunarity, octaves, Offset, Gain);
else if (type == "hetero_terrain")
Fac = intensity * noise_musgrave_hetero_terrain(p, dimension, lacunarity, octaves, Offset);
Color = color(Fac, Fac, Fac);
if (dimensions == "1D") {
float p = W * Scale;
if (type == "multifractal") {
Fac = noise_musgrave_multi_fractal_1d(p, dimension, lacunarity, octaves);
}
else if (type == "fBM") {
Fac = noise_musgrave_fBm_1d(p, dimension, lacunarity, octaves);
}
else if (type == "hybrid_multifractal") {
Fac = noise_musgrave_hybrid_multi_fractal_1d(
p, dimension, lacunarity, octaves, Offset, Gain);
}
else if (type == "ridged_multifractal") {
Fac = noise_musgrave_ridged_multi_fractal_1d(
p, dimension, lacunarity, octaves, Offset, Gain);
}
else if (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 (type == "multifractal") {
Fac = noise_musgrave_multi_fractal_2d(p, dimension, lacunarity, octaves);
}
else if (type == "fBM") {
Fac = noise_musgrave_fBm_2d(p, dimension, lacunarity, octaves);
}
else if (type == "hybrid_multifractal") {
Fac = noise_musgrave_hybrid_multi_fractal_2d(
p, dimension, lacunarity, octaves, Offset, Gain);
}
else if (type == "ridged_multifractal") {
Fac = noise_musgrave_ridged_multi_fractal_2d(
p, dimension, lacunarity, octaves, Offset, Gain);
}
else if (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 (type == "multifractal") {
Fac = noise_musgrave_multi_fractal_3d(p, dimension, lacunarity, octaves);
}
else if (type == "fBM") {
Fac = noise_musgrave_fBm_3d(p, dimension, lacunarity, octaves);
}
else if (type == "hybrid_multifractal") {
Fac = noise_musgrave_hybrid_multi_fractal_3d(
p, dimension, lacunarity, octaves, Offset, Gain);
}
else if (type == "ridged_multifractal") {
Fac = noise_musgrave_ridged_multi_fractal_3d(
p, dimension, lacunarity, octaves, Offset, Gain);
}
else if (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 (type == "multifractal") {
Fac = noise_musgrave_multi_fractal_4d(p, dimension, lacunarity, octaves);
}
else if (type == "fBM") {
Fac = noise_musgrave_fBm_4d(p, dimension, lacunarity, octaves);
}
else if (type == "hybrid_multifractal") {
Fac = noise_musgrave_hybrid_multi_fractal_4d(
p, dimension, lacunarity, octaves, Offset, Gain);
}
else if (type == "ridged_multifractal") {
Fac = noise_musgrave_ridged_multi_fractal_4d(
p, dimension, lacunarity, octaves, Offset, Gain);
}
else if (type == "hetero_terrain") {
Fac = noise_musgrave_hetero_terrain_4d(p, dimension, lacunarity, octaves, Offset);
}
else {
Fac = 0.0;
}
}
else {
Fac = 0.0;
}
}

View File

@ -432,7 +432,7 @@ ccl_device_noinline void svm_eval_nodes(KernelGlobals *kg,
svm_node_tex_voronoi(kg, sd, stack, node, &offset);
break;
case NODE_TEX_MUSGRAVE:
svm_node_tex_musgrave(kg, sd, stack, node, &offset);
svm_node_tex_musgrave(kg, sd, stack, node.y, node.z, node.w, &offset);
break;
case NODE_TEX_WAVE:
svm_node_tex_wave(kg, sd, stack, node, &offset);

View File

@ -16,7 +16,7 @@
CCL_NAMESPACE_BEGIN
/* Musgrave fBm
/* 1D Musgrave fBm
*
* H: fractal increment parameter
* lacunarity: gap between successive frequencies
@ -25,62 +25,62 @@ CCL_NAMESPACE_BEGIN
* from "Texturing and Modelling: A procedural approach"
*/
ccl_device_noinline_cpu float noise_musgrave_fBm(float3 p,
float H,
float lacunarity,
float octaves)
ccl_device_noinline_cpu float noise_musgrave_fBm_1d(float co,
float H,
float lacunarity,
float octaves)
{
float rmd;
float p = co;
float value = 0.0f;
float pwr = 1.0f;
float pwHL = powf(lacunarity, -H);
int i;
for (i = 0; i < float_to_int(octaves); i++) {
value += snoise_3d(p) * pwr;
for (int i = 0; i < float_to_int(octaves); i++) {
value += snoise_1d(p) * pwr;
pwr *= pwHL;
p *= lacunarity;
}
rmd = octaves - floorf(octaves);
if (rmd != 0.0f)
value += rmd * snoise_3d(p) * pwr;
float rmd = octaves - floorf(octaves);
if (rmd != 0.0f) {
value += rmd * snoise_1d(p) * pwr;
}
return value;
}
/* Musgrave Multifractal
/* 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(float3 p,
float H,
float lacunarity,
float octaves)
ccl_device_noinline_cpu float noise_musgrave_multi_fractal_1d(float co,
float H,
float lacunarity,
float octaves)
{
float rmd;
float p = co;
float value = 1.0f;
float pwr = 1.0f;
float pwHL = powf(lacunarity, -H);
int i;
for (i = 0; i < float_to_int(octaves); i++) {
value *= (pwr * snoise_3d(p) + 1.0f);
for (int i = 0; i < float_to_int(octaves); i++) {
value *= (pwr * snoise_1d(p) + 1.0f);
pwr *= pwHL;
p *= lacunarity;
}
rmd = octaves - floorf(octaves);
if (rmd != 0.0f)
value *= (rmd * pwr * snoise_3d(p) + 1.0f); /* correct? */
float rmd = octaves - floorf(octaves);
if (rmd != 0.0f) {
value *= (rmd * pwr * snoise_1d(p) + 1.0f); /* correct? */
}
return value;
}
/* Musgrave Heterogeneous Terrain
/* 1D Musgrave Heterogeneous Terrain
*
* H: fractal dimension of the roughest area
* lacunarity: gap between successive frequencies
@ -88,35 +88,34 @@ ccl_device_noinline_cpu float noise_musgrave_multi_fractal(float3 p,
* offset: raises the terrain from `sea level'
*/
ccl_device_noinline_cpu float noise_musgrave_hetero_terrain(
float3 p, float H, float lacunarity, float octaves, float offset)
ccl_device_noinline_cpu float noise_musgrave_hetero_terrain_1d(
float co, float H, float lacunarity, float octaves, float offset)
{
float value, increment, rmd;
float p = co;
float pwHL = powf(lacunarity, -H);
float pwr = pwHL;
int i;
/* first unscaled octave of function; later octaves are scaled */
value = offset + snoise_3d(p);
float value = offset + snoise_1d(p);
p *= lacunarity;
for (i = 1; i < float_to_int(octaves); i++) {
increment = (snoise_3d(p) + offset) * pwr * value;
for (int i = 1; i < float_to_int(octaves); i++) {
float increment = (snoise_1d(p) + offset) * pwr * value;
value += increment;
pwr *= pwHL;
p *= lacunarity;
}
rmd = octaves - floorf(octaves);
float rmd = octaves - floorf(octaves);
if (rmd != 0.0f) {
increment = (snoise_3d(p) + offset) * pwr * value;
float increment = (snoise_1d(p) + offset) * pwr * value;
value += rmd * increment;
}
return value;
}
/* Hybrid Additive/Multiplicative Multifractal Terrain
/* 1D Hybrid Additive/Multiplicative Multifractal Terrain
*
* H: fractal dimension of the roughest area
* lacunarity: gap between successive frequencies
@ -124,37 +123,38 @@ ccl_device_noinline_cpu float noise_musgrave_hetero_terrain(
* offset: raises the terrain from `sea level'
*/
ccl_device_noinline_cpu float noise_musgrave_hybrid_multi_fractal(
float3 p, float H, float lacunarity, float octaves, float offset, float gain)
ccl_device_noinline_cpu float noise_musgrave_hybrid_multi_fractal_1d(
float co, float H, float lacunarity, float octaves, float offset, float gain)
{
float result, signal, weight, rmd;
float p = co;
float pwHL = powf(lacunarity, -H);
float pwr = pwHL;
int i;
result = snoise_3d(p) + offset;
weight = gain * result;
float value = snoise_1d(p) + offset;
float weight = gain * value;
p *= lacunarity;
for (i = 1; (weight > 0.001f) && (i < float_to_int(octaves)); i++) {
if (weight > 1.0f)
for (int i = 1; (weight > 0.001f) && (i < float_to_int(octaves)); i++) {
if (weight > 1.0f) {
weight = 1.0f;
}
signal = (snoise_3d(p) + offset) * pwr;
float signal = (snoise_1d(p) + offset) * pwr;
pwr *= pwHL;
result += weight * signal;
value += weight * signal;
weight *= gain * signal;
p *= lacunarity;
}
rmd = octaves - floorf(octaves);
if (rmd != 0.0f)
result += rmd * ((snoise_3d(p) + offset) * pwr);
float rmd = octaves - floorf(octaves);
if (rmd != 0.0f) {
value += rmd * ((snoise_1d(p) + offset) * pwr);
}
return result;
return value;
}
/* Ridged Multifractal Terrain
/* 1D Ridged Multifractal Terrain
*
* H: fractal dimension of the roughest area
* lacunarity: gap between successive frequencies
@ -162,93 +162,688 @@ ccl_device_noinline_cpu float noise_musgrave_hybrid_multi_fractal(
* offset: raises the terrain from `sea level'
*/
ccl_device_noinline_cpu float noise_musgrave_ridged_multi_fractal(
float3 p, float H, float lacunarity, float octaves, float offset, float gain)
ccl_device_noinline_cpu float noise_musgrave_ridged_multi_fractal_1d(
float co, float H, float lacunarity, float octaves, float offset, float gain)
{
float result, signal, weight;
float p = co;
float pwHL = powf(lacunarity, -H);
float pwr = pwHL;
int i;
signal = offset - fabsf(snoise_3d(p));
float signal = offset - fabsf(snoise_1d(p));
signal *= signal;
result = signal;
weight = 1.0f;
float value = signal;
float weight = 1.0f;
for (i = 1; i < float_to_int(octaves); i++) {
for (int i = 1; i < float_to_int(octaves); i++) {
p *= lacunarity;
weight = saturate(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 = pwHL;
float value = snoise_2d(p) + offset;
float weight = gain * value;
p *= lacunarity;
for (int i = 1; (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) {
value += rmd * ((snoise_2d(p) + offset) * pwr);
}
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 = saturate(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 = pwHL;
float value = snoise_3d(p) + offset;
float weight = gain * value;
p *= lacunarity;
for (int i = 1; (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) {
value += rmd * ((snoise_3d(p) + offset) * pwr);
}
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 = saturate(signal * gain);
signal = offset - fabsf(snoise_3d(p));
signal *= signal;
signal *= weight;
result += signal * pwr;
value += signal * pwr;
pwr *= pwHL;
}
return result;
return value;
}
/* Shader */
/* 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 float svm_musgrave(NodeMusgraveType type,
float dimension,
float lacunarity,
float octaves,
float offset,
float intensity,
float gain,
float3 p)
ccl_device_noinline_cpu float noise_musgrave_fBm_4d(float4 co,
float H,
float lacunarity,
float octaves)
{
if (type == NODE_MUSGRAVE_MULTIFRACTAL)
return intensity * noise_musgrave_multi_fractal(p, dimension, lacunarity, octaves);
else if (type == NODE_MUSGRAVE_FBM)
return intensity * noise_musgrave_fBm(p, dimension, lacunarity, octaves);
else if (type == NODE_MUSGRAVE_HYBRID_MULTIFRACTAL)
return intensity *
noise_musgrave_hybrid_multi_fractal(p, dimension, lacunarity, octaves, offset, gain);
else if (type == NODE_MUSGRAVE_RIDGED_MULTIFRACTAL)
return intensity *
noise_musgrave_ridged_multi_fractal(p, dimension, lacunarity, octaves, offset, gain);
else if (type == NODE_MUSGRAVE_HETERO_TERRAIN)
return intensity * noise_musgrave_hetero_terrain(p, dimension, lacunarity, octaves, offset);
float4 p = co;
float value = 0.0f;
float pwr = 1.0f;
float pwHL = powf(lacunarity, -H);
return 0.0f;
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;
}
ccl_device void svm_node_tex_musgrave(
KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node, int *offset)
/* 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)
{
uint4 node2 = read_node(kg, offset);
uint4 node3 = read_node(kg, offset);
float4 p = co;
float value = 1.0f;
float pwr = 1.0f;
float pwHL = powf(lacunarity, -H);
uint type, co_offset, color_offset, fac_offset;
uint dimension_offset, lacunarity_offset, detail_offset, offset_offset;
uint gain_offset, scale_offset;
for (int i = 0; i < float_to_int(octaves); i++) {
value *= (pwr * snoise_4d(p) + 1.0f);
pwr *= pwHL;
p *= lacunarity;
}
svm_unpack_node_uchar4(node.y, &type, &co_offset, &color_offset, &fac_offset);
svm_unpack_node_uchar4(
node.z, &dimension_offset, &lacunarity_offset, &detail_offset, &offset_offset);
svm_unpack_node_uchar2(node.w, &gain_offset, &scale_offset);
float rmd = octaves - floorf(octaves);
if (rmd != 0.0f) {
value *= (rmd * pwr * snoise_4d(p) + 1.0f); /* correct? */
}
float3 co = stack_load_float3(stack, co_offset);
float dimension = stack_load_float_default(stack, dimension_offset, node2.x);
float lacunarity = stack_load_float_default(stack, lacunarity_offset, node2.y);
float detail = stack_load_float_default(stack, detail_offset, node2.z);
float foffset = stack_load_float_default(stack, offset_offset, node2.w);
float gain = stack_load_float_default(stack, gain_offset, node3.x);
float scale = stack_load_float_default(stack, scale_offset, node3.y);
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 = pwHL;
float value = snoise_4d(p) + offset;
float weight = gain * value;
p *= lacunarity;
for (int i = 1; (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) {
value += rmd * ((snoise_4d(p) + offset) * pwr);
}
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 = saturate(signal * gain);
signal = offset - fabsf(snoise_4d(p));
signal *= signal;
signal *= weight;
value += signal * pwr;
pwr *= pwHL;
}
return value;
}
ccl_device void svm_node_tex_musgrave(KernelGlobals *kg,
ShaderData *sd,
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, 16.0f);
lacunarity = fmaxf(lacunarity, 1e-5f);
float f = svm_musgrave(
(NodeMusgraveType)type, dimension, lacunarity, detail, foffset, 1.0f, gain, co * scale);
float fac;
if (stack_valid(fac_offset))
stack_store_float(stack, fac_offset, f);
if (stack_valid(color_offset))
stack_store_float3(stack, color_offset, make_float3(f, f, f));
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);
}
CCL_NAMESPACE_END

View File

@ -1183,6 +1183,13 @@ NODE_DEFINE(MusgraveTextureNode)
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);
@ -1191,16 +1198,16 @@ NODE_DEFINE(MusgraveTextureNode)
type_enum.insert("hetero_terrain", NODE_MUSGRAVE_HETERO_TERRAIN);
SOCKET_ENUM(type, "Type", type_enum, NODE_MUSGRAVE_FBM);
SOCKET_IN_POINT(
vector, "Vector", make_float3(0.0f, 0.0f, 0.0f), 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", 1.0f);
SOCKET_IN_FLOAT(offset, "Offset", 0.0f);
SOCKET_IN_FLOAT(gain, "Gain", 1.0f);
SOCKET_IN_POINT(
vector, "Vector", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_TEXTURE_GENERATED);
SOCKET_OUT_COLOR(color, "Color");
SOCKET_OUT_FLOAT(fac, "Fac");
return type;
@ -1213,35 +1220,38 @@ MusgraveTextureNode::MusgraveTextureNode() : TextureNode(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 *detail_in = input("Detail");
ShaderInput *offset_in = input("Offset");
ShaderInput *gain_in = input("Gain");
ShaderOutput *fac_out = output("Fac");
ShaderOutput *color_out = output("Color");
int vector_offset = tex_mapping.compile_begin(compiler, vector_in);
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(type,
vector_offset,
compiler.stack_assign_if_linked(color_out),
compiler.stack_assign_if_linked(fac_out)),
compiler.encode_uchar4(compiler.stack_assign_if_linked(dimension_in),
compiler.stack_assign_if_linked(lacunarity_in),
compiler.stack_assign_if_linked(detail_in),
compiler.stack_assign_if_linked(offset_in)),
compiler.encode_uchar4(compiler.stack_assign_if_linked(gain_in),
compiler.stack_assign_if_linked(scale_in)));
compiler.add_node(__float_as_int(dimension),
__float_as_int(lacunarity),
__float_as_int(detail),
__float_as_int(offset));
compiler.add_node(__float_as_int(gain), __float_as_int(scale));
compiler.add_node(
NODE_TEX_MUSGRAVE,
compiler.encode_uchar4(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_offset);
tex_mapping.compile_end(compiler, vector_in, vector_stack_offset);
}
void MusgraveTextureNode::compile(OSLCompiler &compiler)
@ -1249,6 +1259,7 @@ void MusgraveTextureNode::compile(OSLCompiler &compiler)
tex_mapping.compile(compiler);
compiler.parameter(this, "type");
compiler.parameter(this, "dimensions");
compiler.add(this, "node_musgrave_texture");
}

View File

@ -236,8 +236,9 @@ class MusgraveTextureNode : public TextureNode {
return NODE_GROUP_LEVEL_2;
}
int dimensions;
NodeMusgraveType type;
float scale, detail, dimension, lacunarity, offset, gain;
float w, scale, detail, dimension, lacunarity, offset, gain;
float3 vector;
};

View File

@ -27,7 +27,7 @@
* \note Use #STRINGIFY() rather than defining with quotes.
*/
#define BLENDER_VERSION 281
#define BLENDER_SUBVERSION 9
#define BLENDER_SUBVERSION 10
/** Several breakages with 280, e.g. collections vs layers. */
#define BLENDER_MINVERSION 280
#define BLENDER_MINSUBVERSION 0

View File

@ -911,6 +911,34 @@ static void update_mapping_node_inputs_and_properties(bNodeTree *ntree)
}
}
/* The Musgrave node now has a dimension property. This property should
* be initialized to 3 by default.
*/
static void update_musgrave_node_dimensions(bNodeTree *ntree)
{
for (bNode *node = ntree->nodes.first; node; node = node->next) {
if (node->type == SH_NODE_TEX_MUSGRAVE) {
NodeTexMusgrave *tex = (NodeTexMusgrave *)node->storage;
tex->dimensions = 3;
}
}
}
/* The Color output of the Musgrave node has been removed. Previously, this
* output was just equal to the Fac output. To correct this, we move links
* from the Color output to the Fac output if they exist.
*/
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->fromsock->type == SOCK_RGBA) {
link->fromsock = link->fromsock->next;
}
}
}
}
void blo_do_versions_cycles(FileData *UNUSED(fd), Library *UNUSED(lib), Main *bmain)
{
/* Particle shape shared with Eevee. */
@ -952,6 +980,15 @@ void blo_do_versions_cycles(FileData *UNUSED(fd), Library *UNUSED(lib), Main *bm
}
FOREACH_NODETREE_END;
}
if (!MAIN_VERSION_ATLEAST(bmain, 281, 10)) {
FOREACH_NODETREE_BEGIN (bmain, ntree, id) {
if (ntree->type == NTREE_SHADER) {
update_musgrave_node_color_output(ntree);
}
}
FOREACH_NODETREE_END;
}
}
void do_versions_after_linking_cycles(Main *bmain)
@ -1101,4 +1138,13 @@ void do_versions_after_linking_cycles(Main *bmain)
}
FOREACH_NODETREE_END;
}
if (!MAIN_VERSION_ATLEAST(bmain, 281, 10)) {
FOREACH_NODETREE_BEGIN (bmain, ntree, id) {
if (ntree->type == NTREE_SHADER) {
update_musgrave_node_dimensions(ntree);
}
}
FOREACH_NODETREE_END;
}
}

View File

@ -908,6 +908,7 @@ static void node_shader_buts_tex_wave(uiLayout *layout, bContext *UNUSED(C), Poi
static void node_shader_buts_tex_musgrave(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
uiItemR(layout, ptr, "musgrave_dimensions", 0, "", ICON_NONE);
uiItemR(layout, ptr, "musgrave_type", 0, "", ICON_NONE);
}

View File

@ -1,4 +1,4 @@
/* Musgrave fBm
/* 1D Musgrave fBm
*
* H: fractal increment parameter
* lacunarity: gap between successive frequencies
@ -7,9 +7,21 @@
* from "Texturing and Modelling: A procedural approach"
*/
float noise_musgrave_fBm(vec3 p, float H, float lacunarity, float octaves)
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 rmd;
float p = w * scale;
float H = max(dimension, 1e-5);
float octaves = clamp(detail, 0.0, 16.0);
float lacunarity = max(lac, 1e-5);
float value = 0.0;
float pwr = 1.0;
float pwHL = pow(lacunarity, -H);
@ -20,24 +32,36 @@ float noise_musgrave_fBm(vec3 p, float H, float lacunarity, float octaves)
p *= lacunarity;
}
rmd = octaves - floor(octaves);
float rmd = octaves - floor(octaves);
if (rmd != 0.0) {
value += rmd * snoise(p) * pwr;
}
return value;
fac = value;
}
/* Musgrave Multifractal
/* 1D Musgrave Multifractal
*
* H: highest fractal dimension
* lacunarity: gap between successive frequencies
* octaves: number of frequencies in the fBm
*/
float noise_musgrave_multi_fractal(vec3 p, float H, float lacunarity, float octaves)
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 rmd;
float p = w * scale;
float H = max(dimension, 1e-5);
float octaves = clamp(detail, 0.0, 16.0);
float lacunarity = max(lac, 1e-5);
float value = 1.0;
float pwr = 1.0;
float pwHL = pow(lacunarity, -H);
@ -48,15 +72,15 @@ float noise_musgrave_multi_fractal(vec3 p, float H, float lacunarity, float octa
p *= lacunarity;
}
rmd = octaves - floor(octaves);
float rmd = octaves - floor(octaves);
if (rmd != 0.0) {
value *= (rmd * pwr * snoise(p) + 1.0); /* correct? */
}
return value;
fac = value;
}
/* Musgrave Heterogeneous Terrain
/* 1D Musgrave Heterogeneous Terrain
*
* H: fractal dimension of the roughest area
* lacunarity: gap between successive frequencies
@ -64,33 +88,45 @@ float noise_musgrave_multi_fractal(vec3 p, float H, float lacunarity, float octa
* offset: raises the terrain from `sea level'
*/
float noise_musgrave_hetero_terrain(vec3 p, float H, float lacunarity, float octaves, float offset)
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 value, increment, rmd;
float p = w * scale;
float H = max(dimension, 1e-5);
float octaves = clamp(detail, 0.0, 16.0);
float lacunarity = max(lac, 1e-5);
float pwHL = pow(lacunarity, -H);
float pwr = pwHL;
/* first unscaled octave of function; later octaves are scaled */
value = offset + snoise(p);
float value = offset + snoise(p);
p *= lacunarity;
for (int i = 1; i < int(octaves); i++) {
increment = (snoise(p) + offset) * pwr * value;
float increment = (snoise(p) + offset) * pwr * value;
value += increment;
pwr *= pwHL;
p *= lacunarity;
}
rmd = octaves - floor(octaves);
float rmd = octaves - floor(octaves);
if (rmd != 0.0) {
increment = (snoise(p) + offset) * pwr * value;
float increment = (snoise(p) + offset) * pwr * value;
value += rmd * increment;
}
return value;
fac = value;
}
/* Hybrid Additive/Multiplicative Multifractal Terrain
/* 1D Hybrid Additive/Multiplicative Multifractal Terrain
*
* H: fractal dimension of the roughest area
* lacunarity: gap between successive frequencies
@ -98,15 +134,26 @@ float noise_musgrave_hetero_terrain(vec3 p, float H, float lacunarity, float oct
* offset: raises the terrain from `sea level'
*/
float noise_musgrave_hybrid_multi_fractal(
vec3 p, float H, float lacunarity, float octaves, float offset, float gain)
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 result, signal, weight, rmd;
float p = w * scale;
float H = max(dimension, 1e-5);
float octaves = clamp(detail, 0.0, 16.0);
float lacunarity = max(lac, 1e-5);
float pwHL = pow(lacunarity, -H);
float pwr = pwHL;
result = snoise(p) + offset;
weight = gain * result;
float value = snoise(p) + offset;
float weight = gain * value;
p *= lacunarity;
for (int i = 1; (weight > 0.001f) && (i < int(octaves)); i++) {
@ -114,22 +161,22 @@ float noise_musgrave_hybrid_multi_fractal(
weight = 1.0;
}
signal = (snoise(p) + offset) * pwr;
float signal = (snoise(p) + offset) * pwr;
pwr *= pwHL;
result += weight * signal;
value += weight * signal;
weight *= gain * signal;
p *= lacunarity;
}
rmd = octaves - floor(octaves);
float rmd = octaves - floor(octaves);
if (rmd != 0.0) {
result += rmd * ((snoise(p) + offset) * pwr);
value += rmd * ((snoise(p) + offset) * pwr);
}
return result;
fac = value;
}
/* Ridged Multifractal Terrain
/* 1D Ridged Multifractal Terrain
*
* H: fractal dimension of the roughest area
* lacunarity: gap between successive frequencies
@ -137,17 +184,28 @@ float noise_musgrave_hybrid_multi_fractal(
* offset: raises the terrain from `sea level'
*/
float noise_musgrave_ridged_multi_fractal(
vec3 p, float H, float lacunarity, float octaves, float offset, float gain)
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 result, signal, weight;
float p = w * scale;
float H = max(dimension, 1e-5);
float octaves = clamp(detail, 0.0, 16.0);
float lacunarity = max(lac, 1e-5);
float pwHL = pow(lacunarity, -H);
float pwr = pwHL;
signal = offset - abs(snoise(p));
float signal = offset - abs(snoise(p));
signal *= signal;
result = signal;
weight = 1.0;
float value = signal;
float weight = 1.0;
for (int i = 1; i < int(octaves); i++) {
p *= lacunarity;
@ -155,54 +213,675 @@ float noise_musgrave_ridged_multi_fractal(
signal = offset - abs(snoise(p));
signal *= signal;
signal *= weight;
result += signal * pwr;
value += signal * pwr;
pwr *= pwHL;
}
return result;
fac = value;
}
float svm_musgrave(int type,
float dimension,
float lacunarity,
float octaves,
float offset,
float intensity,
float gain,
vec3 p)
/* 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)
{
if (type == 0 /* NODE_MUSGRAVE_MULTIFRACTAL */) {
return intensity * noise_musgrave_multi_fractal(p, dimension, lacunarity, octaves);
vec2 p = co.xy * scale;
float H = max(dimension, 1e-5);
float octaves = clamp(detail, 0.0, 16.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;
}
else if (type == 1 /* NODE_MUSGRAVE_FBM */) {
return intensity * noise_musgrave_fBm(p, dimension, lacunarity, octaves);
float rmd = octaves - floor(octaves);
if (rmd != 0.0) {
value += rmd * snoise(p) * pwr;
}
else if (type == 2 /* NODE_MUSGRAVE_HYBRID_MULTIFRACTAL */) {
return intensity *
noise_musgrave_hybrid_multi_fractal(p, dimension, lacunarity, octaves, offset, gain);
}
else if (type == 3 /* NODE_MUSGRAVE_RIDGED_MULTIFRACTAL */) {
return intensity *
noise_musgrave_ridged_multi_fractal(p, dimension, lacunarity, octaves, offset, gain);
}
else if (type == 4 /* NODE_MUSGRAVE_HETERO_TERRAIN */) {
return intensity * noise_musgrave_hetero_terrain(p, dimension, lacunarity, octaves, offset);
}
return 0.0;
fac = value;
}
void node_tex_musgrave(vec3 co,
float scale,
float detail,
float dimension,
float lacunarity,
float offset,
float gain,
float type,
out vec4 color,
out float fac)
/* 2D Musgrave Multifractal
*
* 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)
{
fac = svm_musgrave(int(type), dimension, lacunarity, detail, offset, 1.0, gain, co *scale);
vec2 p = co.xy * scale;
float H = max(dimension, 1e-5);
float octaves = clamp(detail, 0.0, 16.0);
float lacunarity = max(lac, 1e-5);
color = vec4(fac, fac, fac, 1.0);
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, 16.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 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'
*/
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, 16.0);
float lacunarity = max(lac, 1e-5);
float pwHL = pow(lacunarity, -H);
float pwr = pwHL;
float value = snoise(p) + offset;
float weight = gain * value;
p *= lacunarity;
for (int i = 1; (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) {
value += rmd * ((snoise(p) + offset) * pwr);
}
fac = 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'
*/
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, 16.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, 16.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 Multifractal
*
* 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, 16.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, 16.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 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'
*/
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, 16.0);
float lacunarity = max(lac, 1e-5);
float pwHL = pow(lacunarity, -H);
float pwr = pwHL;
float value = snoise(p) + offset;
float weight = gain * value;
p *= lacunarity;
for (int i = 1; (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) {
value += rmd * ((snoise(p) + offset) * pwr);
}
fac = 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'
*/
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, 16.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, 16.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 Multifractal
*
* 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, 16.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, 16.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 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'
*/
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, 16.0);
float lacunarity = max(lac, 1e-5);
float pwHL = pow(lacunarity, -H);
float pwr = pwHL;
float value = snoise(p) + offset;
float weight = gain * value;
p *= lacunarity;
for (int i = 1; (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) {
value += rmd * ((snoise(p) + offset) * pwr);
}
fac = 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'
*/
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, 16.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;
}

View File

@ -885,7 +885,7 @@ typedef struct NodeTexVoronoi {
typedef struct NodeTexMusgrave {
NodeTexBase base;
int musgrave_type;
char _pad[4];
int dimensions;
} NodeTexMusgrave;
typedef struct NodeTexWave {

View File

@ -4389,11 +4389,17 @@ static void def_sh_tex_musgrave(StructRNA *srna)
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, NULL, "dimensions");
RNA_def_property_enum_items(prop, rna_enum_node_tex_dimensions_items);
RNA_def_property_ui_text(prop, "Dimensions", "");
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, NULL, "musgrave_type");
RNA_def_property_enum_items(prop, prop_musgrave_type);
RNA_def_property_ui_text(prop, "Type", "");
RNA_def_property_update(prop, 0, "rna_Node_update");
RNA_def_property_update(prop, 0, "rna_ShaderNode_socket_update");
}
static void def_sh_tex_voronoi(StructRNA *srna)

View File

@ -23,6 +23,7 @@
static bNodeSocketTemplate sh_node_tex_musgrave_in[] = {
{SOCK_VECTOR, 1, N_("Vector"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_NONE, SOCK_HIDE_VALUE},
{SOCK_FLOAT, 1, N_("W"), 0.0f, 0.0f, 0.0f, 0.0f, -1000.0f, 1000.0f},
{SOCK_FLOAT, 1, N_("Scale"), 5.0f, 0.0f, 0.0f, 0.0f, -1000.0f, 1000.0f},
{SOCK_FLOAT, 1, N_("Detail"), 2.0f, 0.0f, 0.0f, 0.0f, 0.0f, 16.0f},
{SOCK_FLOAT, 1, N_("Dimension"), 2.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1000.0f},
@ -33,17 +34,6 @@ static bNodeSocketTemplate sh_node_tex_musgrave_in[] = {
};
static bNodeSocketTemplate sh_node_tex_musgrave_out[] = {
{SOCK_RGBA,
0,
N_("Color"),
0.0f,
0.0f,
0.0f,
0.0f,
0.0f,
1.0f,
PROP_NONE,
SOCK_NO_INTERNAL_LINK},
{SOCK_FLOAT,
0,
N_("Fac"),
@ -64,6 +54,7 @@ static void node_shader_init_tex_musgrave(bNodeTree *UNUSED(ntree), bNode *node)
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;
}
@ -78,12 +69,77 @@ static int node_shader_gpu_tex_musgrave(GPUMaterial *mat,
node_shader_gpu_tex_mapping(mat, node, in, out);
NodeTexMusgrave *tex = (NodeTexMusgrave *)node->storage;
float type = tex->musgrave_type;
int dimensions = tex->dimensions;
int type = tex->musgrave_type;
return GPU_stack_link(mat, node, "node_tex_musgrave", in, out, GPU_constant(&type));
static const char *names[][5] = {
[SHD_MUSGRAVE_MULTIFRACTAL] =
{
"",
"node_tex_musgrave_multi_fractal_1d",
"node_tex_musgrave_multi_fractal_2d",
"node_tex_musgrave_multi_fractal_3d",
"node_tex_musgrave_multi_fractal_4d",
},
[SHD_MUSGRAVE_FBM] =
{
"",
"node_tex_musgrave_fBm_1d",
"node_tex_musgrave_fBm_2d",
"node_tex_musgrave_fBm_3d",
"node_tex_musgrave_fBm_4d",
},
[SHD_MUSGRAVE_HYBRID_MULTIFRACTAL] =
{
"",
"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",
},
[SHD_MUSGRAVE_RIDGED_MULTIFRACTAL] =
{
"",
"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",
},
[SHD_MUSGRAVE_HETERO_TERRAIN] =
{
"",
"node_tex_musgrave_hetero_terrain_1d",
"node_tex_musgrave_hetero_terrain_2d",
"node_tex_musgrave_hetero_terrain_3d",
"node_tex_musgrave_hetero_terrain_4d",
},
};
BLI_assert(type >= 0 && type < 5);
BLI_assert(dimensions > 0 && dimensions < 5);
return GPU_stack_link(mat, node, names[type][dimensions], in, out);
}
static void node_shader_update_tex_musgrave(bNodeTree *UNUSED(ntree), bNode *node)
{
NodeTexMusgrave *tex = (NodeTexMusgrave *)node->storage;
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");
nodeSetSocketAvailability(inVectorSock, tex->dimensions != 1);
nodeSetSocketAvailability(inWSock, tex->dimensions == 1 || tex->dimensions == 4);
nodeSetSocketAvailability(inOffsetSock,
tex->musgrave_type != SHD_MUSGRAVE_MULTIFRACTAL &&
tex->musgrave_type != SHD_MUSGRAVE_FBM);
nodeSetSocketAvailability(inGainSock,
tex->musgrave_type == SHD_MUSGRAVE_HYBRID_MULTIFRACTAL &&
tex->musgrave_type != SHD_MUSGRAVE_RIDGED_MULTIFRACTAL);
}
/* node type definition */
void register_node_type_sh_tex_musgrave(void)
{
static bNodeType ntype;
@ -95,6 +151,7 @@ void register_node_type_sh_tex_musgrave(void)
node_type_storage(
&ntype, "NodeTexMusgrave", node_free_standard_storage, node_copy_standard_storage);
node_type_gpu(&ntype, node_shader_gpu_tex_musgrave);
node_type_update(&ntype, node_shader_update_tex_musgrave);
nodeRegisterType(&ntype);
}