Sign in to follow this  
zaneski13

GLSL Array Problem [SOMEWHAT SOLVED]

Recommended Posts

_____________________________________________________________________________________________ [EDIT] THE NEW PROBLEM'S DESCRIPTION IS AT THE 6'TH POST [/EDIT] _____________________________________________________________________________________________ I spent the past couple days messing around with shaders. When I found out that my graphics card has trouble running through loops I decided to make my program create the source code for the shader at run time, based on the number of lights in the scene. I start of with my scene having 4 lights, and everything works fine. When I press the spacebar I create light data IE position, radius and color. I then delete the current light shader and regenerate the shader source code based on the new number of lghts. I then compile and link the shaders. The program works up until I have 7 lights. Remember, I start out with 4 lights, so I can press the spacebar twice with my scene still looking good. But as soon as I press the sapcebar that lucky third time the shaders don't work. I get the following error from GLSL "Fragment shader(s) failed to link, vertex shader(s) linked." I also cout the shader source to the command prompt so Heres the generated shader source code

VERT SHADER
const int NUM_LIGHTS = 7;
uniform vec3 LightPosition[NUM_LIGHTS];
uniform mat4 CameraViewMatrix;
varying vec2 texCoord;
varying vec3 vertPos;
varying vec3 lightPos[NUM_LIGHTS];
void main(void)
{
texCoord = gl_MultiTexCoord0.xy;
lightPos[0] = (vec4(LightPosition[0],1.0f) * CameraViewMatrix).xyz;
lightPos[1] = (vec4(LightPosition[1],1.0f) * CameraViewMatrix).xyz;
lightPos[2] = (vec4(LightPosition[2],1.0f) * CameraViewMatrix).xyz;
lightPos[3] = (vec4(LightPosition[3],1.0f) * CameraViewMatrix).xyz;
lightPos[4] = (vec4(LightPosition[4],1.0f) * CameraViewMatrix).xyz;
lightPos[5] = (vec4(LightPosition[5],1.0f) * CameraViewMatrix).xyz;
lightPos[6] = (vec4(LightPosition[6],1.0f) * CameraViewMatrix).xyz;
gl_Position = ftransform();
vertPos = (gl_Vertex* gl_ModelViewMatrix).xyz;
}


FRAG SHADER

const int NUM_LIGHTS = 7;
uniform sampler2D diffuseTex;
uniform vec4 LightColor[NUM_LIGHTS];
uniform float LightRadius[NUM_LIGHTS];
varying vec2 texCoord;
varying vec3 vertPos;
varying vec3 lightPos[NUM_LIGHTS];
void main(void)
{
vec4 diffuseColor = texture2D(diffuseTex, texCoord);
vec4 colorAcum = vec4(0.0f, 0.0f, 0.0f, 1.0f);
float percentLit;
percentLit = 1.0f - (distance(lightPos[0], vertPos) / LightRadius[0]);
if ( percentLit < 0.0f )
percentLit = 0.0f;
colorAcum += (vec4(percentLit,percentLit,percentLit,1.0f) * LightColor[0]);
percentLit = 1.0f - (distance(lightPos[1], vertPos) / LightRadius[1]);
if ( percentLit < 0.0f )
percentLit = 0.0f;
colorAcum += (vec4(percentLit,percentLit,percentLit,1.0f) * LightColor[1]);
percentLit = 1.0f - (distance(lightPos[2], vertPos) / LightRadius[2]);
if ( percentLit < 0.0f )
percentLit = 0.0f;
colorAcum += (vec4(percentLit,percentLit,percentLit,1.0f) * LightColor[2]);
percentLit = 1.0f - (distance(lightPos[3], vertPos) / LightRadius[3]);
if ( percentLit < 0.0f )
percentLit = 0.0f;
colorAcum += (vec4(percentLit,percentLit,percentLit,1.0f) * LightColor[3]);
percentLit = 1.0f - (distance(lightPos[4], vertPos) / LightRadius[4]);
if ( percentLit < 0.0f )
percentLit = 0.0f;
colorAcum += (vec4(percentLit,percentLit,percentLit,1.0f) * LightColor[4]);
percentLit = 1.0f - (distance(lightPos[5], vertPos) / LightRadius[5]);
if ( percentLit < 0.0f )
percentLit = 0.0f;
colorAcum += (vec4(percentLit,percentLit,percentLit,1.0f) * LightColor[5]);
percentLit = 1.0f - (distance(lightPos[6], vertPos) / LightRadius[6]);
if ( percentLit < 0.0f )
percentLit = 0.0f;
colorAcum += (vec4(percentLit,percentLit,percentLit,1.0f) * LightColor[6]);
if ( colorAcum.r < 0.3f && colorAcum.g < 0.3f && colorAcum.b < 0.3f )
 colorAcum = vec4(0.3f, 0.3f, 0.3f, 1.0f);

gl_FragColor = diffuseColor * colorAcum;
}








It looks good to me. The vertex shader does link and yet my frag shader doesn't. I don't see why. Hopefully someone will be able to help me EDIT: The program crashes at 9 lights [Edited by - zaneski13 on February 20, 2010 1:30:27 AM]

Share this post


Link to post
Share on other sites
I just learned that theres a limit of how much information the vertex shader can send to the fragment shader and where it tops out is when I reach 8 lights. So how might I implement a way to render more than 7 lights in a scene. Am I going to have to some complex multipass algorithm? Like draw the scene with 7 lights, then redraw the scene with a new set of 7 lights and keep doing that until there are no more lights to draw. Then after that how should I blend the scenes together?

Share this post


Link to post
Share on other sites
Concerning your OpenGL problem, you should use glGetIntegerv with GL_MAX_VARYING_FLOATS to find out how many varying variables you are able to use. I think 30-60 is a common number for that field on a little older hardware, so its not surprising you're maxing it out trying to use 9 vec4's.

Regarding your design problem, have you considered if you really need that many lights acting on every vertex? I have no idea what kind of effect you are trying to create so correct me if I'm wrong, but I can't imagine you need so many active lights at one time. You can still keep all the lights in your scene, but just pick the closest three to an object for computation or something like that.

If for whatever reason you must calculate every light on every object in the scene, you could certainly try some kind of multipass algorithm. I would imagine you just render the scene to a texture with one handful of lights, and render it again with another handful, and accumulate the texture results together. Not a lighting expert though so that may not be entirely correct.

Share this post


Link to post
Share on other sites
When I queried GL_MAX_VARYING_FLOATS I got 44. In my shader, when I have 8 lights, I only have 29 varying floats in my frag shader. I'm getting 29 from...

varying vec3 lightPos[8] = 24 floats
varying vec3 vertPos = 3 floats
varying vec2 texCoord = 2 floats
_________
29 floats

And 29 is less than 44.

Do I also have to add up the varying floats in the Vertex Shader, even though it'l have the same information? Because if so it would look like

FRAG Shader = 29 floats

Vert shader
______________

varying vec3 lightPos[8] = 24 floats
varying vec3 vertPos = 3 floats
varying vec2 texCoord = 2 floats
___________
29 floats

FRAG SHADER = 29 and VERT SHADER = 29
29 + 29 = 58 which is greater than 44 so the shader would fail but When I use 7 lights it should in theory fail as well because

FRAG SHADER

varying vec3 lightPos[7] = 21 floats
varying vec3 vertPos = 3 floats
varying vec2 texCoord = 2 floats
___________
26 floats

VERT SHADER

varying vec3 lightPos[7] = 21 floats
varying vec3 vertPos = 3 floats
varying vec2 texCoord = 2 floats
___________
26 floats

and everyone knows that 26 + 26 = 52 which is still greater than 44, so 7 lights shouldn't work, and yet it does. Am I doing the calculation wrong?

Share this post


Link to post
Share on other sites
Out of curiousity I was trying to find more information about this, and it seems like you might not be the first person to have a similar issue, although I've yet to find any good explanations.

Just a couple random facts I've gleaned from other forum posts, though I don't have any good references to back these up.

At one time I've heard that some glsl compilers will treat all varyings as vec4's internally. So even if you are not using all 4 fields of the vec4 the leftovers might be wasted. Try getting your program to run with as many vec3's as you can, and see if you change them to vec4's it still works. This could be an internal hardware limitation to make it faster to swizzle the varyings.

I'm aware that this still puts you at only 40 floats, although other varyings might be used in the compiler in some way (maybe a fixed function varying like gl_Normal is still used or something? although I have no idea). I've also heard that nvidia might use 1-2 varyings for clip planes or something, although I can't imagine why they would report 44 floats unless you could use them.

Hopefully you can get someone who knows more to comment, unfortunately the whole GLSL compiling process is not perfect yet I think and can cause some strange problems.

My suggestion for now is to just use less floats :)

Share this post


Link to post
Share on other sites
I wonder if the 16 floats from the mat4 in the vertex shader is causing this issue. 29 floats + 16 floats from matrix = 45 floats which is greater than 44. I'll do some tests.


EDIT:

Well, when I take out the matrices it still only works up until 8 lights.

Share this post


Link to post
Share on other sites
______________________________________________________________________________________


Here's My New Problem


______________________________________________________________________________________

Hey guys I have a new problem with glsl. I made a new program and I made it so the shader only supports 3 lights. However now, when I query errors from glsl I got something a little unexpected. First, in my console said "Fragment shader(s) linked, vertex shader(s) linked." Which made me happy but the next thing it said was a bit peculiar. "ERROR: Unknown char α" Its on a whole new line so I'm not sure if glsl is writing it but it sure isn't me. I looked though all my uniforms in my shader and made sure everything matched up in my app so that the calls to glUniform..() made it to the shader. I also printed to the console where key stuff happens and the moment the program crashes is when I draw the first vertex. This is most likely because the shader isn't set up correctly, and yet it is...

Share this post


Link to post
Share on other sites
Ok, so I don't get that error when I hard code in the shader source into my program. So it doesn't work when I read the shader source from a file. That's strange because I've used the same loadShader() function for other shaders and they've worked for me in the past. Well, I'll just have to hard code in the shader sources that don't work.

Share this post


Link to post
Share on other sites
Are you sure you don't just have a simple bug in your shader source loader? Just because you didn't have a problem before doesn't mean that the code is perfect.

It might be easy to see what's wrong with debugger, or you can post the load function for someone to take a look at.

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