GL_TEXTURE_3D filtering

Hi,
Does anyone know how to use a separate
GL_TEXTURE_MAG_FILTER
GL_TEXTURE_MIN_FILTER
parameter for the depth axis?

Many thanks.

No can do (unless there’s some specific hardware that supports it, like the PS2, and exposes it in an extension, which I think none does)

You may wish to look into TexGen in EYE_LINEAR space to emulate the effect you’re looking for.

Thanks!
Too bad though…
Must be a way to get to it, I simpy want to use 3d textures mipmapped and filtered in w/h but unmipped / GL_NEAREST in depth.
Wish things were a little more programmable.

Cheers.

Hi again. Re-activating an old post of mine.
I should probably dig into the specs myself but I can not wait to find out: Could this be done using fragment programs? Im sure it will be easy with GL 2. It would mean that instead of baking a big texture cake, and loosing tex tiling feature, we bind a 3D texture and switch texture using the 3rd (s)texcoord. All textures have to be same size though. This is also very usable for possible multi-layered depth shadow maps / projected soft-shadows.

Cheers.
FritzLang

[This message has been edited by fritzlang (edited 12-07-2002).]

Yes, you can put whatever you want into the “r” coordinte using a fragment program. Just like you can put z into “r” using texgen. However, that doesn’t help you, because you will still suffer the filtering problem if you want to use mip mapping or anisotropy. The filtering is implicitly derived from your sampling instruction in the ARB_fragment_program spec.

Thanks again!
So what you are saying is that fragment progams does not expose this type of
control, that after all the actual
function of filtering / mipmap is in the driver, making the effect of the code
below impossible?

// S & T
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER,
GL_LINEAR);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_3D, GL_GENERATE_MIPMAP_SGIS,
GL_TRUE);

// R:
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER,
GL_NEAREST);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER,
GL_NEAREST);

Cheers.

[This message has been edited by fritzlang (edited 12-07-2002).]

Filtering is done during rasterization. If minification is required, then the state you setup is used. Ditto for magnification.
It’s not done per texture coordinate.

This case could be reduced do the 2D version where some rows require linear filtering, some require mipmaping, some nearest. How exactly would you do this?

V-man

Fragment programs don’t change the way regular OpenGL texturing filtering works, but it is possible to code your own filters using fragment programs. In your example, you could do 8 lookups into your 3D texture (using nearest filtering), and then do the interpolation however you like using a few lerp instructions.

Bicubic filtering, summed area tables and other interesting filtering schemes are all possible in a similar way.

Bear in mind this is will be considerably slower than a normal texture lookup since you’re not taking advantage of the bilinear filtering hardware.

-Simon.

Make sure your texture coordinates on the ‘unfiltered axis’ are setup in a way that nullifies the effects of linear filtering.

Ie the r texture coordinates should satisfy

r=n*1.0/(texture_depth) + 0.5/(texture_depth)

where n is a whole number.

Eg for a 3D texture with depth of 256, the r coordinate should be one of these
1/512, 3/512, 5/512, 7/512 …
and so on.

This will not disable the filtering of course, you’ll still take the performance hit of the additional texel fetch. But the visual result should be what you want (if I didn’t make any blatant mistake).

[QUOTE]Originally posted by V-man:
[b]Filtering is done during rasterization. If minification is required, then the state you setup is used. Ditto for magnification.
It’s not done per texture coordinate.

I realise all this. My point was to use
a 3D texture as an array of 2D ones, the 3rd
coordinate just index into a 2D texture and “selects” it. Hence no filter and mipmap in the 3rd axis.
But I realize that getting into pixel programs, I sure loose the speed benefit which was the whole point.
I wanted to minimize texture bindings, being able to have texture id’s in a vertex array and being able to use tiling. This way one
does not have to sort the render cue by material.

fritzlang

zeckensack:

I think you made the blatant mistake of adding a half pixel This will make it always average neighboring pixels rather than picking the pixel you want. Recall that a texture coordinate of 1 picks the same pixel as a coordinate of 0, rather than picking the last pixel in the texture.

I’ve deliberately added half a texel, because IIRC that means ‘the center of that thingy’.

0 would then not be the center of a texel, but the texel edge instead. Isn’t this the same thing as demonstrated by all these GL_CLAMP_TO_EDGE problems?

shrugs

Just try it out

[QUOTE]Originally posted by zeckensack:
[b]Make sure your texture coordinates on the ‘unfiltered axis’ are setup in a way that nullifies the effects of linear filtering.

You are a genius.
Just tried it and it works perfectly.

Now this solves so many things!
Just build a 3D texture out of your 2D ones, and put the texid into the vertex array
(and pref. into VRAM).
3D textures should work on GF3 and up.

Thanks everyone.
fritzlang.

[This message has been edited by fritzlang (edited 12-07-2002).]

zeckensack:

I didn’t say you did it accidentally, I said it was a mistake . However, brushing up on my texture coordinates, it looks like you are correct about how the filtering happens, that you do need to add 0.5, and that I am the one who was mistaken.

[This message has been edited by Coriolis (edited 12-07-2002).]

Originally posted by zeckensack:
[b]0 would then not be the center of a texel, but the texel edge instead. Isn’t this the same thing as demonstrated by all these GL_CLAMP_TO_EDGE problems?

shrugs

Just try it out [/b]

There’s no center, remember? That whole numbers are exactly between neighboring texels and what happens to 0.0 and 1.0 depends on the WRAP mode.

But yup, your are a genius! So obvious and beautiful. Just simplify it

r = (n + 0.5) / texturedeth

V-man

Mipmaps seem to ruin this whole concept,
they seem to blend whatever approach I
use. As it stands now, all this is only
appliable at the base texture level,
ie. GL_LINEAR
and not
GL_LINEAR_MIPMAP_LINEAR nor
GL_LINEAR_MIPMAP_NEAREST

Tweaking texture level / lod does not
help.

fritzlang

[This message has been edited by fritzlang (edited 12-08-2002).]

If you are slicing through the 3D texture in the r direction, then it will work.

In other words, if your slices (quads) all have the same r value for the texture as computed with the equation above, it will work, otherwise, the “undesirable” filtering effects will appear in the “r direction”.

V-man

Originally posted by V-man:
[b]If you are slicing through the 3D texture in the r direction, then it will work.

Thanks. But, what do you mean exactly?

// We have a 3D texture 512x512x16 - that
// is we have 16 slices we want to acess.
int texDepth = 16;
int currTex = 7;
float r = (currTex + 0.5f) / texDepth;

glMultiTexCoord3fARB
(GL_TEXTURE0_ARB, 0, 0, r);

This works fine nearby, displaying only slice no 7, but moving away or in sharp perspective, slice currTex +/- 1,2,3…
now leaks in and blends badly.
In a way it makes sense to me, since the “nullification” math gets less precise with growing mipmap levels.
But you really mean this can be avoided?

fritzlang

(Since a 3D mipmap must be a half-res version of the previous ‘cube’, it must mean that one loose half r slices per mip level. For the initial idea to work, the mipmaps must be regular 2D mipmaps stored “per slice”. Shouldn’t this be impossible!?)

[This message has been edited by fritzlang (edited 12-09-2002).]

I don’t think it’s possible with mipmapping in the general case.

You could duplicate slices to get more leeway. And you must avoid those smaller mipmaps that start blending together two of your ‘wanted’ slices.

You may get away with a mipmap level restriction (see SGIS_texture_lod) to +2, quadrupling each slice. The tradeoff is between memory and texture aliasing.

1)Is there a guaranteed minimum texel/pixel ratio in your app?

2)Would regular 2D textures and texture switching really be that expensive in your program?

Originally posted by zeckensack:
[b]I don’t think it’s possible with mipmapping in the general case.

Me neither. I mean, its obvious the more I think of it. The “nullification” formula got rid of the filtering but, for it to work, r axis cannot at all be mipmapped:

base 512x512x16
mip1 256x256x16
mip2 128x128x16

mip9 1x1x16

Now that does not look very possible to achieve in standardized way, does it?

Originally posted by zeckensack:
Would regular 2D textures and texture switching really be that expensive in your program?

Maybe not. I just find the whole concept of sorting by material very un-elegant, especially as multitexture layers grow.
I mean, was it not for the cost and
mechanics of texture switches, we could almost draw everything in one go. Binding an array of 2D textures (=3D) and switch using a vertexarray parameter would have been such an aesthetic way to go.

Now I guess its back onto auto-baking / stitching a few 2K and 4K palettes. Any other ideas maybe, how one should (re)design the fastest texture / material / bumpmap / render manager with a GeforceFX in mind?

fritzlang

[This message has been edited by fritzlang (edited 12-10-2002).]