Dependent texture reads

Hi,

I need to apply a colour map (palette) to a monochrome texture. So far I have identified three solutions:

  1. Use GL_EXT_paletted_texture
  2. Employ a fragment shader that performs a dependent texture read.
  3. Map the input intensities to RGBA values in software.

Option 3 is the fallback, but it is slow. Options 1 and 2 are not available on some of the gfx hardware we need to support (Intel and previous-generation ATI chipsets).

My question is this: from page 655 of the Red Book (5th Ed, OpenGL 2.0), I gather that dependent texture reads can be accomplished using the combiner texture environment. I would be very grateful if someone could point out how to do that!

I gather that dependent texture reads can be accomplished using the combiner texture environment.
No. They cannot.

You can’t use the texture environment to actually change the texture coordinate. You can mix and match the various texture environment inputs, but the texture coordinate itself is not changable by the environment.

Originally posted by mabraham:
Options 1 and 2 are not available on some of the gfx hardware we need to support (Intel and previous-generation ATI chipsets).
How old hardware are we talking about? Dependent texture reads are supported from Radeon 8500 (well, original Radeon supports EMBM which is a form of DTR but of course not as flexible).

What about using glPixelMap to do it? That <might> be faster than pure software, and just needs the imaging subset, or so I believe (but open to correction on that).

Humus, regarding EMBM -

to me, your comment suggests that one could use a cubemap, or an environment map, to do palette lookups (on supported HW, and taking into account the projections involved in the mappings, of course).

Does that sound viable?

Originally posted by charliejay:
What about using glPixelMap to do it? That <might> be faster than pure software, and just needs the imaging subset, or so I believe (but open to correction on that).
Tried that one a while ago, and it’s software emulated and dreadfully slow. Our software path is actually not too bad. It takes around 4…5ms to map a 1024x1024 buffer (on an AMD 4200X2), but then you need to upload 4x as much texture data so that adds significant extra time.

I will investigate bump mapping. FYI, we would very much like to support Mobility Radeon 9000 and the Intel Extreme chipsets. Obviously these are usually paired with not-so-fast CPUs and so the problem becomes even more important.

Cheers,
Matt.

I have since discovered that the Mobility Radeon 9000 supports GL_ATI_fragment_shader, so I added a code path for that, with the following shader:

  
            // PASS 1
            // sample texture unit 0 (the colour index buffer) with texture coordinates specified for texture unit 0,
            // and store the result in r0
            gl.glSampleMapATI( GL.GL_REG_0_ATI, GL.GL_TEXTURE0, GL.GL_SWIZZLE_STR_ATI ); // free
            // some no-op in the first pass...
            gl.glColorFragmentOp1ATI( GL.GL_MOV_ATI, GL.GL_REG_0_ATI, GL.GL_NONE, GL.GL_NONE, GL.GL_REG_0_ATI, GL.GL_NONE, GL.GL_NONE );
            // PASS 2
            // sample texture unit 1 (the palette 1-D texture), with texture coordinates from the previous pass
            gl.glSampleMapATI( GL.GL_REG_1_ATI, GL.GL_REG_0_ATI, GL.GL_SWIZZLE_STR_ATI ); // free
            // r0 = primary * r1
            gl.glColorFragmentOp2ATI( GL.GL_MUL_ATI, GL.GL_REG_0_ATI, GL.GL_NONE, GL.GL_NONE, GL.GL_PRIMARY_COLOR, GL.GL_NONE, GL.GL_NONE, GL.GL_REG_1_ATI, GL.GL_NONE, GL.GL_NONE );
            gl.glAlphaFragmentOp2ATI( GL.GL_MUL_ATI, GL.GL_REG_0_ATI, GL.GL_NONE, GL.GL_PRIMARY_COLOR, GL.GL_NONE, GL.GL_NONE, GL.GL_REG_1_ATI, GL.GL_NONE, GL.GL_NONE );

This works, except it shows some strange artefacts in the image. These are faint lines around certain (brighter) areas in the original image. Definitely NOT present in the software-mapper path. Does anyone know why that could be? FYI: texture unit 0 is the 2-D color index texture, internal format GL_LUMINANCE, and unit 1 is a 1-D BGRA texture containing the 256 palette entries.

Thanks,
Matt.

PS: Above is Java code (we use JOGL).

Any chance of a screenshot of the problem?

What’s the texture environment mode?

(I think that’s the right term) - talking about the decal/replace/modulate setting.

I had some weird brightening effects with luminance and luminance-alpha textures under similar circumstances on a Mobility Radeon 9200 on a mac using text fragment shader, which AFAIK is the same extension but with a program string interface bolted on. Those may have been with the decal mode, for which results with those textures are undefined.

Charlie,

I can’t seem to attach files to this thread so can you send me a PM with an email address, and I’d be very happy to send you a screenshot showing those artefacts.

The artefacts appear to be independent of the texture environment mode (GL_TEXTURE_ENV_MODE), we just use the default (GL_MODULATE) anyway. In any case, I was under the impression that these are for the fixed function pipeline only?!

Matt.

I just “fixed” those artefacts produced by the shader, by setting ‘Anisotropic Filtering’ to ‘Application preference’ in the driver settings (for some reason, it had been set to 8x).

Strange though that this should have any impact… anyway I’m glad it’s sorted.

I can’t figure out how EMBM should help me do what I want (to palettise the index buffer), so I’d be very grateful if someone could provide more details.

Just checking, but when you say “index buffer”, are we talking about OpenGL’s Color Index Buffer, capital letters intended, or about something more general?

EMBM, from what I’ve read, uses the value in a bump map to locate the value in an environment map. That’s a palette lookup, if your palette’s in the environment map.

It seems to depend on extensions, which might limit it’s use for your purposes, unless there are a fair number of cards which will do EMBM but won’t do shaders.

Sorry for the confusion, with “index buffer” I denote my buffer of input values that should be colour-mapped. Nothing OpenGL-specific…

Hmm, am having doubts now about whether this would work with a single channel texture, since if the same number gets replicated into R,G,B, before the pixel is used as a normal into the environment map, then you sample the same single point in the map all the time, because your vector is 1,1,1 all the time.

I think it should work with an RGB(A) texture that has zeros in two of the color channels, though…

Originally posted by mabraham:
I can’t figure out how EMBM should help me do what I want (to palettise the index buffer), so I’d be very grateful if someone could provide more details.
It probably won’t be useful for that. I only through it in there because it’s a form of dependent texture reads. It doesn’t allow looking up at a specific address, only offsetting the coords. Maybe if you found a way to cancel out the effect of adding the source texture coords.

All,

Thanks for your help! I now have my colour mapper working for:

  1. GLSL
  2. ARB_fragment_program
  3. ATI_fragment_shader
  4. EXT_paletted_texture
  5. software BGRA mapping

With options 1…4 I get decent acceleration on a wide variety of hardware, including ATI (Mobility) Radeon 9000 and (Mobile) Intel 915/910 series, as well as pretty much all NV chipsets out there.