diff --git a/intern/cycles/kernel/osl/shaders/node_noise.h b/intern/cycles/kernel/osl/shaders/node_noise.h index 21d5f0fd28e..5384a37c7b1 100644 --- a/intern/cycles/kernel/osl/shaders/node_noise.h +++ b/intern/cycles/kernel/osl/shaders/node_noise.h @@ -9,78 +9,98 @@ float safe_noise(float co) { + float precision_correction = 0.5 * float(fabs(co) >= 1000000.0); /* Repeat Perlin noise texture every 100000.0 on each axis to prevent floating point * representation issues. */ - float p = fmod(co, 100000.0); + float p = fmod(co, 100000.0) + precision_correction; return noise("noise", p); } float safe_noise(vector2 co) { + vector2 precision_correction = 0.5 * vector2(float(fabs(co.x) >= 1000000.0), + float(fabs(co.y) >= 1000000.0)); /* 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); + vector2 p = fmod(co, 100000.0) + precision_correction; return noise("noise", p.x, p.y); } float safe_noise(vector3 co) { + vector3 precision_correction = 0.5 * vector3(float(fabs(co.x) >= 1000000.0), + float(fabs(co.y) >= 1000000.0), + float(fabs(co.z) >= 1000000.0)); /* 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); + vector3 p = fmod(co, 100000.0) + precision_correction; return noise("noise", p); } float safe_noise(vector4 co) { + vector4 precision_correction = 0.5 * vector4(float(fabs(co.x) >= 1000000.0), + float(fabs(co.y) >= 1000000.0), + float(fabs(co.z) >= 1000000.0), + float(fabs(co.w) >= 1000000.0)); /* 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); + vector4 p = fmod(co, 100000.0) + precision_correction; return noise("noise", vector3(p.x, p.y, p.z), p.w); } float safe_snoise(float co) { + float precision_correction = 0.5 * float(fabs(co) >= 1000000.0); /* Repeat Perlin noise texture every 100000.0 on each axis to prevent floating point * representation issues. */ - float p = fmod(co, 100000.0); + float p = fmod(co, 100000.0) + precision_correction; return noise("snoise", p); } float safe_snoise(vector2 co) { + vector2 precision_correction = 0.5 * vector2(float(fabs(co.x) >= 1000000.0), + float(fabs(co.y) >= 1000000.0)); /* 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); + vector2 p = fmod(co, 100000.0) + precision_correction; return noise("snoise", p.x, p.y); } float safe_snoise(vector3 co) { + vector3 precision_correction = 0.5 * vector3(float(fabs(co.x) >= 1000000.0), + float(fabs(co.y) >= 1000000.0), + float(fabs(co.z) >= 1000000.0)); /* 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); + vector3 p = fmod(co, 100000.0) + precision_correction; return noise("snoise", p); } float safe_snoise(vector4 co) { + vector4 precision_correction = 0.5 * vector4(float(fabs(co.x) >= 1000000.0), + float(fabs(co.y) >= 1000000.0), + float(fabs(co.z) >= 1000000.0), + float(fabs(co.w) >= 1000000.0)); /* 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); + vector4 p = fmod(co, 100000.0) + precision_correction; return noise("snoise", vector3(p.x, p.y, p.z), p.w); } diff --git a/intern/cycles/kernel/svm/noise.h b/intern/cycles/kernel/svm/noise.h index cb6355a558a..295ad69f120 100644 --- a/intern/cycles/kernel/svm/noise.h +++ b/intern/cycles/kernel/svm/noise.h @@ -684,10 +684,11 @@ ccl_device_inline float noise_scale4(float result) ccl_device_inline float snoise_1d(float p) { + float precision_correction = 0.5f * float(fabsf(p) >= 1000000.0f); /* 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); + p = fmodf(p, 100000.0f) + precision_correction; return noise_scale1(perlin_1d(p)); } @@ -699,10 +700,12 @@ ccl_device_inline float noise_1d(float p) ccl_device_inline float snoise_2d(float2 p) { + float2 precision_correction = 0.5f * make_float2(float(fabsf(p.x) >= 1000000.0f), + float(fabsf(p.y) >= 1000000.0f)); /* 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); + p = fmod(p, 100000.0f) + precision_correction; return noise_scale2(perlin_2d(p.x, p.y)); } @@ -714,10 +717,13 @@ ccl_device_inline float noise_2d(float2 p) ccl_device_inline float snoise_3d(float3 p) { + float3 precision_correction = 0.5f * make_float3(float(fabsf(p.x) >= 1000000.0f), + float(fabsf(p.y) >= 1000000.0f), + float(fabsf(p.z) >= 1000000.0f)); /* 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); + p = fmod(p, 100000.0f) + precision_correction; return noise_scale3(perlin_3d(p.x, p.y, p.z)); } @@ -729,10 +735,14 @@ ccl_device_inline float noise_3d(float3 p) ccl_device_inline float snoise_4d(float4 p) { + float4 precision_correction = 0.5f * make_float4(float(fabsf(p.x) >= 1000000.0f), + float(fabsf(p.y) >= 1000000.0f), + float(fabsf(p.z) >= 1000000.0f), + float(fabsf(p.w) >= 1000000.0f)); /* 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); + p = fmod(p, 100000.0f) + precision_correction; return noise_scale4(perlin_4d(p.x, p.y, p.z, p.w)); } diff --git a/source/blender/blenlib/intern/noise.cc b/source/blender/blenlib/intern/noise.cc index c0403191ad8..87c813a2fa0 100644 --- a/source/blender/blenlib/intern/noise.cc +++ b/source/blender/blenlib/intern/noise.cc @@ -490,39 +490,49 @@ BLI_INLINE float perlin_noise(float4 position) float perlin_signed(float position) { + float precision_correction = 0.5f * float(math::abs(position) >= 1000000.0f); /* Repeat Perlin noise texture every 100000.0 on each axis to prevent floating point * representation issues. */ - position = math::mod(position, 100000.0f); + position = math::mod(position, 100000.0f) + precision_correction; return perlin_noise(position) * 0.2500f; } float perlin_signed(float2 position) { + float2 precision_correction = 0.5f * float2(float(math::abs(position.x) >= 1000000.0f), + float(math::abs(position.y) >= 1000000.0f)); /* 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); + position = math::mod(position, 100000.0f) + precision_correction; return perlin_noise(position) * 0.6616f; } float perlin_signed(float3 position) { + float3 precision_correction = 0.5f * float3(float(math::abs(position.x) >= 1000000.0f), + float(math::abs(position.y) >= 1000000.0f), + float(math::abs(position.z) >= 1000000.0f)); /* 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); + position = math::mod(position, 100000.0f) + precision_correction; return perlin_noise(position) * 0.9820f; } float perlin_signed(float4 position) { + float4 precision_correction = 0.5f * float4(float(math::abs(position.x) >= 1000000.0f), + float(math::abs(position.y) >= 1000000.0f), + float(math::abs(position.z) >= 1000000.0f), + float(math::abs(position.w) >= 1000000.0f)); /* 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); + position = math::mod(position, 100000.0f) + precision_correction; return perlin_noise(position) * 0.8344f; } diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_noise.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_noise.glsl index 9cb201c0017..8b009b06e85 100644 --- a/source/blender/gpu/shaders/material/gpu_shader_material_noise.glsl +++ b/source/blender/gpu/shaders/material/gpu_shader_material_noise.glsl @@ -261,9 +261,10 @@ float noise_scale4(float result) float snoise(float p) { + float precision_correction = 0.5 * float(abs(p) >= 1000000.0); /* Repeat Perlin noise texture every 100000.0 on each axis to prevent floating point * representation issues. */ - p = compatible_fmod(p, 100000.0); + p = compatible_fmod(p, 100000.0) + precision_correction; return noise_scale1(noise_perlin(p)); } @@ -275,10 +276,12 @@ float noise(float p) float snoise(vec2 p) { + vec2 precision_correction = 0.5 * + vec2(float(abs(p.x) >= 1000000.0), float(abs(p.y) >= 1000000.0)); /* 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); + p = compatible_fmod(p, 100000.0) + precision_correction; return noise_scale2(noise_perlin(p)); } @@ -290,10 +293,13 @@ float noise(vec2 p) float snoise(vec3 p) { + vec3 precision_correction = 0.5 * vec3(float(abs(p.x) >= 1000000.0), + float(abs(p.y) >= 1000000.0), + float(abs(p.z) >= 1000000.0)); /* 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); + p = compatible_fmod(p, 100000.0) + precision_correction; return noise_scale3(noise_perlin(p)); } @@ -305,10 +311,14 @@ float noise(vec3 p) float snoise(vec4 p) { + vec4 precision_correction = 0.5 * vec4(float(abs(p.x) >= 1000000.0), + float(abs(p.y) >= 1000000.0), + float(abs(p.z) >= 1000000.0), + float(abs(p.w) >= 1000000.0)); /* 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); + p = compatible_fmod(p, 100000.0) + precision_correction; return noise_scale4(noise_perlin(p)); }