Sign in to follow this  
tingdahl

GLSL fragment shader array problems

Recommended Posts

Hi, I have a 2D texture, and I want to take a single component from that texture and perform a table lookup with it: uniform vec4 ctab[256]; uniform sampler2D DataTexture; void main() { vec4 data = texture2D(DataTexture, gl_TexCoord[0].st); float val = floor( data.r*255.0 + 0.5 ); int idx = int(val); if ( idx<0 ) idx=0; else if ( idx>255 ) idx=255; gl_FragColor = ctab[idx]; } The problem is that the ctab lookup does not work (I get a GL_INVALID_OPERATION error, and the shader does not run). I can hardcode any ctab lookup, e.g. gl_FragColor = ctab[0], with all values from 0 to 255. I can also do a: if ( idx==0 ) gl_FragColor = ctab[0]; else if ( idx==1 ) gl_FragColor = ctab[1]; for all 256 values (0 - 255), and that works, but I don't want to spend GPU time on such lookups. Any clue what could be wrong? /Kristofer

Share this post


Link to post
Share on other sites
Make sure your application finds that table and that it has the right input stuff. Also check that you really are sending right kind of data, check the size too.

If those don't help please include more information about you application.

Share this post


Link to post
Share on other sites
I don't know for sure, but I am thinking your hardware isn't capable or drivers are too old? On my 8800GTX it runs fine with 97.02 drivers. Using Render Monkey.

Share this post


Link to post
Share on other sites
Yeah, are you sure your card allows that many (256*4) uniform variables? It might work when you hardcode the index because the compiler recognizes that you don't actually use the whole array and simplifies it. Try making the array smaller and see if that works, or use glGet with whatever the name is (GL_MAX_UNIFORMS or something to that effect).

Share this post


Link to post
Share on other sites
I'm using an NV Geoforce 6600 card, with the 9631 driver. Could it be that my card is too weak?

I can have 512 uniforms, but I still have the problem if I reduce the array-size to 10. The data in the structures seem to be fine, as I can display each value through the hard-coded lookup.

Since the number of uniforms is a limit, I decided that I should't use an array, but a second texture. I can display any of the two textures individually, but as soon as I want to
combine the information from the two, it doesn't work (see code below). Any clue?

/Kristofer

uniform sampler2D DataTexture;
uniform sampler1D ctab;

void main()
{
vec4 data = texture2D( DataTexture, gl_TexCoord[0].st );

gl_FragColor = texture1D( ctab, 0.5 ); //Works
gl_FragColor = texture1D( ctab, gl_TexCoord[0].t ); //Works
gl_FragColor = texture1D( ctab, gl_TexCoord[0].s ); //Works
gl_FragColor = texture1D( ctab, clamp(data.r,0.0,1.0) ); //Doesn't work
gl_FragColor = vec4( 0, data.r, 0, 1 ); //Works
gl_FragColor = vec4( 0, data.r,
texture1D( ctab, data.r ).r , 1 ); //Does not Work
}

Share this post


Link to post
Share on other sites
Quote:
Original post by tingdahl
uniform vec4 ctab[256];
uniform sampler2D DataTexture;

void main()
{
vec4 data = texture2D(DataTexture, gl_TexCoord[0].st);
float val = floor( data.r*255.0 + 0.5 );

int idx = int(val);
if ( idx<0 ) idx=0;
else if ( idx>255 ) idx=255;
gl_FragColor = ctab[idx];
}


The problem is that the ctab lookup does not work (I get a GL_INVALID_OPERATION error, and the shader does not run). I can hardcode any ctab lookup, e.g. gl_FragColor = ctab[0], with all values from 0 to 255. I can also do a:

if ( idx==0 ) gl_FragColor = ctab[0];
else if ( idx==1 ) gl_FragColor = ctab[1];

for all 256 values (0 - 255), and that works, but I don't want to spend GPU time on such lookups. Any clue what could be wrong?

If I get it right, you're doing dynamic uniform indexing in the pixel shader. This does not work on PS3.0 hw (EDIT: MARS can run it because 8800 is SM4.0). This is why the "faked switch" works: it doesn't require dynamic indexing. I am not sure because my driver rejected this on compile/link stage. Maybe it's unable to guess it.

You should put your values in the look-up-table directly.

Think at it! Right now, you're basically using a LUT indicating what uniforms to use. Then you fetch the uniform values based on the lookup.
Now, if you're on a NV40, you can just use FP32 textures and loop on it. I already did this and it worked great. You also get the possibility to update all the uniforms in a single blow (some sort of G80 "constant buffer") and a whopping amount of values!

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this