8
$\begingroup$

I am working on Silverlight app. I am trying to render floor covered with tiles. Although I am using mip maps I am still getting awful Moire patterns, when trying to render big area.

What I am doing is creating cuboid and then cover it with single tile:

enter image description here

In my pixel shader I am multiplying texture coordinates in order to create tiled floor (otherwise I would get one tile stretched over my cuboid). Pixel shader code:

float Width                 : register(c3);                  //Width of cuboid
float Height                : register(c4);                  //Height of cuboid

texture texTexture;
sampler textureSampler  : register(s0) = sampler_state {
    Texture = (texTexture);
};

struct VsOutput
{
    float4 position : POSITION;
    float3 dirLightPosition : COLOR;
    float2 texCoord : TEXCOORD0;
    float3 normal   : TEXCOORD1;
    float3 view : TEXCOORD2;
};

float4 main(VsOutput IN) : COLOR
{
    float2 texCoord = float2(IN.texCoord.x * Width / 4.0f, 
                             IN.texCoord.y * Height / 4.0f); //multiplying texture coordinates


    float4 texColor = tex2D(textureSampler, texCoord);

    return float4(color.r, color.g, color.b, 1.0f);
}

My output is:

enter image description here

What else can I do to prevent from creating Moires patterns on texture?

$\endgroup$
6
  • $\begingroup$ Have you verified that mipmaps are actually used? The screenshot looks like bilinear filtering, instead of trilinear, $\endgroup$ Oct 7, 2015 at 13:47
  • $\begingroup$ @JulienGuertault It may just be my poor eyesight but I can't see any distinct discontinuities that'd be indicative of just bilinear + nearest MIP map. $\endgroup$
    – Simon F
    Oct 7, 2015 at 13:57
  • $\begingroup$ Actually my sampler state is set to AnisotropicWrap, which, I believe, is the best. Also I am 100% sure, that I use mipmaps. $\endgroup$ Oct 7, 2015 at 14:04
  • $\begingroup$ @SimonF: sorry for the confusion, I meant linear. But anyway, apparently the problem would be elsewhere. $\endgroup$ Oct 7, 2015 at 14:06
  • 1
    $\begingroup$ @Nero I did so :) $\endgroup$ Oct 9, 2015 at 15:56

2 Answers 2

5
$\begingroup$

Two things come to mind:

  1. When generating your smaller mip map levels try to avoid using a simple 2x2 box filter because, though cheap and cheerful, they do a really poor job of removing high frequency information (that exceeds the Nyquist limit) as well as over filtering some of the lower frequency information you need to keep. (Also, as an aside, you need to perform the MIP map generation in linear space. If your source data is sRGB, you thus need to map to and from linear). FWIW, In Williams' original paper on MIP mapping, he said he used a "box (Fourier) window" to generate the prefiltered levels, which would be a sinc function in image space.

  2. Standard Trilinear filtering will also over- and under-filter parts of the texture. If you don't like the aliasing you may have to a) adjust the bias to increase the filtering (which will increase blurring) and/or b) try using anisotropic filtering.

$\endgroup$
7
  • $\begingroup$ Sorry for maybe stupid question, but what is '2x2 box filter'? Does it have any other name? $\endgroup$ Oct 7, 2015 at 14:18
  • $\begingroup$ I just meant the naive method of generating the next lower, X*Y MIP map level from the 2X * 2Y level above it. I.e. that of averaging 2x2 texels in the upper level to produce the corresponding texel in the lower one. It's cheap, but it's not great. Even a simple 4x4 tent filter should produce a far better result. $\endgroup$
    – Simon F
    Oct 7, 2015 at 14:25
  • $\begingroup$ Just to make sure I fully understand you - now I am creating my mip maps like this: pastebin.com/nX1MVvEp . Instead of that i should generate mipmaps from my original texture with original size yes? $\endgroup$ Oct 7, 2015 at 14:34
  • $\begingroup$ Well, I don't know what is inside the "resize" function so it's a little difficult to answer. The chaining, ie. 1024 generates 512, 512 generates 256, etc is not going to be a huge problem, as long as what's going on inside "resize" is ok. As an experiment, could you create a 1024^2 texture that's all 0xFFFFFF except for the top left pixel which you set to pure red, (0x0000FF). What do you get in the 512^2 result? $\endgroup$
    – Simon F
    Oct 7, 2015 at 14:47
  • $\begingroup$ My result: postimg.org/image/atd8nc4j3/3636ad65 $\endgroup$ Oct 7, 2015 at 14:55
2
$\begingroup$

SOLUTION

I managed to solve my problem by increacing size of texture 2048x2048px so there would be generated more mipmaps. Also it seems like changing my SamplerState form anisotropic to something like that helped:

SamplerState MirrorTexCoord = new SamplerState()
        {
            AddressU = TextureAddressMode.Mirror,
            AddressV = TextureAddressMode.Mirror,
            .
            .
            .
        };

Actually I don' t know what is TextureAdressMode.Mirror, but it helped a lot, now it looks like this:

enter image description here

$\endgroup$
4
  • 1
    $\begingroup$ Mirror is likely to define what happens when your texture repeats. In the normal mode (just considering horizontal only) if you had a texture that looked like "<" you'd get "<<<<<". With mirroring you get "<><><><><". Obviously can also apply to vertical direction as well. $\endgroup$
    – Simon F
    Oct 9, 2015 at 16:15
  • $\begingroup$ It looks like increasing the resolution is the main helper. Moires patterns are just barely starting to form in the back corner of the rectangle. $\endgroup$
    – RichieSams
    Oct 9, 2015 at 16:32
  • $\begingroup$ Actually no, mirroring does most of the job :) I tested it with mirroring only and with bigger texture only as well, and turned out that mirror provides great effect. Fortunatelly tile texture is simetric so it' s not a big deal. $\endgroup$ Oct 9, 2015 at 16:38
  • $\begingroup$ It's hard to judge how much of an improvement this has made since the plane does not extend as far into the distance as in the example in the question. $\endgroup$ Oct 16, 2015 at 7:55

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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