Shading: add Roughness input to Noise and Wave texture nodes

Currently in fractal_noise functions, each subsequent octave doubles the
frequency and reduces the amplitude by half. This patch introduces Roughness
input to Noise and Wave nodes. This multiplier determines how quickly the
amplitudes of the subsequent octaves decrease.

Value of 0.5 will be the default, generating identical noise we had before.
Values above 0.5 will increase influence of each octave resulting in more
"rough" noise, most interesting pattern changes happen there. Values below
0.5 will result in more "smooth" noise.

Differential Revision: https://developer.blender.org/D7065
This commit is contained in:
Bartosz Moniewski 2020-03-26 14:43:53 +01:00 committed by Brecht Van Lommel
parent f3433fcd3b
commit 054950def9
13 changed files with 272 additions and 181 deletions

View File

@ -84,114 +84,118 @@ float safe_snoise(vector4 p)
}
/* The fractal_noise functions are all exactly the same except for the input type. */
float fractal_noise(float p, float details)
float fractal_noise(float p, float details, float roughness)
{
float fscale = 1.0;
float amp = 1.0;
float maxamp = 0.0;
float sum = 0.0;
float octaves = clamp(details, 0.0, 16.0);
int n = (int)octaves;
for (int i = 0; i <= n; i++) {
float t = safe_noise(fscale * p);
sum += t * amp;
amp *= 0.5;
maxamp += amp;
amp *= clamp(roughness, 0.0, 1.0);
fscale *= 2.0;
}
float rmd = octaves - floor(octaves);
if (rmd != 0.0) {
float t = safe_noise(fscale * p);
float sum2 = sum + t * amp;
sum *= ((float)(1 << n) / (float)((1 << (n + 1)) - 1));
sum2 *= ((float)(1 << (n + 1)) / (float)((1 << (n + 2)) - 1));
sum /= maxamp;
sum2 /= maxamp + amp;
return (1.0 - rmd) * sum + rmd * sum2;
}
else {
sum *= ((float)(1 << n) / (float)((1 << (n + 1)) - 1));
return sum;
return sum / maxamp;
}
}
/* The fractal_noise functions are all exactly the same except for the input type. */
float fractal_noise(vector2 p, float details)
float fractal_noise(vector2 p, float details, float roughness)
{
float fscale = 1.0;
float amp = 1.0;
float maxamp = 0.0;
float sum = 0.0;
float octaves = clamp(details, 0.0, 16.0);
int n = (int)octaves;
for (int i = 0; i <= n; i++) {
float t = safe_noise(fscale * p);
sum += t * amp;
amp *= 0.5;
maxamp += amp;
amp *= clamp(roughness, 0.0, 1.0);
fscale *= 2.0;
}
float rmd = octaves - floor(octaves);
if (rmd != 0.0) {
float t = safe_noise(fscale * p);
float sum2 = sum + t * amp;
sum *= ((float)(1 << n) / (float)((1 << (n + 1)) - 1));
sum2 *= ((float)(1 << (n + 1)) / (float)((1 << (n + 2)) - 1));
sum /= maxamp;
sum2 /= maxamp + amp;
return (1.0 - rmd) * sum + rmd * sum2;
}
else {
sum *= ((float)(1 << n) / (float)((1 << (n + 1)) - 1));
return sum;
return sum / maxamp;
}
}
/* The fractal_noise functions are all exactly the same except for the input type. */
float fractal_noise(vector3 p, float details)
float fractal_noise(vector3 p, float details, float roughness)
{
float fscale = 1.0;
float amp = 1.0;
float maxamp = 0.0;
float sum = 0.0;
float octaves = clamp(details, 0.0, 16.0);
int n = (int)octaves;
for (int i = 0; i <= n; i++) {
float t = safe_noise(fscale * p);
sum += t * amp;
amp *= 0.5;
maxamp += amp;
amp *= clamp(roughness, 0.0, 1.0);
fscale *= 2.0;
}
float rmd = octaves - floor(octaves);
if (rmd != 0.0) {
float t = safe_noise(fscale * p);
float sum2 = sum + t * amp;
sum *= ((float)(1 << n) / (float)((1 << (n + 1)) - 1));
sum2 *= ((float)(1 << (n + 1)) / (float)((1 << (n + 2)) - 1));
sum /= maxamp;
sum2 /= maxamp + amp;
return (1.0 - rmd) * sum + rmd * sum2;
}
else {
sum *= ((float)(1 << n) / (float)((1 << (n + 1)) - 1));
return sum;
return sum / maxamp;
}
}
/* The fractal_noise functions are all exactly the same except for the input type. */
float fractal_noise(vector4 p, float details)
float fractal_noise(vector4 p, float details, float roughness)
{
float fscale = 1.0;
float amp = 1.0;
float maxamp = 0.0;
float sum = 0.0;
float octaves = clamp(details, 0.0, 16.0);
int n = (int)octaves;
for (int i = 0; i <= n; i++) {
float t = safe_noise(fscale * p);
sum += t * amp;
amp *= 0.5;
maxamp += amp;
amp *= clamp(roughness, 0.0, 1.0);
fscale *= 2.0;
}
float rmd = octaves - floor(octaves);
if (rmd != 0.0) {
float t = safe_noise(fscale * p);
float sum2 = sum + t * amp;
sum *= ((float)(1 << n) / (float)((1 << (n + 1)) - 1));
sum2 *= ((float)(1 << (n + 1)) / (float)((1 << (n + 2)) - 1));
sum /= maxamp;
sum2 /= maxamp + amp;
return (1.0 - rmd) * sum + rmd * sum2;
}
else {
sum *= ((float)(1 << n) / (float)((1 << (n + 1)) - 1));
return sum;
return sum / maxamp;
}
}

View File

@ -55,21 +55,22 @@ vector4 random_vector4_offset(float seed)
100.0 + noise("hash", seed, 3.0) * 100.0);
}
float noise_texture(float co, float detail, float distortion, output color Color)
float noise_texture(float co, float detail, float roughness, float distortion, output color Color)
{
float p = co;
if (distortion != 0.0) {
p += safe_snoise(p + random_float_offset(0.0)) * distortion;
}
float value = fractal_noise(p, detail);
float value = fractal_noise(p, detail, roughness);
Color = color(value,
fractal_noise(p + random_float_offset(1.0), detail),
fractal_noise(p + random_float_offset(2.0), detail));
fractal_noise(p + random_float_offset(1.0), detail, roughness),
fractal_noise(p + random_float_offset(2.0), detail, roughness));
return value;
}
float noise_texture(vector2 co, float detail, float distortion, output color Color)
float noise_texture(
vector2 co, float detail, float roughness, float distortion, output color Color)
{
vector2 p = co;
if (distortion != 0.0) {
@ -77,14 +78,15 @@ float noise_texture(vector2 co, float detail, float distortion, output color Col
safe_snoise(p + random_vector2_offset(1.0)) * distortion);
}
float value = fractal_noise(p, detail);
float value = fractal_noise(p, detail, roughness);
Color = color(value,
fractal_noise(p + random_vector2_offset(2.0), detail),
fractal_noise(p + random_vector2_offset(3.0), detail));
fractal_noise(p + random_vector2_offset(2.0), detail, roughness),
fractal_noise(p + random_vector2_offset(3.0), detail, roughness));
return value;
}
float noise_texture(vector3 co, float detail, float distortion, output color Color)
float noise_texture(
vector3 co, float detail, float roughness, float distortion, output color Color)
{
vector3 p = co;
if (distortion != 0.0) {
@ -93,14 +95,15 @@ float noise_texture(vector3 co, float detail, float distortion, output color Col
safe_snoise(p + random_vector3_offset(2.0)) * distortion);
}
float value = fractal_noise(p, detail);
float value = fractal_noise(p, detail, roughness);
Color = color(value,
fractal_noise(p + random_vector3_offset(3.0), detail),
fractal_noise(p + random_vector3_offset(4.0), detail));
fractal_noise(p + random_vector3_offset(3.0), detail, roughness),
fractal_noise(p + random_vector3_offset(4.0), detail, roughness));
return value;
}
float noise_texture(vector4 co, float detail, float distortion, output color Color)
float noise_texture(
vector4 co, float detail, float roughness, float distortion, output color Color)
{
vector4 p = co;
if (distortion != 0.0) {
@ -110,10 +113,10 @@ float noise_texture(vector4 co, float detail, float distortion, output color Col
safe_snoise(p + random_vector4_offset(3.0)) * distortion);
}
float value = fractal_noise(p, detail);
float value = fractal_noise(p, detail, roughness);
Color = color(value,
fractal_noise(p + random_vector4_offset(4.0), detail),
fractal_noise(p + random_vector4_offset(5.0), detail));
fractal_noise(p + random_vector4_offset(4.0), detail, roughness),
fractal_noise(p + random_vector4_offset(5.0), detail, roughness));
return value;
}
@ -124,6 +127,7 @@ shader node_noise_texture(int use_mapping = 0,
float W = 0.0,
float Scale = 5.0,
float Detail = 2.0,
float Roughness = 0.5,
float Distortion = 0.0,
output float Fac = 0.0,
output color Color = 0.0)
@ -136,13 +140,13 @@ shader node_noise_texture(int use_mapping = 0,
float w = W * Scale;
if (dimensions == "1D")
Fac = noise_texture(w, Detail, Distortion, Color);
Fac = noise_texture(w, Detail, Roughness, Distortion, Color);
else if (dimensions == "2D")
Fac = noise_texture(vector2(p[0], p[1]), Detail, Distortion, Color);
Fac = noise_texture(vector2(p[0], p[1]), Detail, Roughness, Distortion, Color);
else if (dimensions == "3D")
Fac = noise_texture(p, Detail, Distortion, Color);
Fac = noise_texture(p, Detail, Roughness, Distortion, Color);
else if (dimensions == "4D")
Fac = noise_texture(vector4(p[0], p[1], p[2], w), Detail, Distortion, Color);
Fac = noise_texture(vector4(p[0], p[1], p[2], w), Detail, Roughness, Distortion, Color);
else
error("Unknown dimension!");
}

View File

@ -24,9 +24,10 @@ float wave(point p_input,
string bands_direction,
string rings_direction,
string profile,
float detail,
float distortion,
float detail,
float dscale,
float droughness,
float phase)
{
/* Prevent precision issues on unit coordinates. */
@ -67,7 +68,7 @@ float wave(point p_input,
n += phase;
if (distortion != 0.0) {
n = n + (distortion * (fractal_noise(p * dscale, detail) * 2.0 - 1.0));
n = n + (distortion * (fractal_noise(p * dscale, detail, droughness) * 2.0 - 1.0));
}
if (profile == "sine") {
@ -93,6 +94,7 @@ shader node_wave_texture(int use_mapping = 0,
float Distortion = 0.0,
float Detail = 2.0,
float DetailScale = 1.0,
float DetailRoughness = 0.5,
float PhaseOffset = 0.0,
point Vector = P,
output float Fac = 0.0,
@ -108,9 +110,10 @@ shader node_wave_texture(int use_mapping = 0,
bands_direction,
rings_direction,
profile,
Detail,
Distortion,
Detail,
DetailScale,
DetailRoughness,
PhaseOffset);
Color = Fac;
}

View File

@ -17,114 +17,118 @@
CCL_NAMESPACE_BEGIN
/* The fractal_noise_[1-4] functions are all exactly the same except for the input type. */
ccl_device_noinline float fractal_noise_1d(float p, float octaves)
ccl_device_noinline float fractal_noise_1d(float p, float octaves, float roughness)
{
float fscale = 1.0f;
float amp = 1.0f;
float maxamp = 0.0f;
float sum = 0.0f;
octaves = clamp(octaves, 0.0f, 16.0f);
int n = float_to_int(octaves);
for (int i = 0; i <= n; i++) {
float t = noise_1d(fscale * p);
sum += t * amp;
amp *= 0.5f;
maxamp += amp;
amp *= clamp(roughness, 0.0f, 1.0f);
fscale *= 2.0f;
}
float rmd = octaves - floorf(octaves);
if (rmd != 0.0f) {
float t = noise_1d(fscale * p);
float sum2 = sum + t * amp;
sum *= ((float)(1 << n) / (float)((1 << (n + 1)) - 1));
sum2 *= ((float)(1 << (n + 1)) / (float)((1 << (n + 2)) - 1));
sum /= maxamp;
sum2 /= maxamp + amp;
return (1.0f - rmd) * sum + rmd * sum2;
}
else {
sum *= ((float)(1 << n) / (float)((1 << (n + 1)) - 1));
return sum;
return sum / maxamp;
}
}
/* The fractal_noise_[1-4] functions are all exactly the same except for the input type. */
ccl_device_noinline float fractal_noise_2d(float2 p, float octaves)
ccl_device_noinline float fractal_noise_2d(float2 p, float octaves, float roughness)
{
float fscale = 1.0f;
float amp = 1.0f;
float maxamp = 0.0f;
float sum = 0.0f;
octaves = clamp(octaves, 0.0f, 16.0f);
int n = float_to_int(octaves);
for (int i = 0; i <= n; i++) {
float t = noise_2d(fscale * p);
sum += t * amp;
amp *= 0.5f;
maxamp += amp;
amp *= clamp(roughness, 0.0f, 1.0f);
fscale *= 2.0f;
}
float rmd = octaves - floorf(octaves);
if (rmd != 0.0f) {
float t = noise_2d(fscale * p);
float sum2 = sum + t * amp;
sum *= ((float)(1 << n) / (float)((1 << (n + 1)) - 1));
sum2 *= ((float)(1 << (n + 1)) / (float)((1 << (n + 2)) - 1));
sum /= maxamp;
sum2 /= maxamp + amp;
return (1.0f - rmd) * sum + rmd * sum2;
}
else {
sum *= ((float)(1 << n) / (float)((1 << (n + 1)) - 1));
return sum;
return sum / maxamp;
}
}
/* The fractal_noise_[1-4] functions are all exactly the same except for the input type. */
ccl_device_noinline float fractal_noise_3d(float3 p, float octaves)
ccl_device_noinline float fractal_noise_3d(float3 p, float octaves, float roughness)
{
float fscale = 1.0f;
float amp = 1.0f;
float maxamp = 0.0f;
float sum = 0.0f;
octaves = clamp(octaves, 0.0f, 16.0f);
int n = float_to_int(octaves);
for (int i = 0; i <= n; i++) {
float t = noise_3d(fscale * p);
sum += t * amp;
amp *= 0.5f;
maxamp += amp;
amp *= clamp(roughness, 0.0f, 1.0f);
fscale *= 2.0f;
}
float rmd = octaves - floorf(octaves);
if (rmd != 0.0f) {
float t = noise_3d(fscale * p);
float sum2 = sum + t * amp;
sum *= ((float)(1 << n) / (float)((1 << (n + 1)) - 1));
sum2 *= ((float)(1 << (n + 1)) / (float)((1 << (n + 2)) - 1));
sum /= maxamp;
sum2 /= maxamp + amp;
return (1.0f - rmd) * sum + rmd * sum2;
}
else {
sum *= ((float)(1 << n) / (float)((1 << (n + 1)) - 1));
return sum;
return sum / maxamp;
}
}
/* The fractal_noise_[1-4] functions are all exactly the same except for the input type. */
ccl_device_noinline float fractal_noise_4d(float4 p, float octaves)
ccl_device_noinline float fractal_noise_4d(float4 p, float octaves, float roughness)
{
float fscale = 1.0f;
float amp = 1.0f;
float maxamp = 0.0f;
float sum = 0.0f;
octaves = clamp(octaves, 0.0f, 16.0f);
int n = float_to_int(octaves);
for (int i = 0; i <= n; i++) {
float t = noise_4d(fscale * p);
sum += t * amp;
amp *= 0.5f;
maxamp += amp;
amp *= clamp(roughness, 0.0f, 1.0f);
fscale *= 2.0f;
}
float rmd = octaves - floorf(octaves);
if (rmd != 0.0f) {
float t = noise_4d(fscale * p);
float sum2 = sum + t * amp;
sum *= ((float)(1 << n) / (float)((1 << (n + 1)) - 1));
sum2 *= ((float)(1 << (n + 1)) / (float)((1 << (n + 2)) - 1));
sum /= maxamp;
sum2 /= maxamp + amp;
return (1.0f - rmd) * sum + rmd * sum2;
}
else {
sum *= ((float)(1 << n) / (float)((1 << (n + 1)) - 1));
return sum;
return sum / maxamp;
}
}

View File

@ -50,24 +50,34 @@ ccl_device_inline float4 random_float4_offset(float seed)
100.0f + hash_float2_to_float(make_float2(seed, 3.0f)) * 100.0f);
}
ccl_device void noise_texture_1d(
float co, float detail, float distortion, bool color_is_needed, float *value, float3 *color)
ccl_device void noise_texture_1d(float co,
float detail,
float roughness,
float distortion,
bool color_is_needed,
float *value,
float3 *color)
{
float p = co;
if (distortion != 0.0f) {
p += snoise_1d(p + random_float_offset(0.0f)) * distortion;
}
*value = fractal_noise_1d(p, detail);
*value = fractal_noise_1d(p, detail, roughness);
if (color_is_needed) {
*color = make_float3(*value,
fractal_noise_1d(p + random_float_offset(1.0f), detail),
fractal_noise_1d(p + random_float_offset(2.0f), detail));
fractal_noise_1d(p + random_float_offset(1.0f), detail, roughness),
fractal_noise_1d(p + random_float_offset(2.0f), detail, roughness));
}
}
ccl_device void noise_texture_2d(
float2 co, float detail, float distortion, bool color_is_needed, float *value, float3 *color)
ccl_device void noise_texture_2d(float2 co,
float detail,
float roughness,
float distortion,
bool color_is_needed,
float *value,
float3 *color)
{
float2 p = co;
if (distortion != 0.0f) {
@ -75,16 +85,21 @@ ccl_device void noise_texture_2d(
snoise_2d(p + random_float2_offset(1.0f)) * distortion);
}
*value = fractal_noise_2d(p, detail);
*value = fractal_noise_2d(p, detail, roughness);
if (color_is_needed) {
*color = make_float3(*value,
fractal_noise_2d(p + random_float2_offset(2.0f), detail),
fractal_noise_2d(p + random_float2_offset(3.0f), detail));
fractal_noise_2d(p + random_float2_offset(2.0f), detail, roughness),
fractal_noise_2d(p + random_float2_offset(3.0f), detail, roughness));
}
}
ccl_device void noise_texture_3d(
float3 co, float detail, float distortion, bool color_is_needed, float *value, float3 *color)
ccl_device void noise_texture_3d(float3 co,
float detail,
float roughness,
float distortion,
bool color_is_needed,
float *value,
float3 *color)
{
float3 p = co;
if (distortion != 0.0f) {
@ -93,16 +108,21 @@ ccl_device void noise_texture_3d(
snoise_3d(p + random_float3_offset(2.0f)) * distortion);
}
*value = fractal_noise_3d(p, detail);
*value = fractal_noise_3d(p, detail, roughness);
if (color_is_needed) {
*color = make_float3(*value,
fractal_noise_3d(p + random_float3_offset(3.0f), detail),
fractal_noise_3d(p + random_float3_offset(4.0f), detail));
fractal_noise_3d(p + random_float3_offset(3.0f), detail, roughness),
fractal_noise_3d(p + random_float3_offset(4.0f), detail, roughness));
}
}
ccl_device void noise_texture_4d(
float4 co, float detail, float distortion, bool color_is_needed, float *value, float3 *color)
ccl_device void noise_texture_4d(float4 co,
float detail,
float roughness,
float distortion,
bool color_is_needed,
float *value,
float3 *color)
{
float4 p = co;
if (distortion != 0.0f) {
@ -112,11 +132,11 @@ ccl_device void noise_texture_4d(
snoise_4d(p + random_float4_offset(3.0f)) * distortion);
}
*value = fractal_noise_4d(p, detail);
*value = fractal_noise_4d(p, detail, roughness);
if (color_is_needed) {
*color = make_float3(*value,
fractal_noise_4d(p + random_float4_offset(4.0f), detail),
fractal_noise_4d(p + random_float4_offset(5.0f), detail));
fractal_noise_4d(p + random_float4_offset(4.0f), detail, roughness),
fractal_noise_4d(p + random_float4_offset(5.0f), detail, roughness));
}
}
@ -128,21 +148,27 @@ ccl_device void svm_node_tex_noise(KernelGlobals *kg,
uint offsets2,
int *offset)
{
uint vector_stack_offset, w_stack_offset, scale_stack_offset, detail_stack_offset;
uint distortion_stack_offset, value_stack_offset, color_stack_offset;
uint vector_stack_offset, w_stack_offset, scale_stack_offset;
uint detail_stack_offset, roughness_stack_offset, distortion_stack_offset;
uint value_stack_offset, color_stack_offset;
svm_unpack_node_uchar4(
offsets1, &vector_stack_offset, &w_stack_offset, &scale_stack_offset, &detail_stack_offset);
svm_unpack_node_uchar3(
offsets2, &distortion_stack_offset, &value_stack_offset, &color_stack_offset);
svm_unpack_node_uchar4(offsets2,
&roughness_stack_offset,
&distortion_stack_offset,
&value_stack_offset,
&color_stack_offset);
uint4 defaults = read_node(kg, offset);
uint4 defaults1 = read_node(kg, offset);
uint4 defaults2 = read_node(kg, offset);
float3 vector = stack_load_float3(stack, vector_stack_offset);
float w = stack_load_float_default(stack, w_stack_offset, defaults.x);
float scale = stack_load_float_default(stack, scale_stack_offset, defaults.y);
float detail = stack_load_float_default(stack, detail_stack_offset, defaults.z);
float distortion = stack_load_float_default(stack, distortion_stack_offset, defaults.w);
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 roughness = stack_load_float_default(stack, roughness_stack_offset, defaults1.w);
float distortion = stack_load_float_default(stack, distortion_stack_offset, defaults2.x);
vector *= scale;
w *= scale;
@ -151,11 +177,13 @@ ccl_device void svm_node_tex_noise(KernelGlobals *kg,
float3 color;
switch (dimensions) {
case 1:
noise_texture_1d(w, detail, distortion, stack_valid(color_stack_offset), &value, &color);
noise_texture_1d(
w, detail, roughness, distortion, stack_valid(color_stack_offset), &value, &color);
break;
case 2:
noise_texture_2d(make_float2(vector.x, vector.y),
detail,
roughness,
distortion,
stack_valid(color_stack_offset),
&value,
@ -163,11 +191,12 @@ ccl_device void svm_node_tex_noise(KernelGlobals *kg,
break;
case 3:
noise_texture_3d(
vector, detail, distortion, stack_valid(color_stack_offset), &value, &color);
vector, detail, roughness, distortion, stack_valid(color_stack_offset), &value, &color);
break;
case 4:
noise_texture_4d(make_float4(vector.x, vector.y, vector.z, w),
detail,
roughness,
distortion,
stack_valid(color_stack_offset),
&value,

View File

@ -23,9 +23,10 @@ ccl_device_noinline_cpu float svm_wave(NodeWaveType type,
NodeWaveRingsDirection rings_dir,
NodeWaveProfile profile,
float3 p,
float detail,
float distortion,
float detail,
float dscale,
float droughness,
float phase)
{
/* Prevent precision issues on unit coordinates. */
@ -66,7 +67,7 @@ ccl_device_noinline_cpu float svm_wave(NodeWaveType type,
n += phase;
if (distortion != 0.0f)
n += distortion * (fractal_noise_3d(p * dscale, detail) * 2.0f - 1.0f);
n += distortion * (fractal_noise_3d(p * dscale, detail, droughness) * 2.0f - 1.0f);
if (profile == NODE_WAVE_PROFILE_SIN) {
return 0.5f + 0.5f * sinf(n - M_PI_2_F);
@ -84,35 +85,40 @@ ccl_device_noinline_cpu float svm_wave(NodeWaveType type,
ccl_device void svm_node_tex_wave(
KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node, int *offset)
{
uint4 defaults1 = read_node(kg, offset);
uint4 defaults2 = read_node(kg, offset);
uint4 node2 = read_node(kg, offset);
uint4 node3 = read_node(kg, offset);
/* RNA properties */
uint type_offset, bands_dir_offset, rings_dir_offset, profile_offset;
/* Inputs, Outputs */
uint co_offset, scale_offset, distortion_offset, detail_offset, dscale_offset, phase_offset;
uint co_offset, scale_offset, distortion_offset, detail_offset, dscale_offset, droughness_offset,
phase_offset;
uint color_offset, fac_offset;
svm_unpack_node_uchar4(
node.y, &type_offset, &bands_dir_offset, &rings_dir_offset, &profile_offset);
svm_unpack_node_uchar4(node.z, &co_offset, &scale_offset, &distortion_offset, &detail_offset);
svm_unpack_node_uchar4(node.w, &dscale_offset, &phase_offset, &color_offset, &fac_offset);
svm_unpack_node_uchar3(node.z, &co_offset, &scale_offset, &distortion_offset);
svm_unpack_node_uchar4(
node.w, &detail_offset, &dscale_offset, &droughness_offset, &phase_offset);
svm_unpack_node_uchar2(node2.x, &color_offset, &fac_offset);
float3 co = stack_load_float3(stack, co_offset);
float scale = stack_load_float_default(stack, scale_offset, defaults1.x);
float detail = stack_load_float_default(stack, detail_offset, defaults1.y);
float distortion = stack_load_float_default(stack, distortion_offset, defaults1.z);
float dscale = stack_load_float_default(stack, dscale_offset, defaults1.w);
float phase = stack_load_float_default(stack, phase_offset, defaults2.x);
float scale = stack_load_float_default(stack, scale_offset, node2.y);
float distortion = stack_load_float_default(stack, distortion_offset, node2.z);
float detail = stack_load_float_default(stack, detail_offset, node2.w);
float dscale = stack_load_float_default(stack, dscale_offset, node3.x);
float droughness = stack_load_float_default(stack, droughness_offset, node3.y);
float phase = stack_load_float_default(stack, phase_offset, node3.z);
float f = svm_wave((NodeWaveType)type_offset,
(NodeWaveBandsDirection)bands_dir_offset,
(NodeWaveRingsDirection)rings_dir_offset,
(NodeWaveProfile)profile_offset,
co * scale,
detail,
distortion,
detail,
dscale,
droughness,
phase);
if (stack_valid(fac_offset))

View File

@ -922,6 +922,7 @@ NODE_DEFINE(NoiseTextureNode)
SOCKET_IN_FLOAT(w, "W", 0.0f);
SOCKET_IN_FLOAT(scale, "Scale", 1.0f);
SOCKET_IN_FLOAT(detail, "Detail", 2.0f);
SOCKET_IN_FLOAT(roughness, "Roughness", 0.5f);
SOCKET_IN_FLOAT(distortion, "Distortion", 0.0f);
SOCKET_OUT_FLOAT(fac, "Fac");
@ -940,6 +941,7 @@ void NoiseTextureNode::compile(SVMCompiler &compiler)
ShaderInput *w_in = input("W");
ShaderInput *scale_in = input("Scale");
ShaderInput *detail_in = input("Detail");
ShaderInput *roughness_in = input("Roughness");
ShaderInput *distortion_in = input("Distortion");
ShaderOutput *fac_out = output("Fac");
ShaderOutput *color_out = output("Color");
@ -948,6 +950,7 @@ void NoiseTextureNode::compile(SVMCompiler &compiler)
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 roughness_stack_offset = compiler.stack_assign_if_linked(roughness_in);
int distortion_stack_offset = compiler.stack_assign_if_linked(distortion_in);
int fac_stack_offset = compiler.stack_assign_if_linked(fac_out);
int color_stack_offset = compiler.stack_assign_if_linked(color_out);
@ -957,11 +960,13 @@ void NoiseTextureNode::compile(SVMCompiler &compiler)
dimensions,
compiler.encode_uchar4(
vector_stack_offset, w_stack_offset, scale_stack_offset, detail_stack_offset),
compiler.encode_uchar4(distortion_stack_offset, fac_stack_offset, color_stack_offset));
compiler.add_node(__float_as_int(w),
__float_as_int(scale),
__float_as_int(detail),
__float_as_int(distortion));
compiler.encode_uchar4(
roughness_stack_offset, distortion_stack_offset, fac_stack_offset, color_stack_offset));
compiler.add_node(
__float_as_int(w), __float_as_int(scale), __float_as_int(detail), __float_as_int(roughness));
compiler.add_node(
__float_as_int(distortion), SVM_STACK_INVALID, SVM_STACK_INVALID, SVM_STACK_INVALID);
tex_mapping.compile_end(compiler, vector_in, vector_stack_offset);
}
@ -1343,14 +1348,14 @@ NODE_DEFINE(WaveTextureNode)
profile_enum.insert("tri", NODE_WAVE_PROFILE_TRI);
SOCKET_ENUM(profile, "Profile", profile_enum, NODE_WAVE_PROFILE_SIN);
SOCKET_IN_POINT(
vector, "Vector", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_TEXTURE_GENERATED);
SOCKET_IN_FLOAT(scale, "Scale", 1.0f);
SOCKET_IN_FLOAT(distortion, "Distortion", 0.0f);
SOCKET_IN_FLOAT(detail, "Detail", 2.0f);
SOCKET_IN_FLOAT(detail_scale, "Detail Scale", 0.0f);
SOCKET_IN_FLOAT(detail_roughness, "Detail Roughness", 0.5f);
SOCKET_IN_FLOAT(phase, "Phase Offset", 0.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");
@ -1368,6 +1373,7 @@ void WaveTextureNode::compile(SVMCompiler &compiler)
ShaderInput *distortion_in = input("Distortion");
ShaderInput *detail_in = input("Detail");
ShaderInput *dscale_in = input("Detail Scale");
ShaderInput *droughness_in = input("Detail Roughness");
ShaderInput *phase_in = input("Phase Offset");
ShaderOutput *color_out = output("Color");
ShaderOutput *fac_out = output("Fac");
@ -1378,20 +1384,22 @@ void WaveTextureNode::compile(SVMCompiler &compiler)
compiler.encode_uchar4(type, bands_direction, rings_direction, profile),
compiler.encode_uchar4(vector_offset,
compiler.stack_assign_if_linked(scale_in),
compiler.stack_assign_if_linked(distortion_in),
compiler.stack_assign_if_linked(detail_in)),
compiler.encode_uchar4(compiler.stack_assign_if_linked(dscale_in),
compiler.stack_assign_if_linked(phase_in),
compiler.stack_assign_if_linked(color_out),
compiler.stack_assign_if_linked(fac_out)));
compiler.stack_assign_if_linked(distortion_in)),
compiler.encode_uchar4(compiler.stack_assign_if_linked(detail_in),
compiler.stack_assign_if_linked(dscale_in),
compiler.stack_assign_if_linked(droughness_in),
compiler.stack_assign_if_linked(phase_in)));
compiler.add_node(__float_as_int(scale),
__float_as_int(detail),
compiler.add_node(compiler.encode_uchar4(compiler.stack_assign_if_linked(color_out),
compiler.stack_assign_if_linked(fac_out)),
__float_as_int(scale),
__float_as_int(distortion),
__float_as_int(detail_scale));
__float_as_int(detail));
compiler.add_node(
__float_as_int(phase), SVM_STACK_INVALID, SVM_STACK_INVALID, SVM_STACK_INVALID);
compiler.add_node(__float_as_int(detail_scale),
__float_as_int(detail_roughness),
__float_as_int(phase),
SVM_STACK_INVALID);
tex_mapping.compile_end(compiler, vector_in, vector_offset);
}

View File

@ -230,7 +230,7 @@ class NoiseTextureNode : public TextureNode {
SHADER_NODE_CLASS(NoiseTextureNode)
int dimensions;
float w, scale, detail, distortion;
float w, scale, detail, roughness, distortion;
float3 vector;
};
@ -291,7 +291,7 @@ class WaveTextureNode : public TextureNode {
NodeWaveRingsDirection rings_direction;
NodeWaveProfile profile;
float scale, distortion, detail, detail_scale, phase;
float scale, distortion, detail, detail_scale, detail_roughness, phase;
float3 vector;
};

View File

@ -1,111 +1,115 @@
/* The fractal_noise functions are all exactly the same except for the input type. */
float fractal_noise(float p, float octaves)
float fractal_noise(float p, float octaves, float roughness)
{
float fscale = 1.0;
float amp = 1.0;
float maxamp = 0.0;
float sum = 0.0;
octaves = clamp(octaves, 0.0, 16.0);
int n = int(octaves);
for (int i = 0; i <= n; i++) {
float t = noise(fscale * p);
sum += t * amp;
amp *= 0.5;
maxamp += amp;
amp *= clamp(roughness, 0.0, 1.0);
fscale *= 2.0;
}
float rmd = octaves - floor(octaves);
if (rmd != 0.0) {
float t = noise(fscale * p);
float sum2 = sum + t * amp;
sum *= (float(1 << n) / float((1 << (n + 1)) - 1));
sum2 *= (float(1 << (n + 1)) / float((1 << (n + 2)) - 1));
sum /= maxamp;
sum2 /= maxamp + amp;
return (1.0 - rmd) * sum + rmd * sum2;
}
else {
sum *= (float(1 << n) / float((1 << (n + 1)) - 1));
return sum;
return sum / maxamp;
}
}
/* The fractal_noise functions are all exactly the same except for the input type. */
float fractal_noise(vec2 p, float octaves)
float fractal_noise(vec2 p, float octaves, float roughness)
{
float fscale = 1.0;
float amp = 1.0;
float maxamp = 0.0;
float sum = 0.0;
octaves = clamp(octaves, 0.0, 16.0);
int n = int(octaves);
for (int i = 0; i <= n; i++) {
float t = noise(fscale * p);
sum += t * amp;
amp *= 0.5;
maxamp += amp;
amp *= clamp(roughness, 0.0, 1.0);
fscale *= 2.0;
}
float rmd = octaves - floor(octaves);
if (rmd != 0.0) {
float t = noise(fscale * p);
float sum2 = sum + t * amp;
sum *= (float(1 << n) / float((1 << (n + 1)) - 1));
sum2 *= (float(1 << (n + 1)) / float((1 << (n + 2)) - 1));
sum /= maxamp;
sum2 /= maxamp + amp;
return (1.0 - rmd) * sum + rmd * sum2;
}
else {
sum *= (float(1 << n) / float((1 << (n + 1)) - 1));
return sum;
return sum / maxamp;
}
}
/* The fractal_noise functions are all exactly the same except for the input type. */
float fractal_noise(vec3 p, float octaves)
float fractal_noise(vec3 p, float octaves, float roughness)
{
float fscale = 1.0;
float amp = 1.0;
float maxamp = 0.0;
float sum = 0.0;
octaves = clamp(octaves, 0.0, 16.0);
int n = int(octaves);
for (int i = 0; i <= n; i++) {
float t = noise(fscale * p);
sum += t * amp;
amp *= 0.5;
maxamp += amp;
amp *= clamp(roughness, 0.0, 1.0);
fscale *= 2.0;
}
float rmd = octaves - floor(octaves);
if (rmd != 0.0) {
float t = noise(fscale * p);
float sum2 = sum + t * amp;
sum *= (float(1 << n) / float((1 << (n + 1)) - 1));
sum2 *= (float(1 << (n + 1)) / float((1 << (n + 2)) - 1));
sum /= maxamp;
sum2 /= maxamp + amp;
return (1.0 - rmd) * sum + rmd * sum2;
}
else {
sum *= (float(1 << n) / float((1 << (n + 1)) - 1));
return sum;
return sum / maxamp;
}
}
/* The fractal_noise functions are all exactly the same except for the input type. */
float fractal_noise(vec4 p, float octaves)
float fractal_noise(vec4 p, float octaves, float roughness)
{
float fscale = 1.0;
float amp = 1.0;
float maxamp = 0.0;
float sum = 0.0;
octaves = clamp(octaves, 0.0, 16.0);
int n = int(octaves);
for (int i = 0; i <= n; i++) {
float t = noise(fscale * p);
sum += t * amp;
amp *= 0.5;
maxamp += amp;
amp *= clamp(roughness, 0.0, 1.0);
fscale *= 2.0;
}
float rmd = octaves - floor(octaves);
if (rmd != 0.0) {
float t = noise(fscale * p);
float sum2 = sum + t * amp;
sum *= (float(1 << n) / float((1 << (n + 1)) - 1));
sum2 *= (float(1 << (n + 1)) / float((1 << (n + 2)) - 1));
sum /= maxamp;
sum2 /= maxamp + amp;
return (1.0 - rmd) * sum + rmd * sum2;
}
else {
sum *= (float(1 << n) / float((1 << (n + 1)) - 1));
return sum;
return sum / maxamp;
}
}

View File

@ -32,23 +32,35 @@ vec4 random_vec4_offset(float seed)
100.0 + hash_vec2_to_float(vec2(seed, 3.0)) * 100.0);
}
void node_noise_texture_1d(
vec3 co, float w, float scale, float detail, float distortion, out float value, out vec4 color)
void node_noise_texture_1d(vec3 co,
float w,
float scale,
float detail,
float roughness,
float distortion,
out float value,
out vec4 color)
{
float p = w * scale;
if (distortion != 0.0) {
p += snoise(p + random_float_offset(0.0)) * distortion;
}
value = fractal_noise(p, detail);
value = fractal_noise(p, detail, roughness);
color = vec4(value,
fractal_noise(p + random_float_offset(1.0), detail),
fractal_noise(p + random_float_offset(2.0), detail),
fractal_noise(p + random_float_offset(1.0), detail, roughness),
fractal_noise(p + random_float_offset(2.0), detail, roughness),
1.0);
}
void node_noise_texture_2d(
vec3 co, float w, float scale, float detail, float distortion, out float value, out vec4 color)
void node_noise_texture_2d(vec3 co,
float w,
float scale,
float detail,
float roughness,
float distortion,
out float value,
out vec4 color)
{
vec2 p = co.xy * scale;
if (distortion != 0.0) {
@ -56,15 +68,21 @@ void node_noise_texture_2d(
snoise(p + random_vec2_offset(1.0)) * distortion);
}
value = fractal_noise(p, detail);
value = fractal_noise(p, detail, roughness);
color = vec4(value,
fractal_noise(p + random_vec2_offset(2.0), detail),
fractal_noise(p + random_vec2_offset(3.0), detail),
fractal_noise(p + random_vec2_offset(2.0), detail, roughness),
fractal_noise(p + random_vec2_offset(3.0), detail, roughness),
1.0);
}
void node_noise_texture_3d(
vec3 co, float w, float scale, float detail, float distortion, out float value, out vec4 color)
void node_noise_texture_3d(vec3 co,
float w,
float scale,
float detail,
float roughness,
float distortion,
out float value,
out vec4 color)
{
vec3 p = co * scale;
if (distortion != 0.0) {
@ -73,15 +91,21 @@ void node_noise_texture_3d(
snoise(p + random_vec3_offset(2.0)) * distortion);
}
value = fractal_noise(p, detail);
value = fractal_noise(p, detail, roughness);
color = vec4(value,
fractal_noise(p + random_vec3_offset(3.0), detail),
fractal_noise(p + random_vec3_offset(4.0), detail),
fractal_noise(p + random_vec3_offset(3.0), detail, roughness),
fractal_noise(p + random_vec3_offset(4.0), detail, roughness),
1.0);
}
void node_noise_texture_4d(
vec3 co, float w, float scale, float detail, float distortion, out float value, out vec4 color)
void node_noise_texture_4d(vec3 co,
float w,
float scale,
float detail,
float roughness,
float distortion,
out float value,
out vec4 color)
{
vec4 p = vec4(co, w) * scale;
if (distortion != 0.0) {
@ -91,9 +115,9 @@ void node_noise_texture_4d(
snoise(p + random_vec4_offset(3.0)) * distortion);
}
value = fractal_noise(p, detail);
value = fractal_noise(p, detail, roughness);
color = vec4(value,
fractal_noise(p + random_vec4_offset(4.0), detail),
fractal_noise(p + random_vec4_offset(5.0), detail),
fractal_noise(p + random_vec4_offset(4.0), detail, roughness),
fractal_noise(p + random_vec4_offset(5.0), detail, roughness),
1.0);
}

View File

@ -2,6 +2,7 @@ float calc_wave(vec3 p,
float distortion,
float detail,
float detail_scale,
float detail_roughness,
float phase,
int wave_type,
int bands_dir,
@ -46,7 +47,7 @@ float calc_wave(vec3 p,
n += phase;
if (distortion != 0.0) {
n += distortion * (fractal_noise(p * detail_scale, detail) * 2.0 - 1.0);
n += distortion * (fractal_noise(p * detail_scale, detail, detail_roughness) * 2.0 - 1.0);
}
if (wave_profile == 0) { /* profile sin */
@ -67,6 +68,7 @@ void node_tex_wave(vec3 co,
float distortion,
float detail,
float detail_scale,
float detail_roughness,
float phase,
float wave_type,
float bands_dir,
@ -80,6 +82,7 @@ void node_tex_wave(vec3 co,
distortion,
detail,
detail_scale,
detail_roughness,
phase,
int(wave_type),
int(bands_dir),

View File

@ -26,6 +26,7 @@ static bNodeSocketTemplate sh_node_tex_noise_in[] = {
{SOCK_FLOAT, N_("W"), 0.0f, 0.0f, 0.0f, 0.0f, -1000.0f, 1000.0f},
{SOCK_FLOAT, N_("Scale"), 5.0f, 0.0f, 0.0f, 0.0f, -1000.0f, 1000.0f},
{SOCK_FLOAT, N_("Detail"), 2.0f, 0.0f, 0.0f, 0.0f, 0.0f, 16.0f},
{SOCK_FLOAT, N_("Roughness"), 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR},
{SOCK_FLOAT, N_("Distortion"), 0.0f, 0.0f, 0.0f, 0.0f, -1000.0f, 1000.0f},
{-1, ""},
};

View File

@ -27,6 +27,7 @@ static bNodeSocketTemplate sh_node_tex_wave_in[] = {
{SOCK_FLOAT, N_("Distortion"), 0.0f, 0.0f, 0.0f, 0.0f, -1000.0f, 1000.0f},
{SOCK_FLOAT, N_("Detail"), 2.0f, 0.0f, 0.0f, 0.0f, 0.0f, 16.0f},
{SOCK_FLOAT, N_("Detail Scale"), 1.0f, 0.0f, 0.0f, 0.0f, -1000.0f, 1000.0f},
{SOCK_FLOAT, N_("Detail Roughness"), 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR},
{SOCK_FLOAT, N_("Phase Offset"), 0.0f, 0.0f, 0.0f, 0.0f, -1000.0f, 1000.0f},
{-1, ""},
};