Maniphest T93219

Checker texture artifacts when feeded with object texture coordinates
Confirmed, NormalKNOWN ISSUE

Assigned To
None
Authored By
Rigoletto Eikenberg (rigoletto)
Nov 19 2021, 6:23 PM
Tags
  • BF Blender
  • Nodes & Physics
  • EEVEE & Viewport
Subscribers
Brecht Van Lommel (brecht)
Charlie Jolly (charlie)
Evan Wilson (EAW)
Michael (michael64)
Pratik Borhade (PratikPB2123)
Rigoletto Eikenberg (rigoletto)

Description

System Information
Operating system: Linux-5.4.0-90-generic-x86_64-with-glibc2.27 64 Bits
Graphics card: GeForce GTX 1660 Ti/PCIe/SSE2 NVIDIA Corporation 4.5.0 NVIDIA 460.91.03

Blender Version
Broken: version: 3.1.0 Alpha, branch: master, commit date: 2021-11-18 22:32, hash: rB5ed3a5d02379
Worked: afaik never, still had this issues with all previous versions down to 2.7

Short description of error
Checker texture has calcuation issues when feeded with object texture coordinates.
Other textures like brick or voronoy are ok.

Exact steps for others to reproduce the error
create a plane
assign the checker texture with object coordinates


Event Timeline

Rigoletto Eikenberg (rigoletto) created this task.Nov 19 2021, 6:23 PM
Charlie Jolly (charlie) added a subscriber: Charlie Jolly (charlie).Nov 19 2021, 6:36 PM
Charlie Jolly (charlie) added a comment.Nov 19 2021, 8:22 PM

Confirmed, Eevee only.

Evan Wilson (EAW) closed this task as Archived.Nov 22 2021, 5:06 AM
Evan Wilson (EAW) added a subscriber: Evan Wilson (EAW).

Thank you for the report.

The z-fighting due to signed zeros is a known issue, as stated in the manual.

See:
https://docs.blender.org/manual/en/latest/render/shader_nodes/textures/checker.html

As it is documented, and workarounds are given in the manual, I’ll close this report as per tracker policy.

Rigoletto Eikenberg (rigoletto) added a comment.Nov 22 2021, 6:21 PM

Sorry but i cant understand where the issue comes from.

Where is the z-fighting come from?
There is only one plane, no overlying geometry.

Evan Wilson (EAW) reopened this task as Confirmed.Nov 22 2021, 6:39 PM

I was going by my memory of this being a known issue, and confirmed it by checking the manual. Checking the code, I see that @chalie was the last one to modify it, I will defer to his expertise and mark this confirmed.

Charlie Jolly (charlie) added a comment.Nov 22 2021, 6:47 PM

@Rigoletto Eikenberg (rigoletto) this is normally a result of float precision, the object coordinates will be calculated on the fly and the result maybe positive 0.0 or negative 0.0.

@Evan Wilson (EAW) if you mean modify the manual, yes this was updated after porting Checker to GN.

I'd mark it as a known issue (with mitigation shown in manual) or ask someone from the rendering module to take a look.

Evan Wilson (EAW) added a comment.Nov 22 2021, 6:49 PM
In T93219#1258117, @Rigoletto Eikenberg (rigoletto) wrote:

Sorry but i cant understand where the issue comes from.

Where is the z-fighting come from?
There is only one plane, no overlying geometry.

Cell Noise is discontinuous at exact integer units. Cycles (and Blender Internal before 2.80) adds an epsilon offset to give better visual results. It appears EEVEE doesn’t have this epsilon offset.

Charlie Jolly (charlie) added a comment.EditedNov 22 2021, 6:54 PM

There is code to prevent this in Eevee checker texture.

Eevee

void node_tex_checker(
    vec3 co, vec4 color1, vec4 color2, float scale, out vec4 color, out float fac)
{
  vec3 p = co * scale;

  /* Prevent precision issues on unit coordinates. */
  p = (p + 0.000001) * 0.999999;

  int xi = int(abs(floor(p.x)));
  int yi = int(abs(floor(p.y)));
  int zi = int(abs(floor(p.z)));

  bool check = ((mod(xi, 2) == mod(yi, 2)) == bool(mod(zi, 2)));

  color = check ? color1 : color2;
  fac = check ? 1.0 : 0.0;
}

Cycles

ccl_device float svm_checker(float3 p)
{
  /* avoid precision issues on unit coordinates */
  p.x = (p.x + 0.000001f) * 0.999999f;
  p.y = (p.y + 0.000001f) * 0.999999f;
  p.z = (p.z + 0.000001f) * 0.999999f;

  int xi = abs(float_to_int(floorf(p.x)));
  int yi = abs(float_to_int(floorf(p.y)));
  int zi = abs(float_to_int(floorf(p.z)));

  return ((xi % 2 == yi % 2) == (zi % 2)) ? 1.0f : 0.0f;
}
Pratik Borhade (PratikPB2123) added projects: Nodes & Physics, EEVEE & Viewport.Nov 22 2021, 7:00 PM
Pratik Borhade (PratikPB2123) added a subscriber: Pratik Borhade (PratikPB2123).
Charlie Jolly (charlie) added a comment.Nov 23 2021, 2:11 AM

Below is a possible fix for the checker texture by detecting negative coordinate values below 1e-05.

/* Prevent precision issues on signed zeros. */
  p.x = (abs(p.x) <= 1e-05) ? 0.0 : p.x;
  p.y = (abs(p.y) <= 1e-05) ? 0.0 : p.y;
  p.z = (abs(p.z) <= 1e-05) ? 0.0 : p.z;

This doesn't explain why the object coordinates seem to be less stable in Eevee and work in Cycles without this fix.

void node_tex_checker(
    vec3 co, vec4 color1, vec4 color2, float scale, out vec4 color, out float fac)
{
  vec3 p = co;

  /* Prevent precision issues on signed zeros. */
  p.x = (abs(p.x) <= 1e-05) ? 0.0 : p.x;
  p.y = (abs(p.y) <= 1e-05) ? 0.0 : p.y;
  p.z = (abs(p.z) <= 1e-05) ? 0.0 : p.z;

  p *= scale;

  /* Prevent precision issues on unit coordinates. */
  p = (p + 0.000001) * 0.999999;

  int xi = int(abs(floor(p.x)));
  int yi = int(abs(floor(p.y)));
  int zi = int(abs(floor(p.z)));

  bool check = ((mod(xi, 2) == mod(yi, 2)) == bool(mod(zi, 2)));

  color = check ? color1 : color2;
  fac = check ? 1.0 : 0.0;
}
Rigoletto Eikenberg (rigoletto) added a comment.Nov 24 2021, 7:52 PM

@Charlie Jolly (charlie) thanks for making the explain. I have a clue know where such things come from.
I didnt thought eevee / cycles uses have their own code for the textures or different precision (float vs floatf), so eevee is faster by less precision.

Brecht Van Lommel (brecht) added a subscriber: Brecht Van Lommel (brecht).Nov 25 2021, 4:26 PM

GLSL shaders may be compiled with less precision or aggressive optimization. It would not surprise me if for example a compiler rearranges that into a fused-multiply-add with less precision.

The current epsilon is 1e-06. Instead of adding new logic with 1e-05, we may as well use that higher epsilon in the existing code?

diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_tex_checker.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_tex_checker.glsl
index f534f3b..c404596 100644
--- a/source/blender/gpu/shaders/material/gpu_shader_material_tex_checker.glsl
+++ b/source/blender/gpu/shaders/material/gpu_shader_material_tex_checker.glsl
@@ -4,7 +4,7 @@ void node_tex_checker(
   vec3 p = co * scale;
 
   /* Prevent precision issues on unit coordinates. */
-  p = (p + 0.000001) * 0.999999;
+  p = (p + 0.00001) * 0.99999;
 
   int xi = int(abs(floor(p.x)));
   int yi = int(abs(floor(p.y)));
Brecht Van Lommel (brecht) added a comment.Nov 25 2021, 4:28 PM

The reason for this is also because you get the same precision issue at 0.0, 1.0, 2.0, ... . So it should not be specific to values near 0.0.

Charlie Jolly (charlie) added a comment.Nov 26 2021, 8:13 PM

I spent a little time investigating this. Not an obvious solution at present.

Higher epsilon causes shifting issues when scale is very small.
Eevee left, Cycles right

The can be fixed by changing the epsilon using the sign of the coordinates.

/* Prevent center shift on small values. */
vec3 s;
float d = 0.00001;
s.x = p.x < 0.0 ? -d : d;
s.y = p.y < 0.0 ? -d : d;
s.z = p.z < 0.0 ? -d : d;
p *= scale;

/* Prevent precision issues on unit coordinates. */
p = ((p + s) * 0.99999);

Fixed centered checker. This would break existing behaviour.
Eevee left, Cycles right

Even with low epsilon values, at values near the epsilon there are precision issues
Eevee left, Cycles right

Precision with low epsilon is fixed with the signed zero precision check.

/* Prevent precision issues on signed zeros. */
p.x = (abs(p.x) <= 1e-05) ? 0.0 : p.x;
p.y = (abs(p.y) <= 1e-05) ? 0.0 : p.y;
p.z = (abs(p.z) <= 1e-05) ? 0.0 : p.z;

With both zero check and center fix at scale 0.000001.
Eevee left, Cycles right

Even with the fixes, there is still an issue with cube at scale 1.0

Rigoletto Eikenberg (rigoletto) added a comment.Nov 27 2021, 9:11 PM

Could it be the problem comes from the "mod" function? There may be differences mod vs %.

Brecht Van Lommel (brecht) added a comment.Nov 29 2021, 5:37 PM

I think shifting when the scale is very small is acceptable.

I don't see a reason to think the problem comes from mod.

Charlie Jolly (charlie) added a comment.Nov 29 2021, 11:59 PM

Overall the result is slightly better increasing the epsilon but still has issues.

I'll try a few other ideas before creating a patch.

This is the shifting when scale is 0.001.

Issues at scale 42.3.

Issues at scale 1.

Charlie Jolly (charlie) added a comment.EditedDec 15 2021, 2:38 AM

I've added a patch for a possible solution by adding option to lock axis on checker texture. I wasn't satisfied with changing the epsilon as a solution.

D13582: Nodes: Add axis lock to Checker texture node

Michael (michael64) added a subscriber: Michael (michael64).Dec 15 2021, 4:07 PM

Hello @Charlie Jolly (charlie),
I really don't like flickering so I tried a different approach for a checker texture in P2665.
For me that was stable on different orders of magnitude but as every GPU has a different
take on math maybe that is worse on different hardware.

Charlie Jolly (charlie) added a comment.EditedDec 15 2021, 5:59 PM

@Michael (michael64) I'll take a look and report back.

Seems like it works in a similar way to increasing the epsilon.

Scale: 0.001 - shifting from center

Scale: 8.000 - different pattern to cycles

Charlie Jolly (charlie) changed the subtype of this task from "Report" to "Known Issue".Dec 31 2021, 9:40 PM

I haven't found a nice way of solving this issue other than providing option for 2D texture in D13582.

Change status to known issue and add the link to the workarounds in the manual here:

https://docs.blender.org/manual/en/latest/render/shader_nodes/textures/white_noise.html#notes