ATI_fragment_shader help needed

Can anyone point out what I’m doing wrong here? It’s driving me nuts.

I’m developing a volume rendering application, which uses either 2D or 3D textures (depending on graphics card) to render the volume. I’m also implementing an interactive transfer function using whatever means the card supports. So with GF3 and GF4, I use NV_TEXTURE_SHADER extension with a dependent 1D texture and this works fine for both 2D and 3D main textures. For ATI 9700 and above, I’ve used ARB_FRAGMENT_PROGRAM to do a similar thing - this works ok with 2D texture stacks but is buggy with 3D textures. I think I can sort this one eventually. FWIW, the fragment program (which works ok) is like this -

!!ARBfp1.0
ATTRIB inTexCoord = fragment.texcoord;
TEMP texelColour;
TEX texelColour, inTexCoord, texture, 2D;
TEX result.color, texelColour, texture[1], 1D;
END

My problem is when I try to support ATI Radeon 8500 - 9500 using the deprecated ATI_fragment_shader extension. I need to do this to support some laptop demos so I can’t overlook it. Problem is that the documentation is limited and there’s no specific simple examples that I can find. Sure if I want to produce a rusty chrome effect there is plenty of sample code, but not for a very straightforward dependent texture look-up. What I have currently got is this -

My main texture is an 8-bit 2D luminance texture in TEXTURE1. My transfer function is coded in a 256-entry rgba structure which I’ve loaded as a 1D rgba texture in TEXTURE0. The fragment shader (without all the error checking and stuff) started off like this -

glBeginFragmentShaderATI();
glSampleMapATI(GL_REG_1_ATI, GL_TEXTURE1_ARB, GL_SWIZZLE_STQ_ATI);
glSampleMapATI(GL_REG_0_ATI, GL_REG_1_ATI, GL_SWIZZLE_STQ_ATI);
glEndFragmentShaderATI();

This gave me an INVALID_OP on the second glSampleMapATI(). I took this to mean that it couldn’t do the look-up in a single pass. So I forced in a MOV to break it into two passes, like this -

glBeginFragmentShaderATI();
glSampleMapATI(GL_REG_1_ATI, GL_TEXTURE1_ARB, GL_SWIZZLE_STQ_ATI);
glColorFragmentOp1ATI(GL_MOV_ATI, GL_REG_2_ATI, GL_NONE, GL_NONE, GL_REG_1_ATI, GL_NONE, GL_NONE);
glPassTexCoordATI(GL_REG_2_ATI, GL_REG_2_ATI, GL_SWIZZLE_STR_ATI);
glSampleMapATI(GL_REG_0_ATI, GL_REG_2_ATI, GL_SWIZZLE_STR_ATI);
glEndFragmentShaderATI();

The docs tell me to code the glPassTexCoordATI() to preserve R2 between passes. This doesn’t throw any glGetError() but just gives me a totally black volume. I’m guessing that the dependent texture read is not working or maybe the alpha is getting corrupted somewhere. I’ve tried all combinations I can think of (including swapping the texture units) but I just cannot get the damn thing to work. This should be so simple so I guess I’m making a pretty basic mistake somewhere - I’d be really grateful if someone would point it out :frowning:

Thanks in advance,
Roger

From the top of my head:

  1. Make sure the latest drivers are installed, i’ve had many bugs in fragment shaders with older drivers.

  2. Is there a specific reason you use GL_SWIZZLE_STQ_ATI ? It’s for projective texture coordinates. If you are not using those, you should stick to GL_SWIZZLE_STR_ATI.

  3. Dependant lookups can only be done in the second phase. There has to be one instruction at least between two phases, so you were right for the reason your first piece of code was not working.

  4. You should use glPassTexCoordATI only if you want to use a register from the first phase for a calculation in the second phase. You shouldn’t do it for a dependant lookup.

IMO the code should look like this:

glBeginFragmentShaderATI();
glSampleMapATI(GL_REG_1_ATI, GL_TEXTURE1_ARB, GL_SWIZZLE_STR_ATI);
glColorFragmentOp1ATI(GL_MOV_ATI, GL_REG_2_ATI, GL_NONE, GL_NONE, GL_REG_1_ATI, GL_NONE, GL_NONE);
glSampleMapATI(GL_REG_0_ATI, GL_REG_2_ATI, GL_SWIZZLE_STR_ATI);
glEndFragmentShaderATI();

  1. Alpha is not updated by this code. If you are using alpha-blending later, you should output a constant into the reg0.alpha

Y.

[This message has been edited by Ysaneya (edited 03-24-2003).]

R O F L

I already replied to that topic at comp.graphics.api.opengl and believe me or not but I gave exactly the same advices !

Except for point #5 : the alpha component is not undefined as you warn. The fourth channel is undefined when passed through glPassTexCoordATI but glSampleMapATI does pass the alpha channel, otherwise how would you get an alpha channel from a texture ?

Hi guys,

It sounds like I’m getting the best advice here then! I still can’t figure it out but I’m not sure it’s a driver problem because other fragment shader demos work fine. There’s something funny with the alpha though because some combinations I’ve tried give a recognisable image when shown in a white background - it just looks like a negative.

I don’t suppose anyone here has a very simple example of a dependent texture lookup on Radeon 8500 that I can use to test my driver for sure?

Originally posted by Rog:
I still can’t figure it out but I’m not sure it’s a driver problem because other fragment shader demos work fine.

LOL. Excuse me but that’s the most funny thing I’ve heard today.
Driver bugs are BUGS and so forth their behaviour can’t be predictible. The fact that a “complex” shader works does mean that a certain “long” sequence works well, but it does not mean that any other “shorter” sequence will work.

Originally posted by Rog:
There’s something funny with the alpha though because some combinations I’ve tried give a recognisable image when shown in a white background - it just looks like a negative.

Have you tried to disable blending and see what the shader renders ? Also, keep blending disabled and copy the resulting alpha channel into the rgb channel and see what happens too.

As a side note, register combiners and fragment programs do override fog and color sum stages, but fragment shaders don’t. Make sure your fog and color sum are disabled while you run the shader.

Originally posted by Rog:
I don’t suppose anyone here has a very simple example of a dependent texture lookup on Radeon 8500 that I can use to test my driver for sure?

I have a simple program that works on every ATI card that I could test. Source code is included and it’s free of course. I can send it to you by email if you want.

[This message has been edited by vincoof (edited 03-24-2003).]

Originally posted by vincoof:
LOL. Excuse me but that’s the most funny thing I’ve heard today.
Driver bugs are BUGS and so forth their behaviour can’t be predictible. The fact that a “complex” shader works does mean that a certain “long” sequence works well, but it does not mean that any other “shorter” sequence will work.

Yes I take your point. What I meant was that I can’t seem to get a good rendering unless I just use texture0 (i.e. no dependent textures at all). This made me suspect that there was a bug with ARB_multitexture, which I saw was unlikely given that the other demos worked with more than one texture unit.

Originally posted by vincoof:
I have a simple program that works on every ATI card that I could test. Source code is included and it’s free of course. I can send it to you by email if you want.

Excellent! Please could you e-mail it to me at r.rowland@uea.ac.uk that would be a great help!

I’ve mailed a program that shows an example of dependant texture read. The shader is the following :

  • There is a “base” texture mapped in object space (the texture looks like horizontal colored lines).
  • There is a “reflection” texture mapped using sphere-mapping (the texture looks like a random greyscale image).
  • The shader samples the “base” texture which coordinates is offset by the “reflection” texture. The result is the “base” texture which looks distorted when you rotate the viewpoint.

It’s not eye-candy but still it’s representative I think.

He, he, you’re right about the alpha component Vincoof.

Once i had a problem with the alpha component not being set by my fragment shader and it messed up everything i did later. Spent hours finding that bug. I guess it traumatized me :slight_smile:

Rog, maybe your problems are not coming from the shader code itself ? Are you sure you bind the correct textures and that all states are correct ? If you have a look at the output of the first phase (before the lookup) do you see the expected results ?

Y.

Originally posted by Ysaneya:
Rog, maybe your problems are not coming from the shader code itself ? Are you sure you bind the correct textures and that all states are correct ? If you have a look at the output of the first phase (before the lookup) do you see the expected results ?

Yes, I do see the expected result if I put my base texture in texture0 then just sample t0 to r0 in the shader. I don’t see the expected result if I put my base texture in t1 then sample to r1 and move to r0 in the shader. I originally thought that this indicated a problem with multi-textures but since testing vincoof’s example, I think I’m making a stupid mistake somewhere else.

I’m now debugging - I’ll let you know what happens …

Thanks for all your help so far.

Originally posted by Rog:
I think I’m making a stupid mistake somewhere else.

SUCCESS!!

After looking at vincoof’s example, the problem is solved! It was a stupid mistake - when I swapped my base texture from t0 to t1 to make the shader code easier, I overlooked the fact that I was specifying texture coordinates with glTexCoord2f() instead of glMultiTexCoord2fARB() - so I was setting coordinates in the WRONG texture unit! The only thing I can say in mitigation is that this part of the code is inherited from a base class so it wasn’t right in front of me all the time.

Thanks for making my day start off on a good note!

That sounds more like a reason to not use C++ (or at the very least to use it more carefully) than a mitigating point

Originally posted by Coriolis:
… or at the very least to use it more carefully …

Yep - I’ve been writing software for 25 years now and I still find I need to do things carefully! The one thing that never changes is my ability to make mistakes and learn lessons