4
$\begingroup$

I have a simplistic shader program that adds reference coordinate planes to a scene.

These planes are drawn as intersecting lines.

When viewed at a distance, a visual artifact is created; there is a ripple of lighter and darker areas going left to right across the image.

with anti-aliasing

Given how simple the shader program is, I think this must be due to the interpolation that occurs between the vertex and fragment shaders.

  • (a) Does this type of artifact have a name?
  • (b) What causes it?

I looked into whether this was being caused by anti-aliasing. However, disabling the anti-aliasing shows that the pattern is created beforehand. See here:

without anti-aliasing

in short:

  • this is a Moire pattern (see lfgtm's answer)
  • it is caused by trying to map a perspective projection of parallel lines onto a fixed grid of pixels. (see zoran's answer)

When looking at ways to address this problem, I thought that drawing the lines as surfaces with a gradient transparency across the width of the line would help by allowing the line to straddle pixels and giving it a more accurate width.

Here is how the grid looks when drawn as simple lines vs surfaces with gradient transparency.

lines vs surfaces

This improved the definition between lines at a distance (i.e. they don't overlap each other and create a solid plane). However, this had little appreciable effect on the light & dark ripples.

$\endgroup$
  • 2
    $\begingroup$ One issue here is your lines are constant width, so they don't make sense in perspective as distant lines appear thicker than closer ones. If you where to draw the grid using a texture you can use anisotropic filtering which eliminates a lot of the aliasing pattern. A texture would also be perspective correct and lines in the distance would be thinner as you would expect. $\endgroup$ – PaulHK Apr 14 at 6:17
  • $\begingroup$ @PaulHK, Yes in my experience, anisotropic where applicable has produced the best results when reducing this. $\endgroup$ – lfgtm Apr 14 at 8:46
  • 1
    $\begingroup$ @Marvin, I have updated the answer with an explanation of why this is occuring in your image. Hope this helps. $\endgroup$ – lfgtm Apr 14 at 8:48
  • 1
    $\begingroup$ @Marvin Yes thats the problem with AF, it's only performed on textures. Changing the resolution (not always feisable obviously) will change it's manifestation. You could also try MSAA which yeilds good results at removing moire, but then cannot do stuff like deffered rendering etc... essentially there are pro's and cons to each method which aims to reduce it. Like I said, it will never go away, and even if you fix from one angle, chances are other camera angles will produce it. Certinaly it sounds like you have already spent more time attmpeting to remove it than I ever have ;) Fair play. $\endgroup$ – lfgtm Apr 14 at 14:52
  • 1
    $\begingroup$ @Marvin the other thing to mention... I'm not too sure how you go about detecting it (although there probably are ways). If you could detect it you could perhaps adapt your plan of attack to removing it... but since it depends on many things like resolution, perspective projection etc... it would be difficult to know what to do to fix it for any particular frame. $\endgroup$ – lfgtm Apr 14 at 14:54
2
$\begingroup$

It's a interference pattern, called Moire pattern. You get them in signal analysis and various other fields. I guess it could be considered an optical illusion.

EDIT:

To elaborate, this occurs when a periodic waveform goes out of phase with the observer. In your case the periodic waveform are the lines when observed as a scanline (from left to right of the image or vice versa), and the observer is the image with a set number of horizontal pixels. In some parts, the pixel rasterization falls on pixel boundaries and then there is a watershed moment... should it be rasterized in pixel x, or x + 1. This then manifests as the wave pattern (due to the 'watershed' moment being slightly out of phase with the previous or next scanline i.e one scanline, pixel falls on x, the next scanline it falls on x+1). Also the display device can also have an effect. The moire in your image is much more pronounced on my computer monitor, than it is with my phone. (however this could be due to my phone’s browser scaling or applying some other filtering by default, which could help to reduce it).

Anti aliasing certainly helps, however moire can never be completely eradicated, only mitigated. Also note this can occur with rotated grids in orthographic, however perspective projection will certainly amplify this effect.

| improve this answer | |
$\endgroup$
  • $\begingroup$ Thanks for expanding your answer. I have updated my question with a failed attempt to improve things by drawing the lines as surfaces with a gradient transparency across the line width. I think this failed because alpha blending occurs in the fragment shader, so the watershed moment of having to pick a pixel has already happened. Are there ways to influence how the rasterizer creates fragments? i.e. can it "split" a colour across two fragments using the alpha channel? $\endgroup$ – Marvin Apr 14 at 12:24
  • 1
    $\begingroup$ @Marvin you can certainly perform your own blending in the fragment shader (i.e perform your own form of AA), and perhaps offset/nudge in a geometry shader... but afaik the vertex shader will rasterize the vertex in the pixel prior to the fragment shader being executed (like you say). So without changing the geometry itself, no way to decide (if using vertex/fragment shaders and no geometry shaders). tbh it's just kicking the can down the road. The problem will never go away, simply manifest under different circumstances. $\endgroup$ – lfgtm Apr 14 at 14:48
1
$\begingroup$

The pattern you are seeing arises from perspective projection. Which causes all those parallel lines not to be parallel to each other when projected on the screen.

Your problem with darker and lighter areas is caused by anti-aliasing which is trying to smooth the lines that are sometimes passing right in between 2 pixels, so it blends the lines with the black background.
You also have a problem that sometimes there is an empty (black) pixel between the lines lines and sometimes the lines are right next to each other.

All this always occurs but the reason you're noticing a pattern here is that you just have a lot of really dense parallel lines.

This reminds me of a common problem in game graphics where high-resolution textures viewed from a distance tend to look bad and flicker from frame to frame.
The usual way that is solved is by using a lower resolution texture when the object is far away.

For you an equivalent would be to have more lines closer to the perspective camera and fewer lines further away. I'd also recommend adding transparency to the denser lines as they get further away to achieve a smooth transition.

Edit: Just ran into a problem that has the most pronounced version of this effect, it's called shadow acne

| improve this answer | |
$\endgroup$
  • 2
    $\begingroup$ thanks for your answer, I found it helpful in understanding the cause of the pattern. However, since lfgtm did help me identify it, I will leave his answer as accepted. $\endgroup$ – Marvin Apr 14 at 1:43
1
$\begingroup$

Although it's not wrong to call it an interference pattern, it isn't the whole story here.

The difference between the dark and bright areas is caused by antialiasing (filtering) which is done in the wrong color space. The lines drawn as a single bright pixel (red=219) do not have the same apparent brightness as the lines drawn as two darker pixels (red=118).

After some fiddling with the numbers, they appear to be a match for "TV RGB" which is a range 16-235, given that ${219-16\over2}+16=117.5$ But those values are wrong even if you actually have a monitor correctly configured for that range (unlikely) as it is still not linear, as far as I know.

Here's what a better filtered grid should look like: perspective grid Make sure to view this in its own window, without any browser zoom applied as that can introduce its own artifacts.

| improve this answer | |
$\endgroup$
  • $\begingroup$ From what I understood he draw red lines over a black background, meaning that the anti-aliasing was done automatically, which means that wrong color space is not the source of this effect. $\endgroup$ – zoran404 Apr 14 at 0:58
  • $\begingroup$ an interesting thought, but disabling anti-aliasing shows that this is no the source of the pattern. $\endgroup$ – Marvin Apr 14 at 1:32
  • 1
    $\begingroup$ @zoran404 just because it is done automatically does not mean it is done correctly. $\endgroup$ – Olivier Apr 14 at 17:30
  • 1
    $\begingroup$ @Marvin It's a little more than a thought, I've spent weeks staring at poorly filtered grids as part of my day job. And written better filters to improve them. I will add an image so you can see for yourself. $\endgroup$ – Olivier Apr 14 at 17:59
  • 1
    $\begingroup$ @Marvin that's a reasonable summary, yes. Just like digital cameras usually have a physical lowpass filter (ie. a piece of glass to blur the image) to avoid moiré at the sensor. Except for the color space issue, it appears to be doing a reasonable job for hardware rendering. I unfortunately don't know enough about OpenGL to be of much help on how to fix it. Filtering your texture (the grid pattern) is another possible solution. With offline rendering, we usually do both. $\endgroup$ – Olivier Apr 14 at 18:36

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.