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 154 additions and 60 deletions

View File

@ -7,76 +7,82 @@
#define vector3 point
float safe_noise(float p)
float safe_noise(float co)
{
float f = noise("noise", p);
if (isinf(f)) {
return 0.5;
}
return f;
/* Repeat Perlin noise texture every 100000.0 on each axis to prevent floating point
* representation issues. */
float p = fmod(co, 100000.0);
return noise("noise", p);
}
float safe_noise(vector2 p)
float safe_noise(vector2 co)
{
float f = noise("noise", p.x, p.y);
if (isinf(f)) {
return 0.5;
}
return f;
/* 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 = fmod(co, 100000.0);
return noise("noise", p.x, p.y);
}
float safe_noise(vector3 p)
float safe_noise(vector3 co)
{
float f = noise("noise", p);
if (isinf(f)) {
return 0.5;
}
return f;
/* 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 = 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);
}
float safe_noise(vector4 p)
float safe_noise(vector4 co)
{
float f = noise("noise", vector3(p.x, p.y, p.z), p.w);
if (isinf(f)) {
return 0.5;
}
return f;
/* 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 = fmod(co, 100000.0);
return noise("noise", vector3(p.x, p.y, p.z), p.w);
}
float safe_snoise(float p)
float safe_snoise(float co)
{
float f = noise("snoise", p);
if (isinf(f)) {
return 0.0;
}
return f;
/* Repeat Perlin noise texture every 100000.0 on each axis to prevent floating point
* representation issues. */
float p = fmod(co, 100000.0);
return noise("snoise", p);
}
float safe_snoise(vector2 p)
float safe_snoise(vector2 co)
{
float f = noise("snoise", p.x, p.y);
if (isinf(f)) {
return 0.0;
}
return f;
/* 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 = fmod(co, 100000.0);
return noise("snoise", p.x, p.y);
}
float safe_snoise(vector3 p)
float safe_snoise(vector3 co)
{
float f = noise("snoise", p);
if (isinf(f)) {
return 0.0;
}
return f;
/* 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 = fmod(co, 100000.0);
return noise("snoise", p);
}
float safe_snoise(vector4 p)
float safe_snoise(vector4 co)
{
float f = noise("snoise", vector3(p.x, p.y, p.z), p.w);
if (isinf(f)) {
return 0.0;
}
return f;
/* 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 = fmod(co, 100000.0);
return noise("snoise", vector3(p.x, p.y, p.z), p.w);
}
#define NOISE_FBM(T) \

View File

@ -684,7 +684,12 @@ ccl_device_inline float noise_scale4(float result)
ccl_device_inline float snoise_1d(float p)
{
return noise_scale1(ensure_finite(perlin_1d(p)));
/* 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));
}
ccl_device_inline float noise_1d(float p)
@ -694,7 +699,12 @@ ccl_device_inline float noise_1d(float p)
ccl_device_inline float snoise_2d(float2 p)
{
return noise_scale2(ensure_finite(perlin_2d(p.x, p.y)));
/* 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 = fmod(p, 100000.0f);
return noise_scale2(perlin_2d(p.x, p.y));
}
ccl_device_inline float noise_2d(float2 p)
@ -704,7 +714,12 @@ ccl_device_inline float noise_2d(float2 p)
ccl_device_inline float snoise_3d(float3 p)
{
return noise_scale3(ensure_finite(perlin_3d(p.x, p.y, p.z)));
/* 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 = fmod(p, 100000.0f);
return noise_scale3(perlin_3d(p.x, p.y, p.z));
}
ccl_device_inline float noise_3d(float3 p)
@ -714,7 +729,12 @@ ccl_device_inline float noise_3d(float3 p)
ccl_device_inline float snoise_4d(float4 p)
{
return noise_scale4(ensure_finite(perlin_4d(p.x, p.y, p.z, p.w)));
/* 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 = fmod(p, 100000.0f);
return noise_scale4(perlin_4d(p.x, p.y, p.z, p.w));
}
ccl_device_inline float noise_4d(float4 p)

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,21 +490,40 @@ BLI_INLINE float perlin_noise(float4 position)
float perlin_signed(float position)
{
/* 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;
}
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 = math::mod(position, 100000.0f);
return perlin_noise(position) * 0.6616f;
}
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 = math::mod(position, 100000.0f);
return perlin_noise(position) * 0.9820f;
}
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 = 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 */
@ -260,8 +261,11 @@ float noise_scale4(float result)
float snoise(float p)
{
float r = noise_perlin(p);
return (isinf(r)) ? 0.0 : noise_scale1(r);
/* Repeat Perlin noise texture every 100000.0 on each axis to prevent floating point
* representation issues. */
p = compatible_fmod(p, 100000.0);
return noise_scale1(noise_perlin(p));
}
float noise(float p)
@ -271,8 +275,12 @@ float noise(float p)
float snoise(vec2 p)
{
float r = noise_perlin(p);
return (isinf(r)) ? 0.0 : noise_scale2(r);
/* 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 = compatible_fmod(p, 100000.0);
return noise_scale2(noise_perlin(p));
}
float noise(vec2 p)
@ -282,8 +290,12 @@ float noise(vec2 p)
float snoise(vec3 p)
{
float r = noise_perlin(p);
return (isinf(r)) ? 0.0 : noise_scale3(r);
/* 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 = compatible_fmod(p, 100000.0);
return noise_scale3(noise_perlin(p));
}
float noise(vec3 p)
@ -293,8 +305,12 @@ float noise(vec3 p)
float snoise(vec4 p)
{
float r = noise_perlin(p);
return (isinf(r)) ? 0.0 : noise_scale4(r);
/* 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 = compatible_fmod(p, 100000.0);
return noise_scale4(noise_perlin(p));
}
float noise(vec4 p)