Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOmarSquircleArt <omar.squircleart@gmail.com>2019-08-08 15:33:35 +0300
committerOmarSquircleArt <omar.squircleart@gmail.com>2019-08-08 15:33:35 +0300
commit6c87aa858bf0f756560949b25c1afc9c6a887996 (patch)
tree4147365d7d5317eaa7fc83265b1c5a1fe206e8a2
parent1e3effc18501e8fb9a02f12456c07a492c08d57c (diff)
Remove magic numbers and swizzling from Noise code.
Previously, we used a random swizzling pattern as a sort of seed for noise, this proved bad in a lot of cases, including the cases where some of the components are constants. Additionally, we also added some offsets from a set of "magic numbers" as a form of seed. Those magic numbers are bad practice, so we introduced some new functions to generate random offsets based on the hash functions we already have, this happens at compile time, so this has no effect on performance.
-rw-r--r--intern/cycles/kernel/shaders/node_noise_texture.osl77
-rw-r--r--intern/cycles/kernel/svm/svm_noisetex.h78
-rw-r--r--source/blender/gpu/shaders/gpu_shader_material.glsl80
3 files changed, 161 insertions, 74 deletions
diff --git a/intern/cycles/kernel/shaders/node_noise_texture.osl b/intern/cycles/kernel/shaders/node_noise_texture.osl
index 4b100dc21ad..2113d162137 100644
--- a/intern/cycles/kernel/shaders/node_noise_texture.osl
+++ b/intern/cycles/kernel/shaders/node_noise_texture.osl
@@ -21,68 +21,95 @@
#define vector3 point
-/* To compute the color output of the noise, we either swizzle the
- * components, add a random offset {75, 125, 150}, or do both.
+/* The following offset functions generate random offsets to be added to texture
+ * coordinates to act as a seed since the noise functions don't have seed values.
+ * A seed value is needed for generating distortion textures and color outputs.
+ * The offset's components are in the range [100, 200], not too high to cause
+ * bad precision and not to small to be noticeable. We use float seed because
+ * OSL only support float hashes.
*/
+
+float random_float_offset(float seed)
+{
+ return 100.0 + noise("hash", seed) * 100.0;
+}
+
+vector2 random_vector2_offset(float seed)
+{
+ return vector2(100.0 + noise("hash", seed, 0.0) * 100.0,
+ 100.0 + noise("hash", seed, 1.0) * 100.0);
+}
+
+vector3 random_vector3_offset(float seed)
+{
+ return vector3(100.0 + noise("hash", seed, 0.0) * 100.0,
+ 100.0 + noise("hash", seed, 1.0) * 100.0,
+ 100.0 + noise("hash", seed, 2.0) * 100.0);
+}
+
+vector4 random_vector4_offset(float seed)
+{
+ return vector4(100.0 + noise("hash", seed, 0.0) * 100.0,
+ 100.0 + noise("hash", seed, 1.0) * 100.0,
+ 100.0 + noise("hash", seed, 2.0) * 100.0,
+ 100.0 + noise("hash", seed, 3.0) * 100.0);
+}
+
float noise(float p, float detail, float distortion, output color Color)
{
if (distortion != 0.0) {
- p += safe_noise(p + 13.5) * distortion;
+ p += safe_noise(p + random_float_offset(0.0)) * distortion;
}
float value = noise_turbulence(p, detail);
- Color = color(value, noise_turbulence(p + 75.0, detail), noise_turbulence(p + 125.0, detail));
+ Color = color(value,
+ noise_turbulence(p + random_float_offset(1.0), detail),
+ noise_turbulence(p + random_float_offset(2.0), detail));
return value;
}
float noise(vector2 p, float detail, float distortion, output color Color)
{
if (distortion != 0.0) {
- vector2 r;
- r.x = safe_noise(p + vector2(13.5, 13.5)) * distortion;
- r.y = safe_noise(p) * distortion;
- p += r;
+ p += vector2(safe_noise(p + random_vector2_offset(0.0)) * distortion,
+ safe_noise(p + random_vector2_offset(1.0)) * distortion);
}
float value = noise_turbulence(p, detail);
Color = color(value,
- noise_turbulence(p + vector2(150.0, 125.0), detail),
- noise_turbulence(p + vector2(75.0, 125.0), detail));
+ noise_turbulence(p + random_vector2_offset(2.0), detail),
+ noise_turbulence(p + random_vector2_offset(3.0), detail));
return value;
}
float noise(vector3 p, float detail, float distortion, output color Color)
{
if (distortion != 0.0) {
- vector3 r, offset = vector3(13.5);
- r[0] = safe_noise(p + offset) * distortion;
- r[1] = safe_noise(p) * distortion;
- r[2] = safe_noise(p - offset) * distortion;
- p += r;
+ p += vector3(safe_noise(p + random_vector3_offset(0.0)) * distortion,
+ safe_noise(p + random_vector3_offset(1.0)) * distortion,
+ safe_noise(p + random_vector3_offset(2.0)) * distortion);
}
float value = noise_turbulence(p, detail);
Color = color(value,
- noise_turbulence(vector3(p[1], p[0], p[2]), detail),
- noise_turbulence(vector3(p[1], p[2], p[0]), detail));
+ noise_turbulence(p + random_vector3_offset(3.0), detail),
+ noise_turbulence(p + random_vector3_offset(4.0), detail));
return value;
}
float noise(vector4 p, float detail, float distortion, output color Color)
{
if (distortion != 0.0) {
- vector4 r, offset = vector4(13.5, 13.5, 13.5, 13.5);
- r.x = safe_noise(p + offset) * distortion;
- r.y = safe_noise(p) * distortion;
- r.z = safe_noise(p - offset) * distortion;
- r.w = safe_noise(vector4(p.w, p.y, p.z, p.x) + offset) * distortion;
- p += r;
+ p += vector4(safe_noise(p + random_vector4_offset(0.0)) * distortion,
+ safe_noise(p + random_vector4_offset(1.0)) * distortion,
+ safe_noise(p + random_vector4_offset(2.0)) * distortion,
+ safe_noise(p + random_vector4_offset(3.0)) * distortion);
}
float value = noise_turbulence(p, detail);
Color = color(value,
- noise_turbulence(vector4(p.y, p.w, p.z, p.x), detail),
- noise_turbulence(vector4(p.y, p.z, p.w, p.x), detail));
+ noise_turbulence(p + random_vector4_offset(4.0), detail),
+ noise_turbulence(p + random_vector4_offset(5.0), detail));
return value;
}
diff --git a/intern/cycles/kernel/svm/svm_noisetex.h b/intern/cycles/kernel/svm/svm_noisetex.h
index 3173ff73fbc..03f489efcad 100644
--- a/intern/cycles/kernel/svm/svm_noisetex.h
+++ b/intern/cycles/kernel/svm/svm_noisetex.h
@@ -16,20 +16,52 @@
CCL_NAMESPACE_BEGIN
-/* To compute the color output of the noise, we either swizzle the
- * components, add a random offset {75, 125, 150}, or do both.
+/* The following offset functions generate random offsets to be added to texture
+ * coordinates to act as a seed since the noise functions don't have seed values.
+ * A seed value is needed for generating distortion textures and color outputs.
+ * The offset's components are in the range [100, 200], not too high to cause
+ * bad precision and not to small to be noticeable. We use float seed because
+ * OSL only support float hashes.
*/
+
+ccl_device_inline float random_float_offset(float seed)
+{
+ return 100.0f + hash_float_to_float(seed) * 100.0f;
+}
+
+ccl_device_inline float2 random_float2_offset(float seed)
+{
+ return make_float2(100.0f + hash_float2_to_float(make_float2(seed, 0.0f)) * 100.0f,
+ 100.0f + hash_float2_to_float(make_float2(seed, 1.0f)) * 100.0f);
+}
+
+ccl_device_inline float3 random_float3_offset(float seed)
+{
+ return make_float3(100.0f + hash_float2_to_float(make_float2(seed, 0.0f)) * 100.0f,
+ 100.0f + hash_float2_to_float(make_float2(seed, 1.0f)) * 100.0f,
+ 100.0f + hash_float2_to_float(make_float2(seed, 2.0f)) * 100.0f);
+}
+
+ccl_device_inline float4 random_float4_offset(float seed)
+{
+ return make_float4(100.0f + hash_float2_to_float(make_float2(seed, 0.0f)) * 100.0f,
+ 100.0f + hash_float2_to_float(make_float2(seed, 1.0f)) * 100.0f,
+ 100.0f + hash_float2_to_float(make_float2(seed, 2.0f)) * 100.0f,
+ 100.0f + hash_float2_to_float(make_float2(seed, 3.0f)) * 100.0f);
+}
+
ccl_device void tex_noise_1d(
float p, float detail, float distortion, bool color_is_needed, float *value, float3 *color)
{
if (distortion != 0.0f) {
- p += noise_1d(p + 13.5f) * distortion;
+ p += noise_1d(p + random_float_offset(0.0f)) * distortion;
}
*value = noise_turbulence_1d(p, detail);
if (color_is_needed) {
- *color = make_float3(
- *value, noise_turbulence_1d(p + 75.0f, detail), noise_turbulence_1d(p + 125.0f, detail));
+ *color = make_float3(*value,
+ noise_turbulence_1d(p + random_float_offset(1.0f), detail),
+ noise_turbulence_1d(p + random_float_offset(2.0f), detail));
}
}
@@ -37,17 +69,15 @@ ccl_device void tex_noise_2d(
float2 p, float detail, float distortion, bool color_is_needed, float *value, float3 *color)
{
if (distortion != 0.0f) {
- float2 r;
- r.x = noise_2d(p + make_float2(13.5f, 13.5f)) * distortion;
- r.y = noise_2d(p) * distortion;
- p += r;
+ p += make_float2(noise_2d(p + random_float2_offset(0.0f)) * distortion,
+ noise_2d(p + random_float2_offset(1.0f)) * distortion);
}
*value = noise_turbulence_2d(p, detail);
if (color_is_needed) {
*color = make_float3(*value,
- noise_turbulence_2d(p + make_float2(150.0f, 125.0f), detail),
- noise_turbulence_2d(p + make_float2(75.0f, 125.0f), detail));
+ noise_turbulence_2d(p + random_float2_offset(2.0f), detail),
+ noise_turbulence_2d(p + random_float2_offset(3.0f), detail));
}
}
@@ -55,18 +85,16 @@ ccl_device void tex_noise_3d(
float3 p, float detail, float distortion, bool color_is_needed, float *value, float3 *color)
{
if (distortion != 0.0f) {
- float3 r, offset = make_float3(13.5f, 13.5f, 13.5f);
- r.x = noise_3d(p + offset) * distortion;
- r.y = noise_3d(p) * distortion;
- r.z = noise_3d(p - offset) * distortion;
- p += r;
+ p += make_float3(noise_3d(p + random_float3_offset(0.0f)) * distortion,
+ noise_3d(p + random_float3_offset(1.0f)) * distortion,
+ noise_3d(p + random_float3_offset(2.0f)) * distortion);
}
*value = noise_turbulence_3d(p, detail);
if (color_is_needed) {
*color = make_float3(*value,
- noise_turbulence_3d(make_float3(p.y, p.x, p.z), detail),
- noise_turbulence_3d(make_float3(p.y, p.z, p.x), detail));
+ noise_turbulence_3d(p + random_float3_offset(3.0f), detail),
+ noise_turbulence_3d(p + random_float3_offset(4.0f), detail));
}
}
@@ -74,19 +102,17 @@ ccl_device void tex_noise_4d(
float4 p, float detail, float distortion, bool color_is_needed, float *value, float3 *color)
{
if (distortion != 0.0f) {
- float4 r, offset = make_float4(13.5, 13.5, 13.5, 13.5);
- r.x = noise_4d(p + offset) * distortion;
- r.y = noise_4d(p) * distortion;
- r.z = noise_4d(p - offset) * distortion;
- r.w = noise_4d(make_float4(p.w, p.y, p.z, p.x) + offset) * distortion;
- p += r;
+ p += make_float4(noise_4d(p + random_float4_offset(0.0f)) * distortion,
+ noise_4d(p + random_float4_offset(1.0f)) * distortion,
+ noise_4d(p + random_float4_offset(2.0f)) * distortion,
+ noise_4d(p + random_float4_offset(3.0f)) * distortion);
}
*value = noise_turbulence_4d(p, detail);
if (color_is_needed) {
*color = make_float3(*value,
- noise_turbulence_4d(make_float4(p.y, p.w, p.z, p.x), detail),
- noise_turbulence_4d(make_float4(p.y, p.z, p.w, p.x), detail));
+ noise_turbulence_4d(p + random_float4_offset(4.0f), detail),
+ noise_turbulence_4d(p + random_float4_offset(5.0f), detail));
}
}
diff --git a/source/blender/gpu/shaders/gpu_shader_material.glsl b/source/blender/gpu/shaders/gpu_shader_material.glsl
index a8ce7e733c6..58572e13af8 100644
--- a/source/blender/gpu/shaders/gpu_shader_material.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_material.glsl
@@ -3515,19 +3515,53 @@ float noise_turbulence(vec4 p, float octaves)
}
}
-/* To compute the color output of the noise, we either swizzle the
- * components, add a random offset {75, 125, 150}, or do both.
+/* The following offset functions generate random offsets to be added to texture
+ * coordinates to act as a seed since the noise functions don't have seed values.
+ * A seed value is needed for generating distortion textures and color outputs.
+ * The offset's components are in the range [100, 200], not too high to cause
+ * bad precision and not to small to be noticeable. We use float seed because
+ * OSL only support float hashes.
*/
+
+float random_float_offset(float seed)
+{
+ return 100.0 + hash_float_to_float(seed) * 100.0;
+}
+
+vec2 random_vec2_offset(float seed)
+{
+ return vec2(100.0 + hash_vec2_to_float(vec2(seed, 0.0)) * 100.0,
+ 100.0 + hash_vec2_to_float(vec2(seed, 1.0)) * 100.0);
+}
+
+vec3 random_vec3_offset(float seed)
+{
+ return vec3(100.0 + hash_vec2_to_float(vec2(seed, 0.0)) * 100.0,
+ 100.0 + hash_vec2_to_float(vec2(seed, 1.0)) * 100.0,
+ 100.0 + hash_vec2_to_float(vec2(seed, 2.0)) * 100.0);
+}
+
+vec4 random_vec4_offset(float seed)
+{
+ return vec4(100.0 + hash_vec2_to_float(vec2(seed, 0.0)) * 100.0,
+ 100.0 + hash_vec2_to_float(vec2(seed, 1.0)) * 100.0,
+ 100.0 + hash_vec2_to_float(vec2(seed, 2.0)) * 100.0,
+ 100.0 + hash_vec2_to_float(vec2(seed, 3.0)) * 100.0);
+}
+
void node_tex_noise_1d(
vec3 co, float w, float scale, float detail, float distortion, out float value, out vec4 color)
{
float p = w * scale;
if (distortion != 0.0) {
- p += noise(p + 13.5) * distortion;
+ p += noise(p + random_float_offset(0.0)) * distortion;
}
value = noise_turbulence(p, detail);
- color = vec4(value, noise_turbulence(p + 75.0, detail), noise_turbulence(p + 125.0, detail), 1.0);
+ color = vec4(value,
+ noise_turbulence(p + random_float_offset(1.0), detail),
+ noise_turbulence(p + random_float_offset(2.0), detail),
+ 1.0);
}
void node_tex_noise_2d(
@@ -3535,16 +3569,14 @@ void node_tex_noise_2d(
{
vec2 p = co.xy * scale;
if (distortion != 0.0) {
- vec2 r;
- r.x = noise(p + vec2(13.5)) * distortion;
- r.y = noise(p) * distortion;
- p += r;
+ p += vec2(noise(p + random_vec2_offset(0.0)) * distortion,
+ noise(p + random_vec2_offset(1.0)) * distortion);
}
value = noise_turbulence(p, detail);
color = vec4(value,
- noise_turbulence(p + vec2(150.0, 125.0), detail),
- noise_turbulence(p + vec2(75.0, 125.0), detail),
+ noise_turbulence(p + random_vec2_offset(2.0), detail),
+ noise_turbulence(p + random_vec2_offset(3.0), detail),
1.0);
}
@@ -3553,15 +3585,16 @@ void node_tex_noise_3d(
{
vec3 p = co * scale;
if (distortion != 0.0) {
- vec3 r, offset = vec3(13.5, 13.5, 13.5);
- r.x = noise(p + offset) * distortion;
- r.y = noise(p) * distortion;
- r.z = noise(p - offset) * distortion;
- p += r;
+ p += vec3(noise(p + random_vec3_offset(0.0)) * distortion,
+ noise(p + random_vec3_offset(1.0)) * distortion,
+ noise(p + random_vec3_offset(2.0)) * distortion);
}
value = noise_turbulence(p, detail);
- color = vec4(value, noise_turbulence(p.yxz, detail), noise_turbulence(p.yzx, detail), 1.0);
+ color = vec4(value,
+ noise_turbulence(p + random_vec3_offset(3.0), detail),
+ noise_turbulence(p + random_vec3_offset(4.0), detail),
+ 1.0);
}
void node_tex_noise_4d(
@@ -3569,16 +3602,17 @@ void node_tex_noise_4d(
{
vec4 p = vec4(co, w) * scale;
if (distortion != 0.0) {
- vec4 r, offset = vec4(13.5, 13.5, 13.5, 13.5);
- r.x = noise(p + offset) * distortion;
- r.y = noise(p) * distortion;
- r.z = noise(p - offset) * distortion;
- r.w = noise(p.wyzx + offset) * distortion;
- p += r;
+ p += vec4(noise(p + random_vec4_offset(0.0)) * distortion,
+ noise(p + random_vec4_offset(1.0)) * distortion,
+ noise(p + random_vec4_offset(2.0)) * distortion,
+ noise(p + random_vec4_offset(3.0)) * distortion);
}
value = noise_turbulence(p, detail);
- color = vec4(value, noise_turbulence(p.ywzx, detail), noise_turbulence(p.yzwx, detail), 1.0);
+ color = vec4(value,
+ noise_turbulence(p + random_vec4_offset(4.0), detail),
+ noise_turbulence(p + random_vec4_offset(5.0), detail),
+ 1.0);
}
/* 1D Musgrave fBm