Fix #119797: Noise Texture Precision Issues #119884

Merged
Brecht Van Lommel merged 5 commits from Hoshinova/blender:fix-119797 into main 2024-03-29 16:12:34 +01:00
8 changed files with 58 additions and 40 deletions
Showing only changes of commit 880d17e953 - Show all commits

View File

@ -10,8 +10,7 @@
float safe_noise(float co)
{
/* Repeat Perlin noise texture every 100000.0 on each axis to prevent floating point
* representation issues. This causes discontinuities every 100000.0, however at such scales this
* usually shouldn't be noticeable. */
* representation issues. */
float p = fmod(co, 100000.0);
return noise("noise", p);
@ -22,7 +21,7 @@ float safe_noise(vector2 co)
/* Repeat Perlin noise texture every 100000.0 on each axis to prevent floating point
* representation issues. This causes discontinuities every 100000.0, however at such scales this
* usually shouldn't be noticeable. */
vector2 p = vector2(fmod(co.x, 100000.0), fmod(co.y, 100000.0));
vector2 p = fmod(co, 100000.0);
return noise("noise", p.x, p.y);
}
@ -32,7 +31,7 @@ float safe_noise(vector3 co)
/* Repeat Perlin noise texture every 100000.0 on each axis to prevent floating point
* representation issues. This causes discontinuities every 100000.0, however at such scales this
* usually shouldn't be noticeable. */
vector3 p = vector3(fmod(co.x, 100000.0), fmod(co.y, 100000.0), fmod(co.z, 100000.0));
vector3 p = fmod(co, 100000.0);
Hoshinova marked this conversation as resolved
Review

Seems like we have fmod vector variants that should be used instead?

Seems like we have `fmod` vector variants that should be used instead?
return noise("noise", p);
}
@ -42,8 +41,7 @@ float safe_noise(vector4 co)
/* Repeat Perlin noise texture every 100000.0 on each axis to prevent floating point
* representation issues. This causes discontinuities every 100000.0, however at such scales this
* usually shouldn't be noticeable. */
vector4 p = vector4(
fmod(co.x, 100000.0), fmod(co.y, 100000.0), fmod(co.z, 100000.0), fmod(co.w, 100000.0));
vector4 p = fmod(co, 100000.0);
return noise("noise", vector3(p.x, p.y, p.z), p.w);
}
@ -51,8 +49,7 @@ float safe_noise(vector4 co)
float safe_snoise(float co)
{
/* Repeat Perlin noise texture every 100000.0 on each axis to prevent floating point
* representation issues. This causes discontinuities every 100000.0, however at such scales this
* usually shouldn't be noticeable. */
* representation issues. */
float p = fmod(co, 100000.0);
return noise("snoise", p);
@ -63,7 +60,7 @@ float safe_snoise(vector2 co)
/* Repeat Perlin noise texture every 100000.0 on each axis to prevent floating point
* representation issues. This causes discontinuities every 100000.0, however at such scales this
* usually shouldn't be noticeable. */
vector2 p = vector2(fmod(co.x, 100000.0), fmod(co.y, 100000.0));
vector2 p = fmod(co, 100000.0);
return noise("snoise", p.x, p.y);
}
@ -73,7 +70,7 @@ float safe_snoise(vector3 co)
/* Repeat Perlin noise texture every 100000.0 on each axis to prevent floating point
* representation issues. This causes discontinuities every 100000.0, however at such scales this
* usually shouldn't be noticeable. */
vector3 p = vector3(fmod(co.x, 100000.0), fmod(co.y, 100000.0), fmod(co.z, 100000.0));
vector3 p = fmod(co, 100000.0);
return noise("snoise", p);
}
@ -83,8 +80,7 @@ float safe_snoise(vector4 co)
/* Repeat Perlin noise texture every 100000.0 on each axis to prevent floating point
* representation issues. This causes discontinuities every 100000.0, however at such scales this
* usually shouldn't be noticeable. */
vector4 p = vector4(
fmod(co.x, 100000.0), fmod(co.y, 100000.0), fmod(co.z, 100000.0), fmod(co.w, 100000.0));
vector4 p = fmod(co, 100000.0);
return noise("snoise", vector3(p.x, p.y, p.z), p.w);
}

View File

@ -684,9 +684,9 @@ ccl_device_inline float noise_scale4(float result)
ccl_device_inline float snoise_1d(float p)
{
/* Repeat Perlin noise texture every 100000.0f on each axis to prevent floating point
* representation issues. This causes discontinuities every 100000.0f, however at such scales
* this usually shouldn't be noticeable. */
/* Repeat Perlin noise texture every 100000.0 on each axis to prevent floating point
* representation issues. */
/* The 1D variant of fmod is called fmodf. */
p = fmodf(p, 100000.0f);
return noise_scale1(perlin_1d(p));
@ -702,7 +702,7 @@ ccl_device_inline float snoise_2d(float2 p)
/* Repeat Perlin noise texture every 100000.0f on each axis to prevent floating point
* representation issues. This causes discontinuities every 100000.0f, however at such scales
* this usually shouldn't be noticeable. */
p = make_float2(fmodf(p.x, 100000.0f), fmodf(p.y, 100000.0f));
p = fmod(p, 100000.0f);
return noise_scale2(perlin_2d(p.x, p.y));
}
@ -717,7 +717,7 @@ ccl_device_inline float snoise_3d(float3 p)
/* Repeat Perlin noise texture every 100000.0f on each axis to prevent floating point
* representation issues. This causes discontinuities every 100000.0f, however at such scales
* this usually shouldn't be noticeable. */
p = make_float3(fmodf(p.x, 100000.0f), fmodf(p.y, 100000.0f), fmodf(p.z, 100000.0f));
p = fmod(p, 100000.0f);
return noise_scale3(perlin_3d(p.x, p.y, p.z));
}
@ -732,8 +732,7 @@ ccl_device_inline float snoise_4d(float4 p)
/* Repeat Perlin noise texture every 100000.0f on each axis to prevent floating point
* representation issues. This causes discontinuities every 100000.0f, however at such scales
* this usually shouldn't be noticeable. */
p = make_float4(
fmodf(p.x, 100000.0f), fmodf(p.y, 100000.0f), fmodf(p.z, 100000.0f), fmodf(p.w, 100000.0f));
p = fmod(p, 100000.0f);
return noise_scale4(perlin_4d(p.x, p.y, p.z, p.w));
}

View File

@ -198,6 +198,11 @@ ccl_device_inline float2 clamp(const float2 a, const float2 mn, const float2 mx)
return min(max(a, mn), mx);
}
ccl_device_inline float2 fmod(const float2 a, const float b)
{
return make_float2(fmodf(a.x, b), fmodf(a.y, b));
}
ccl_device_inline float2 fabs(const float2 a)
{
return make_float2(fabsf(a.x), fabsf(a.y));

View File

@ -309,6 +309,11 @@ ccl_device_inline float3 fabs(const float3 a)
# endif
}
ccl_device_inline float3 fmod(const float3 a, const float b)
{
return make_float3(fmodf(a.x, b), fmodf(a.y, b), fmodf(a.z, b));
}
ccl_device_inline float3 sqrt(const float3 a)
{
# ifdef __KERNEL_SSE__

View File

@ -465,6 +465,11 @@ ccl_device_inline float4 fabs(const float4 a)
# endif
}
ccl_device_inline float4 fmod(const float4 a, const float b)
{
return make_float4(fmodf(a.x, b), fmodf(a.y, b), fmodf(a.z, b), fmodf(a.w, b));
}
ccl_device_inline float4 floor(const float4 a)
{
# ifdef __KERNEL_SSE__

View File

@ -490,10 +490,9 @@ BLI_INLINE float perlin_noise(float4 position)
float perlin_signed(float position)
{
/* Repeat Perlin noise texture every 100000.0f on each axis to prevent floating point
* representation issues. This causes discontinuities every 100000.0f, however at such scales
* this usually shouldn't be noticeable. */
position = fmodf(position, 100000.0f);
/* Repeat Perlin noise texture every 100000.0 on each axis to prevent floating point
* representation issues. */
position = math::mod(position, 100000.0f);
return perlin_noise(position) * 0.2500f;
}
@ -503,7 +502,7 @@ float perlin_signed(float2 position)
/* Repeat Perlin noise texture every 100000.0f on each axis to prevent floating point
* representation issues. This causes discontinuities every 100000.0f, however at such scales
* this usually shouldn't be noticeable. */
position = float2(fmodf(position.x, 100000.0f), fmodf(position.y, 100000.0f));
position = math::mod(position, 100000.0f);
return perlin_noise(position) * 0.6616f;
}
@ -513,8 +512,7 @@ float perlin_signed(float3 position)
/* Repeat Perlin noise texture every 100000.0f on each axis to prevent floating point
* representation issues. This causes discontinuities every 100000.0f, however at such scales
* this usually shouldn't be noticeable. */
position = float3(
fmodf(position.x, 100000.0f), fmodf(position.y, 100000.0f), fmodf(position.z, 100000.0f));
position = math::mod(position, 100000.0f);
return perlin_noise(position) * 0.9820f;
}
@ -524,10 +522,7 @@ float perlin_signed(float4 position)
/* Repeat Perlin noise texture every 100000.0f on each axis to prevent floating point
* representation issues. This causes discontinuities every 100000.0f, however at such scales
* this usually shouldn't be noticeable. */
position = float4(fmodf(position.x, 100000.0f),
fmodf(position.y, 100000.0f),
fmodf(position.z, 100000.0f),
fmodf(position.w, 100000.0f));
position = math::mod(position, 100000.0f);
return perlin_noise(position) * 0.8344f;
}

View File

@ -24,6 +24,24 @@ float compatible_fmod(float a, float b)
return 0.0;
}
vec2 compatible_fmod(vec2 a, float b)
{
return vec2(compatible_fmod(a.x, b), compatible_fmod(a.y, b));
}
vec3 compatible_fmod(vec3 a, float b)
{
return vec3(compatible_fmod(a.x, b), compatible_fmod(a.y, b), compatible_fmod(a.z, b));
}
vec4 compatible_fmod(vec4 a, float b)
{
return vec4(compatible_fmod(a.x, b),
compatible_fmod(a.y, b),
compatible_fmod(a.z, b),
compatible_fmod(a.w, b));
}
float compatible_pow(float x, float y)
{
if (y == 0.0) { /* x^0 -> 1, including 0^0 */

View File

@ -2,6 +2,7 @@
*
* SPDX-License-Identifier: GPL-2.0-or-later */
#pragma BLENDER_REQUIRE(gpu_shader_common_math_utils.glsl)
#pragma BLENDER_REQUIRE(gpu_shader_common_hash.glsl)
/* clang-format off */
@ -261,8 +262,7 @@ float noise_scale4(float result)
float snoise(float p)
{
/* Repeat Perlin noise texture every 100000.0 on each axis to prevent floating point
* representation issues. This causes discontinuities every 100000.0, however at such scales this
* usually shouldn't be noticeable. */
* representation issues. */
p = compatible_fmod(p, 100000.0);
return noise_scale1(noise_perlin(p));
@ -278,7 +278,7 @@ float snoise(vec2 p)
/* Repeat Perlin noise texture every 100000.0 on each axis to prevent floating point
* representation issues. This causes discontinuities every 100000.0, however at such scales this
* usually shouldn't be noticeable. */
p = vec2(compatible_fmod(p.x, 100000.0), compatible_fmod(p.y, 100000.0));
p = compatible_fmod(p, 100000.0);
return noise_scale2(noise_perlin(p));
}
@ -293,9 +293,7 @@ float snoise(vec3 p)
/* Repeat Perlin noise texture every 100000.0 on each axis to prevent floating point
* representation issues. This causes discontinuities every 100000.0, however at such scales this
* usually shouldn't be noticeable. */
p = vec3(compatible_fmod(p.x, 100000.0),
compatible_fmod(p.y, 100000.0),
compatible_fmod(p.z, 100000.0));
p = compatible_fmod(p, 100000.0);
return noise_scale3(noise_perlin(p));
}
@ -310,10 +308,7 @@ float snoise(vec4 p)
/* Repeat Perlin noise texture every 100000.0 on each axis to prevent floating point
* representation issues. This causes discontinuities every 100000.0, however at such scales this
* usually shouldn't be noticeable. */
p = vec4(compatible_fmod(p.x, 100000.0),
compatible_fmod(p.y, 100000.0),
compatible_fmod(p.z, 100000.0),
compatible_fmod(p.w, 100000.0));
p = compatible_fmod(p, 100000.0);
return noise_scale4(noise_perlin(p));
}