Out/in mat4 array does not work

Hi,
I have a shadow-mapping shader in my deferred renderer. Because its a deferred renderer, I have to reconstruct the pixels position in the fragment shader, multiply it with a shadow-space matrix and sample the depth.
I have the following vertex shader:

#version 150

uniform mat4 im_ModelViewMatrix;
uniform mat4 im_ProjectionMatrix;
uniform mat3 im_NormalMatrix;
uniform mat4 im_ShadowMatrix[3];
uniform mat4 im_ViewSpaceMat;

in vec3 iv_Vertex;

out flat mat4 mShadowSpaceMatrix[3];

void main( void )
{
	gl_Position = im_ProjectionMatrix * im_ModelViewMatrix * vec4(iv_Vertex, 1.0);
	
	mat4 mViewSpaceInv = inverse(im_ViewSpaceMat);
	mShadowSpaceMatrix[0] = im_ShadowMatrix[0] * mViewSpaceInv;
	mShadowSpaceMatrix[1] = im_ShadowMatrix[1] * mViewSpaceInv;
	mShadowSpaceMatrix[2] = im_ShadowMatrix[2] * mViewSpaceInv;
}

And I sample the matrices in the Fragment shader like this:


in flat mat4 mShadowSpaceMatrix[3];

...

float ShadowLookup( vec3 fragpos, float depth )
{
	float index;
	vec4 coords;
	if( depth < 150.0 )
	{
		index = 0.0;
		coords = mShadowSpaceMatrix[0] * vec4( fragpos, 1.0 );
	}
	else if( depth < 400.0 )
	{
		index = 1.0;
		coords = mShadowSpaceMatrix[1] * vec4( fragpos, 1.0 );
	}
	else if( depth < 2000.0 )
	{
		index = 2.0;
		coords = mShadowSpaceMatrix[2] * vec4( fragpos, 1.0 );
	}
	else
	{
		return 1.0;
	}

	coords.w = coords.z;
	coords.z = index;
	
	return ShadowCoordLookup( coords );
}

Actually this gives me wrong results, as my whole screen is black now.
However, if I change the vertex shader to this:

#version 150

uniform mat4 im_ModelViewMatrix;
uniform mat4 im_ProjectionMatrix;
uniform mat3 im_NormalMatrix;
uniform mat4 im_ShadowMatrix[3];
uniform mat4 im_ViewSpaceMat;

in vec3 iv_Vertex;

out flat mat4 mShadowSpaceMatrix0;
out flat mat4 mShadowSpaceMatrix1; //CHANGE HERE
out flat mat4 mShadowSpaceMatrix2;

void main( void )
{
	gl_Position = im_ProjectionMatrix * im_ModelViewMatrix * vec4(iv_Vertex, 1.0);
	
	mat4 mViewSpaceInv = inverse(im_ViewSpaceMat);
	mShadowSpaceMatrix0 = im_ShadowMatrix[0] * mViewSpaceInv;
	mShadowSpaceMatrix1 = im_ShadowMatrix[1] * mViewSpaceInv;
	mShadowSpaceMatrix2 = im_ShadowMatrix[2] * mViewSpaceInv;
}

And my Fragment Shader to this:


in flat mat4 mShadowSpaceMatrix0;
in flat mat4 mShadowSpaceMatrix1; //CHANGE HERE
in flat mat4 mShadowSpaceMatrix2;

...

float ShadowLookup( vec3 fragpos, float depth )
{
	float index;
	vec4 coords;
	if( depth < 150.0 )
	{
		index = 0.0;
		coords = mShadowSpaceMatrix0 * vec4( fragpos, 1.0 );
	}
	else if( depth < 400.0 )
	{
		index = 1.0;
		coords = mShadowSpaceMatrix1 * vec4( fragpos, 1.0 );
	}
	else if( depth < 2000.0 )
	{
		index = 2.0;
		coords = mShadowSpaceMatrix2 * vec4( fragpos, 1.0 );
	}
	else
	{
		return 1.0;
	}

	coords.w = coords.z;
	coords.z = index;
	
	return ShadowCoordLookup( coords );
}

Then it works. Note that I just changed “in flat mat4 mShadowSpaceMatrix[3]” to “in flat mat4 mShadowSpaceMatrixN”.
Any Ideas?

I solved the issue by using a “uniform mat4 mShadowSpaceMatrix[3];” and calculating the viewspace-inverse on the CPU.
But I still would like to know why it was not working in the fist place.

But I still would like to know why it was not working in the fist place.

Well, considering that you were wasting precious vertex shader time computing something you could do statically, maybe the vertex shader gained sentience and was giving you a subtle hint that you shouldn’t be doing it that way :wink:

In any case, what the errors did you get? What hardware? What driver version?

Personally, I would avoid using more… esoteric GLSL features, like outputting matrices or arrays or arrays of matrices. The farther off the beaten path you go with OpenGL, the more likely you are to hit problems.

Well the reason why I outputted the matrices in the vertex shader was that I (at that time) hadnt a method for calculating a inverse of a 4x4 matrix. Because its a deferred renderer I just draw a fullscreen quad with that shader, so there are just 4 vertices involved and I bet that my graphics card is more than 4 times faster at calculating a matrix inverse than my CPU is. But now I got a nice SIMD Implementation by Intel which is pretty fast on the CPU as well so thats no big performance issue.
I tested the shader on my AMD HD 6950 with Catalyst 12.1 (OpenGL version 6.14.10.11399).
I cannot say what was wrong with my matrices but I know they where somehow screwed because all my geometry was shadowed which resulted in a very dark screen.

But now I got a nice SIMD Implementation by Intel which is pretty fast on the CPU as well so thats no big performance issue.

It doesn’t matter if it’s fast with SSE or slow with x87 double-precision opcodes; it’s 3 matrix inverses per-frame. My old Pentium 75 could handle that. It’s not going to even be a blip on your performance radar.

You are totally right, but I dont want to start a debate about the performance. I just want to know why outputting an array of matrices in the vertex shader does not work whereas outputting the matrices as individual variables does. As I said my actual issue is solved but I still am curious.

There is no “why”; it’s just a driver bug. It’s such unusued functionality that you’re probably the first person who’s ever tried it. AMD probably doesn’t even have test cases for it.

I wouldn’t hold my breath on it getting fixed; just try not to do unusual things like that next time.

It’s a compiler’s bug, we will have it fixed later, thanks.

When I was doing a quick shader on nVidia I used the “inverse” function and it didn’t work on it either. I didn’t follow it up as it was just a test and was planning to do the invert on the cpu long term.

This topic was automatically closed 183 days after the last reply. New replies are no longer allowed.