views:

327

answers:

3

I have a tex2D sampler I want to only return precisely those colours that are present on my texture. I am using Shader Model 3, so cannot use load.

In the event of a texel overlapping multiple colours, I want it to pick one and have the whole texel be that colour.

I think to do this I want to disable mipmapping, or at least trilinear filtering of mips.

sampler2D gColourmapSampler : register(s0) = sampler_state {
    Texture = <gColourmapTexture>; //Defined above
    MinFilter = None; //Controls sampling. None, Linear, or Point.
    MagFilter = None; //Controls sampling. None, Linear, or Point.
    MipFilter = None; //Controls how the mips are generated. None, Linear, or Point.
    //...
};

My problem is I don't really understand Min/Mag/Mip filtering, so am not sure what combination I need to set these in, or if this is even what I am after.

What a portion of my source texture looks like;
http://img689.imageshack.us/img689/6171/sourcev.png

Screenshot of what the relevant area looks like after the full texture is mapped to my sphere;
http://img717.imageshack.us/img717/9202/resultc.png
The anti-aliasing/blending/filtering artefacts are clearly visible; I don't want these.


MSDN has this to say;

D3DSAMP_MAGFILTER: Magnification filter of type D3DTEXTUREFILTERTYPE

D3DSAMP_MINFILTER: Minification filter of type D3DTEXTUREFILTERTYPE.

D3DSAMP_MIPFILTER: Mipmap filter to use during minification. See D3DTEXTUREFILTERTYPE.

D3DTEXF_NONE: When used with D3DSAMP_MIPFILTER, disables mipmapping.

Another good link on understanding hlsl intrinsics.


RESOLVED

Not an HLSL issue at all! Sorry all. I seem to ask a lot of questions that are impossible to answer. Ogre was over-riding the above settings. This was fixed with;

Ogre::MaterialManager::getSingleton().setDefaultTextureFiltering(Ogre::FO_NONE , Ogre::FO_NONE, Ogre::FO_NONE);
A: 

If you want to have really just one texel, use load instead of sample. load takes (as far as i know) an int2as an argument, that specifies the actual array coordinates in the texture. load looks then up the entry in your texture at the given array coordinates.

So, just scale your float2, e.g. by using ceil(float2(texCoord.x*textureWidth, texCoord.y*textureHeight)).

MSDN for load: http://msdn.microsoft.com/en-us/library/bb509694(VS.85).aspx

When using just shader model 3, you could a little hack to achieve this: Again, let's assume that you know textureWidth and textureHeight.

// compute floating point stride for texture
float step_x = 1./textureWidth;
float step_y = 1./textureHeight;

// compute texel array coordinates
int target_x = texCoord.x * textureWidth;
int target_y = texCoord.y * textureHeight;

// round to values, such that they're multiples of step_x and step_y
float2 texCoordNew;
texCoordNew.x = target_x * step_x;
texCoordNew.y = target_y * step_y;

I did not test it, but I think it could work.

phimuemue
Ah, so perfect. Alas, I can only use Shader Model 3, and this is 4+ only. +1 though, as I didn't specify that.
RJFalconer
I've resolved my problem, but out of interest, can you explain your editted answer a little more please? I don't understand the shader model 3 hack. What do you pass texCoordNew into?
RJFalconer
+1  A: 

What you have done should turn off filtering. There are 2 potential issues, that I can think of, though

1) The driver just ignores you and filters anyway (If this is happening there is nothing you can do) 2) You have some form of edge anti-aliasing enabled.

Looking at your resulting image that doesn't look much like bilinear filtering to me so I'd think you are suffering from having antialiasing turned on somewhere. Have you set the antialiasing flag when you create the device/render-texture?

Goz
Ahem. Yes, good call. :$. The application is in Ogre, which does have an anti-aliasing aspect, which was indeed enabled. I am however wanting to sample from this texture, not draw it, so I don't think it's an issue. I'm currently drawing it as a test. Confusingly, disabling anti-aliasing still shows the same artefacts.
RJFalconer
So what do you want? Do you want the light grey not to get applied to the object? Or do you want to have the stair step jaggy effect round the edge of the dark portion of the texture?
Goz
@RJFalconer: Anti-aliasing is not a global property, it's a property of your render target. That said, I'm confused by the picture. Where are your primitive boundaries ? Antialiasing should only show its effects there. Do the primitive boundaries align with the texture discontinuities?
Bahbar
@Goz I want the jagged effect, 2 tones of grey only. @Bahbar the model is a sphere of some sort. I don't know where the vertex boundaries are relative to that image. The artefacts do however appear in many places across the sphere.
RJFalconer
@Bahbar: Most forms of Anti-aliasing does not just anti-alias polygon boundaries. 2x Super-sampling renders to 4 times the size and then averages every 4 pixels into 1. This will blur EVERYTHING as well as the polygon edges. 4 tap Multi-sampling will do similar as it will generate 4 samples and then blend them together into 1 pixel.
Goz
@Goz: yeah, SSAA would, but that's not what the AA controls on render targets. It (mostly for all cards I've seen) controls MSAA, which only affects the result on edge boundaries (Fragment shader runs once per pixel, gets stored for each sample that is covered by the triangle. If the triangle covers all the samples of the pixel, then it's as if you run with no AA at all, which is what I believe happens here).
Bahbar
+1  A: 

What it looks to me is that you're getting the values from a lower level mip-map (unfiltered) than the highest detail you're showing.

MipFilter = None 

should prevent that, unless something in the code overrides it. So look for calls to SetSamplerState.

Bahbar
No calls to that. Other samplers do have a different sampler_states though.
RJFalconer
@RJFalconer: so, are you sure you're using the correct effect for the draw in question ?
Bahbar
Yes, I'm certain.
RJFalconer
Gah. I did have filtering enabled. Ogre was overriding the shader and doing texture filtering itself. Fixed with "Ogre::MaterialManager::getSingleton().setDefaultTextureFiltering(Ogre::FO_NONE , Ogre::FO_NONE, Ogre::FO_NONE);".
RJFalconer