Geometry Nodes: Add shader Musgrave texture node
Port shader node musgrave texture Differential Revision: https://developer.blender.org/D12701
This commit is contained in:
parent
de6bf5d4d2
commit
729b2d026d
|
@ -722,6 +722,7 @@ geometry_node_categories = [
|
|||
]),
|
||||
GeometryNodeCategory("GEO_TEXTURE", "Texture", items=[
|
||||
NodeItem("ShaderNodeTexGradient"),
|
||||
NodeItem("ShaderNodeTexMusgrave"),
|
||||
NodeItem("ShaderNodeTexNoise"),
|
||||
NodeItem("ShaderNodeTexVoronoi"),
|
||||
NodeItem("ShaderNodeTexWhiteNoise"),
|
||||
|
|
|
@ -112,6 +112,105 @@ float3 perlin_float3_fractal_distorted(float4 position,
|
|||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Musgrave Multi Fractal
|
||||
* \{ */
|
||||
|
||||
float musgrave_ridged_multi_fractal(const float co,
|
||||
const float H,
|
||||
const float lacunarity,
|
||||
const float octaves,
|
||||
const float offset,
|
||||
const float gain);
|
||||
float musgrave_ridged_multi_fractal(const float2 co,
|
||||
const float H,
|
||||
const float lacunarity,
|
||||
const float octaves,
|
||||
const float offset,
|
||||
const float gain);
|
||||
float musgrave_ridged_multi_fractal(const float3 co,
|
||||
const float H,
|
||||
const float lacunarity,
|
||||
const float octaves,
|
||||
const float offset,
|
||||
const float gain);
|
||||
float musgrave_ridged_multi_fractal(const float4 co,
|
||||
const float H,
|
||||
const float lacunarity,
|
||||
const float octaves,
|
||||
const float offset,
|
||||
const float gain);
|
||||
|
||||
float musgrave_hybrid_multi_fractal(const float co,
|
||||
const float H,
|
||||
const float lacunarity,
|
||||
const float octaves,
|
||||
const float offset,
|
||||
const float gain);
|
||||
float musgrave_hybrid_multi_fractal(const float2 co,
|
||||
const float H,
|
||||
const float lacunarity,
|
||||
const float octaves,
|
||||
const float offset,
|
||||
const float gain);
|
||||
float musgrave_hybrid_multi_fractal(const float3 co,
|
||||
const float H,
|
||||
const float lacunarity,
|
||||
const float octaves,
|
||||
const float offset,
|
||||
const float gain);
|
||||
float musgrave_hybrid_multi_fractal(const float4 co,
|
||||
const float H,
|
||||
const float lacunarity,
|
||||
const float octaves,
|
||||
const float offset,
|
||||
const float gain);
|
||||
|
||||
float musgrave_fBm(const float co, const float H, const float lacunarity, const float octaves);
|
||||
float musgrave_fBm(const float2 co, const float H, const float lacunarity, const float octaves);
|
||||
float musgrave_fBm(const float3 co, const float H, const float lacunarity, const float octaves);
|
||||
float musgrave_fBm(const float4 co, const float H, const float lacunarity, const float octaves);
|
||||
|
||||
float musgrave_multi_fractal(const float co,
|
||||
const float H,
|
||||
const float lacunarity,
|
||||
const float octaves);
|
||||
float musgrave_multi_fractal(const float2 co,
|
||||
const float H,
|
||||
const float lacunarity,
|
||||
const float octaves);
|
||||
float musgrave_multi_fractal(const float3 co,
|
||||
const float H,
|
||||
const float lacunarity,
|
||||
const float octaves);
|
||||
float musgrave_multi_fractal(const float4 co,
|
||||
const float H,
|
||||
const float lacunarity,
|
||||
const float octaves);
|
||||
|
||||
float musgrave_hetero_terrain(const float co,
|
||||
const float H,
|
||||
const float lacunarity,
|
||||
const float octaves,
|
||||
const float offset);
|
||||
float musgrave_hetero_terrain(const float2 co,
|
||||
const float H,
|
||||
const float lacunarity,
|
||||
const float octaves,
|
||||
const float offset);
|
||||
float musgrave_hetero_terrain(const float3 co,
|
||||
const float H,
|
||||
const float lacunarity,
|
||||
const float octaves,
|
||||
const float offset);
|
||||
float musgrave_hetero_terrain(const float4 co,
|
||||
const float H,
|
||||
const float lacunarity,
|
||||
const float octaves,
|
||||
const float offset);
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Voronoi Noise
|
||||
* \{ */
|
||||
|
|
|
@ -756,6 +756,724 @@ float3 perlin_float3_fractal_distorted(float4 position,
|
|||
perlin_fractal(position + random_float4_offset(5.0f), octaves, roughness));
|
||||
}
|
||||
|
||||
/* --------------
|
||||
* Musgrave Noise
|
||||
* --------------
|
||||
*/
|
||||
|
||||
/* 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 musgrave_fBm(const float co, const float H, const float lacunarity, const float octaves)
|
||||
{
|
||||
float p = co;
|
||||
float value = 0.0f;
|
||||
float pwr = 1.0f;
|
||||
const float pwHL = powf(lacunarity, -H);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/* 1D Musgrave Multifractal
|
||||
*
|
||||
* H: highest fractal dimension
|
||||
* lacunarity: gap between successive frequencies
|
||||
* octaves: number of frequencies in the fBm
|
||||
*/
|
||||
|
||||
float musgrave_multi_fractal(const float co,
|
||||
const float H,
|
||||
const float lacunarity,
|
||||
const float octaves)
|
||||
{
|
||||
float p = co;
|
||||
float value = 1.0f;
|
||||
float pwr = 1.0f;
|
||||
const float pwHL = powf(lacunarity, -H);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/* 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 musgrave_hetero_terrain(
|
||||
const float co, const float H, const float lacunarity, const float octaves, const float offset)
|
||||
{
|
||||
float p = co;
|
||||
const float pwHL = powf(lacunarity, -H);
|
||||
float pwr = pwHL;
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
/* 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 musgrave_hybrid_multi_fractal(const float co,
|
||||
const float H,
|
||||
const float lacunarity,
|
||||
const float octaves,
|
||||
const float offset,
|
||||
const float gain)
|
||||
{
|
||||
float p = co;
|
||||
const float pwHL = powf(lacunarity, -H);
|
||||
float pwr = pwHL;
|
||||
|
||||
float value = perlin_signed(p) + offset;
|
||||
float weight = gain * value;
|
||||
p *= lacunarity;
|
||||
|
||||
for (int i = 1; (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) {
|
||||
value += rmd * ((perlin_signed(p) + offset) * pwr);
|
||||
}
|
||||
|
||||
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 musgrave_ridged_multi_fractal(const float co,
|
||||
const float H,
|
||||
const float lacunarity,
|
||||
const float octaves,
|
||||
const float offset,
|
||||
const float gain)
|
||||
{
|
||||
float p = co;
|
||||
const float pwHL = powf(lacunarity, -H);
|
||||
float pwr = pwHL;
|
||||
|
||||
float signal = offset - fabsf(perlin_signed(p));
|
||||
signal *= signal;
|
||||
float value = signal;
|
||||
float weight = 1.0f;
|
||||
|
||||
for (int i = 1; i < (int)octaves; i++) {
|
||||
p *= lacunarity;
|
||||
weight = CLAMPIS(signal * gain, 0.0f, 1.0f);
|
||||
signal = offset - fabsf(perlin_signed(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 musgrave_fBm(const float2 co, const float H, const float lacunarity, const float octaves)
|
||||
{
|
||||
float2 p = co;
|
||||
float value = 0.0f;
|
||||
float pwr = 1.0f;
|
||||
const float pwHL = powf(lacunarity, -H);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/* 2D Musgrave Multifractal
|
||||
*
|
||||
* H: highest fractal dimension
|
||||
* lacunarity: gap between successive frequencies
|
||||
* octaves: number of frequencies in the fBm
|
||||
*/
|
||||
|
||||
float musgrave_multi_fractal(const float2 co,
|
||||
const float H,
|
||||
const float lacunarity,
|
||||
const float octaves)
|
||||
{
|
||||
float2 p = co;
|
||||
float value = 1.0f;
|
||||
float pwr = 1.0f;
|
||||
const float pwHL = powf(lacunarity, -H);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/* 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 musgrave_hetero_terrain(const float2 co,
|
||||
const float H,
|
||||
const float lacunarity,
|
||||
const float octaves,
|
||||
const float offset)
|
||||
{
|
||||
float2 p = co;
|
||||
const float pwHL = powf(lacunarity, -H);
|
||||
float pwr = pwHL;
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
/* 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 musgrave_hybrid_multi_fractal(const float2 co,
|
||||
const float H,
|
||||
const float lacunarity,
|
||||
const float octaves,
|
||||
const float offset,
|
||||
const float gain)
|
||||
{
|
||||
float2 p = co;
|
||||
const float pwHL = powf(lacunarity, -H);
|
||||
float pwr = pwHL;
|
||||
|
||||
float value = perlin_signed(p) + offset;
|
||||
float weight = gain * value;
|
||||
p *= lacunarity;
|
||||
|
||||
for (int i = 1; (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) {
|
||||
value += rmd * ((perlin_signed(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 musgrave_ridged_multi_fractal(const float2 co,
|
||||
const float H,
|
||||
const float lacunarity,
|
||||
const float octaves,
|
||||
const float offset,
|
||||
const float gain)
|
||||
{
|
||||
float2 p = co;
|
||||
const float pwHL = powf(lacunarity, -H);
|
||||
float pwr = pwHL;
|
||||
|
||||
float signal = offset - fabsf(perlin_signed(p));
|
||||
signal *= signal;
|
||||
float value = signal;
|
||||
float weight = 1.0f;
|
||||
|
||||
for (int i = 1; i < (int)octaves; i++) {
|
||||
p *= lacunarity;
|
||||
weight = CLAMPIS(signal * gain, 0.0f, 1.0f);
|
||||
signal = offset - fabsf(perlin_signed(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 musgrave_fBm(const float3 co, const float H, const float lacunarity, const float octaves)
|
||||
{
|
||||
float3 p = co;
|
||||
float value = 0.0f;
|
||||
float pwr = 1.0f;
|
||||
const float pwHL = powf(lacunarity, -H);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/* 3D Musgrave Multifractal
|
||||
*
|
||||
* H: highest fractal dimension
|
||||
* lacunarity: gap between successive frequencies
|
||||
* octaves: number of frequencies in the fBm
|
||||
*/
|
||||
|
||||
float musgrave_multi_fractal(const float3 co,
|
||||
const float H,
|
||||
const float lacunarity,
|
||||
const float octaves)
|
||||
{
|
||||
float3 p = co;
|
||||
float value = 1.0f;
|
||||
float pwr = 1.0f;
|
||||
const float pwHL = powf(lacunarity, -H);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/* 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 musgrave_hetero_terrain(const float3 co,
|
||||
const float H,
|
||||
const float lacunarity,
|
||||
const float octaves,
|
||||
const float offset)
|
||||
{
|
||||
float3 p = co;
|
||||
const float pwHL = powf(lacunarity, -H);
|
||||
float pwr = pwHL;
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
/* 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 musgrave_hybrid_multi_fractal(const float3 co,
|
||||
const float H,
|
||||
const float lacunarity,
|
||||
const float octaves,
|
||||
const float offset,
|
||||
const float gain)
|
||||
{
|
||||
float3 p = co;
|
||||
const float pwHL = powf(lacunarity, -H);
|
||||
float pwr = pwHL;
|
||||
|
||||
float value = perlin_signed(p) + offset;
|
||||
float weight = gain * value;
|
||||
p *= lacunarity;
|
||||
|
||||
for (int i = 1; (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) {
|
||||
value += rmd * ((perlin_signed(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 musgrave_ridged_multi_fractal(const float3 co,
|
||||
const float H,
|
||||
const float lacunarity,
|
||||
const float octaves,
|
||||
const float offset,
|
||||
const float gain)
|
||||
{
|
||||
float3 p = co;
|
||||
const float pwHL = powf(lacunarity, -H);
|
||||
float pwr = pwHL;
|
||||
|
||||
float signal = offset - fabsf(perlin_signed(p));
|
||||
signal *= signal;
|
||||
float value = signal;
|
||||
float weight = 1.0f;
|
||||
|
||||
for (int i = 1; i < (int)octaves; i++) {
|
||||
p *= lacunarity;
|
||||
weight = CLAMPIS(signal * gain, 0.0f, 1.0f);
|
||||
signal = offset - fabsf(perlin_signed(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 musgrave_fBm(const float4 co, const float H, const float lacunarity, const float octaves)
|
||||
{
|
||||
float4 p = co;
|
||||
float value = 0.0f;
|
||||
float pwr = 1.0f;
|
||||
const float pwHL = powf(lacunarity, -H);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/* 4D Musgrave Multifractal
|
||||
*
|
||||
* H: highest fractal dimension
|
||||
* lacunarity: gap between successive frequencies
|
||||
* octaves: number of frequencies in the fBm
|
||||
*/
|
||||
|
||||
float musgrave_multi_fractal(const float4 co,
|
||||
const float H,
|
||||
const float lacunarity,
|
||||
const float octaves)
|
||||
{
|
||||
float4 p = co;
|
||||
float value = 1.0f;
|
||||
float pwr = 1.0f;
|
||||
const float pwHL = powf(lacunarity, -H);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/* 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 musgrave_hetero_terrain(const float4 co,
|
||||
const float H,
|
||||
const float lacunarity,
|
||||
const float octaves,
|
||||
const float offset)
|
||||
{
|
||||
float4 p = co;
|
||||
const float pwHL = powf(lacunarity, -H);
|
||||
float pwr = pwHL;
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
/* 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 musgrave_hybrid_multi_fractal(const float4 co,
|
||||
const float H,
|
||||
const float lacunarity,
|
||||
const float octaves,
|
||||
const float offset,
|
||||
const float gain)
|
||||
{
|
||||
float4 p = co;
|
||||
const float pwHL = powf(lacunarity, -H);
|
||||
float pwr = pwHL;
|
||||
|
||||
float value = perlin_signed(p) + offset;
|
||||
float weight = gain * value;
|
||||
p *= lacunarity;
|
||||
|
||||
for (int i = 1; (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) {
|
||||
value += rmd * ((perlin_signed(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 musgrave_ridged_multi_fractal(const float4 co,
|
||||
const float H,
|
||||
const float lacunarity,
|
||||
const float octaves,
|
||||
const float offset,
|
||||
const float gain)
|
||||
{
|
||||
float4 p = co;
|
||||
const float pwHL = powf(lacunarity, -H);
|
||||
float pwr = pwHL;
|
||||
|
||||
float signal = offset - fabsf(perlin_signed(p));
|
||||
signal *= signal;
|
||||
float value = signal;
|
||||
float weight = 1.0f;
|
||||
|
||||
for (int i = 1; i < (int)octaves; i++) {
|
||||
p *= lacunarity;
|
||||
weight = CLAMPIS(signal * gain, 0.0f, 1.0f);
|
||||
signal = offset - fabsf(perlin_signed(p));
|
||||
signal *= signal;
|
||||
signal *= weight;
|
||||
value += signal * pwr;
|
||||
pwr *= pwHL;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
/*
|
||||
* Voronoi: Ported from Cycles code.
|
||||
*
|
||||
|
|
|
@ -19,12 +19,14 @@
|
|||
|
||||
#include "../node_shader_util.h"
|
||||
|
||||
#include "BLI_noise.hh"
|
||||
|
||||
namespace blender::nodes {
|
||||
|
||||
static void sh_node_tex_musgrave_declare(NodeDeclarationBuilder &b)
|
||||
{
|
||||
b.is_function_node();
|
||||
b.add_input<decl::Vector>("Vector").hide_value();
|
||||
b.add_input<decl::Vector>("Vector").hide_value().implicit_field();
|
||||
b.add_input<decl::Float>("W").min(-1000.0f).max(1000.0f);
|
||||
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(16.0f).default_value(2.0f);
|
||||
|
@ -124,11 +126,414 @@ static void node_shader_update_tex_musgrave(bNodeTree *UNUSED(ntree), bNode *nod
|
|||
node_sock_label(outFacSock, "Height");
|
||||
}
|
||||
|
||||
namespace blender::nodes {
|
||||
|
||||
class MusgraveFunction : public fn::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<fn::MFSignature, 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 fn::MFSignature create_signature(const int dimensions, const int musgrave_type)
|
||||
{
|
||||
fn::MFSignatureBuilder signature{"Musgrave"};
|
||||
|
||||
if (ELEM(dimensions, 2, 3, 4)) {
|
||||
signature.single_input<float3>("Vector");
|
||||
}
|
||||
if (ELEM(dimensions, 1, 4)) {
|
||||
signature.single_input<float>("W");
|
||||
}
|
||||
signature.single_input<float>("Scale");
|
||||
signature.single_input<float>("Detail");
|
||||
signature.single_input<float>("Dimension");
|
||||
signature.single_input<float>("Lacunarity");
|
||||
if (ELEM(musgrave_type,
|
||||
SHD_MUSGRAVE_RIDGED_MULTIFRACTAL,
|
||||
SHD_MUSGRAVE_HYBRID_MULTIFRACTAL,
|
||||
SHD_MUSGRAVE_HETERO_TERRAIN)) {
|
||||
signature.single_input<float>("Offset");
|
||||
}
|
||||
if (ELEM(musgrave_type, SHD_MUSGRAVE_RIDGED_MULTIFRACTAL, SHD_MUSGRAVE_HYBRID_MULTIFRACTAL)) {
|
||||
signature.single_input<float>("Gain");
|
||||
}
|
||||
|
||||
signature.single_output<float>("Fac");
|
||||
|
||||
return signature.build();
|
||||
}
|
||||
|
||||
void call(IndexMask mask, fn::MFParams params, fn::MFContext UNUSED(context)) const override
|
||||
{
|
||||
auto get_vector = [&](int param_index) -> const VArray<float3> & {
|
||||
return params.readonly_single_input<float3>(param_index, "Vector");
|
||||
};
|
||||
auto get_w = [&](int param_index) -> const VArray<float> & {
|
||||
return params.readonly_single_input<float>(param_index, "W");
|
||||
};
|
||||
auto get_scale = [&](int param_index) -> const VArray<float> & {
|
||||
return params.readonly_single_input<float>(param_index, "Scale");
|
||||
};
|
||||
auto get_detail = [&](int param_index) -> const VArray<float> & {
|
||||
return params.readonly_single_input<float>(param_index, "Detail");
|
||||
};
|
||||
auto get_dimension = [&](int param_index) -> const VArray<float> & {
|
||||
return params.readonly_single_input<float>(param_index, "Dimension");
|
||||
};
|
||||
auto get_lacunarity = [&](int param_index) -> const VArray<float> & {
|
||||
return params.readonly_single_input<float>(param_index, "Lacunarity");
|
||||
};
|
||||
auto get_offset = [&](int param_index) -> const VArray<float> & {
|
||||
return params.readonly_single_input<float>(param_index, "Offset");
|
||||
};
|
||||
auto get_gain = [&](int param_index) -> const 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) {
|
||||
for (int64_t i : mask) {
|
||||
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) {
|
||||
for (int64_t i : mask) {
|
||||
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) {
|
||||
for (int64_t i : mask) {
|
||||
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) {
|
||||
for (int64_t i : mask) {
|
||||
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) {
|
||||
for (int64_t i : mask) {
|
||||
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) {
|
||||
for (int64_t i : mask) {
|
||||
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) {
|
||||
for (int64_t i : mask) {
|
||||
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) {
|
||||
for (int64_t i : mask) {
|
||||
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) {
|
||||
for (int64_t i : mask) {
|
||||
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) {
|
||||
for (int64_t i : mask) {
|
||||
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) {
|
||||
for (int64_t i : mask) {
|
||||
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) {
|
||||
for (int64_t i : mask) {
|
||||
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) {
|
||||
for (int64_t i : mask) {
|
||||
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) {
|
||||
for (int64_t i : mask) {
|
||||
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) {
|
||||
for (int64_t i : mask) {
|
||||
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) {
|
||||
for (int64_t i : mask) {
|
||||
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) {
|
||||
for (int64_t i : mask) {
|
||||
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) {
|
||||
for (int64_t i : mask) {
|
||||
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) {
|
||||
for (int64_t i : mask) {
|
||||
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) {
|
||||
for (int64_t i : mask) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}; // namespace blender::nodes
|
||||
|
||||
static void sh_node_musgrave_build_multi_function(
|
||||
blender::nodes::NodeMultiFunctionBuilder &builder)
|
||||
{
|
||||
bNode &node = builder.node();
|
||||
NodeTexMusgrave *tex = (NodeTexMusgrave *)node.storage;
|
||||
builder.construct_and_set_matching_fn<MusgraveFunction>(tex->dimensions, tex->musgrave_type);
|
||||
}
|
||||
|
||||
} // namespace blender::nodes
|
||||
|
||||
void register_node_type_sh_tex_musgrave(void)
|
||||
{
|
||||
static bNodeType ntype;
|
||||
|
||||
sh_node_type_base(&ntype, SH_NODE_TEX_MUSGRAVE, "Musgrave Texture", NODE_CLASS_TEXTURE, 0);
|
||||
sh_fn_node_type_base(&ntype, SH_NODE_TEX_MUSGRAVE, "Musgrave Texture", NODE_CLASS_TEXTURE, 0);
|
||||
ntype.declare = blender::nodes::sh_node_tex_musgrave_declare;
|
||||
node_type_size_preset(&ntype, NODE_SIZE_MIDDLE);
|
||||
node_type_init(&ntype, node_shader_init_tex_musgrave);
|
||||
|
@ -136,6 +541,7 @@ void register_node_type_sh_tex_musgrave(void)
|
|||
&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);
|
||||
ntype.build_multi_function = blender::nodes::sh_node_musgrave_build_multi_function;
|
||||
|
||||
nodeRegisterType(&ntype);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue