I have 8 light source positions in the vertex shader.
and I have to do “into tangent space”-transformation
on these vectors.
My first idea was to calculate the 8 light source tangent
space direction vectors in the vertex shader and then pass
them to the fragment shader with “out & in” (varyings).
But together with other varyings this will exceed
GL_MAX_VARYING_FLOATS on many cards.
Since I don’t need interpolation on the transformed positions
I wonder if there is an alternative to the limited varyings.
Something that comes without interpolation but more variable
capacity for passing values from vertex to fragment shader?
You can specify the flat variable qualifier. Then that variable will not be varying and shouldn’t count against your varying limit (but I haven’t tested that).
It might look something like this:
For vertex shader:
flat out vec3 Light_pos[8];
For fragment shader:
flat in vec3 Light_pos[8];
P.S. I composed this as Alfonse was posting his reply, and I didn’t see his post before posting mine. He may be right, I don’t know. According to the OpenGL 4.0 core spec (see section 2.11.7):
“The number of components (individual scalar numeric values) of varying and special variables that can be written by the vertex shader, whether or not a tessellation control, tessellation evaluation, or geometry shader is active, is given by the value of the implementation-dependent constant GL_MAX_VERTEX_OUTPUT_COMPONENTS.”
…
“Additionally, when linking a program containing only a vertex and fragment shader, there is a limit on the total number of components used as vertex shader outputs or fragment shader inputs. This limit is given by the value of the implementation-dependent constant GL_MAX_VARYING_COMPONENTS. Each varying or special variable component used as either a vertex shader output or fragment shader input count against this limit, except for the components of gl_Position.”
I think the spec is ambiguous in this regard. The first sentence of the last paragraph quoted doesn’t qualify variables are being varying or special, but the last sentence does. So which is it, really?
Ok the only solution that comes to my mind is that I
pass the Normal, Tangent and Binormal (TBN Matrix)
as normal varying (without flat) to the fragment
shader and then calculate the tangent space light
positions in the fragment shader.
Maybe not beautiful but this way I bypass the varying
limitation =/
That works, but have you considered, instead of transforming the light positions into tangent space, transforming the tangent space normal into world space or eye space(whatever space the light positions are stored in) and doing the light there.
I must agree with the previous poster and suggest computing the TBN matrix for each vertex in some space (probably eye space) and passing this matrix as a vertex attribute. Is there a particular reason why you want the TBN to be different for each light? It would seem more natural and intuitive that the TBN depends on the surface geometry rather than the light source. Perhaps doing it with vertex attributes is even more consistent than recomputing per light source. In any event, there should be more than enough vertex attributes for you to try this approach if it suits your needs.
Hi! I already pass the tangent of the TBN Matrix as vertex
attribute and then calculate the Binormal with cross() from
the tangent and the vertex normal.
Actually, I believe it will still eat an interpolator, regardless what type of interpolation you request: smooth (the default), flat, or noperspective. Interpolator being the register space the value is passed in and the potential for the value to be interpolated.
Are you quite sure about that limit? Even a vs_1_1 device has 16 input registers, each of which holds 4 floats. You can pack your 8 positions into 6 of these and just go to work. Things might not be as bad as they seem, and you might be doing an awful lot of refactoring for no reason.