PDA

View Full Version : ATI glsl: w component of gl_Position



Jan
11-26-2005, 06:04 AM
Hi there

Strange problem:


vec4 temp = (gl_ModelViewProjectionMatrix * Position);
gl_Position = temp;This code compiles, links AND works fine.
By putting temp.w into color i can confirm, that its value is 1;


vec4 temp = (gl_ModelViewProjectionMatrix * Position);
temp.w = 1.0;
gl_Position = temp;This code compiles and links fine, but DOESN'T SHOW ANYTHING! My mesh simply disappears!

It is not just this situation, this is just the simplest case to show the problem. In fact i can never see my mesh, as long as i touch the w component of the vector that gets copied into gl_Position.

Ie:
vec3 temp = (gl_ModelViewProjectionMatrix * Position).xyz;
gl_Position.xyz = temp.xyz;
gl_Position.w = 1.0;

This does not show my mesh neither.

I should add, that my vertex-shader runs in software, because i use a loop, which is not supported on my Radeon 9700.
So it might be the fault of the software-vertexshader.

Can anyone confirm this? Is there a workaround?

The problem is, i want to use quaternions in my shader, and my quaternion does not generate a w-component of my resulting position, so i need to manually set it to 1.0, which then results in my mesh disappearing.

However, the code i use to test it, still uses matrices, which do create a w-component.

Jan.

Jan
11-26-2005, 06:36 AM
After some more playing around i found out the following:

Touching the w-component of the vector that gets copied into gl_Position BEFORE multiplying it with gl_ModelViewProjectionMatrix is save.
Touching it AFTER multiplying with gl_ModelViewProjectionMatrix, even when you only set it to 1.0, results in the mesh disappearing.

Not copying the w-component into gl_Position at all, and instead either setting it manually (gl_Position.w = 1.0) or not setting it at all, also results in the mesh not showing up.

That's still all in software processing.

Something else:

Also, using a fixed loop-count (2.0) does not result in the loop being unrolled, which means the shader is run in software.
Unrolling the loop manually (simply writing the loop-body several times), results in the shader running in hardware (and therefore several times faster).

I think this is a big defect. I wonder why ATI still did not implement this.

Jan.

Zulfiqar Malik
11-26-2005, 07:19 AM
You can only be sure that the value of w is 1.0 after the perspective divide! Your color can turn up 1.0 even if w is above 1.0.

Humus
11-26-2005, 02:15 PM
Originally posted by Jan:
vec3 temp = (gl_ModelViewProjectionMatrix * Position).xyz;
gl_Position.xyz = temp.xyz;
gl_Position.w = 1.0;

This does not show my mesh neither.I'm not surprised it doesn't work, it looks quite broken. The position gets divided by w, but you set it to 1.0 instead of its proper value, so the result can be anything, most likely somewhere outside the view frustum.


Originally posted by Jan:
Also, using a fixed loop-count (2.0) does not result in the loop being unrolled, which means the shader is run in software.
Unrolling the loop manually (simply writing the loop-body several times), results in the shader running in hardware (and therefore several times faster).Do you think you could post a shader showing this problem? Unrolling loops is most certainly supported.

V-man
11-26-2005, 06:11 PM
The problem is, i want to use quaternions in my shader, and my quaternion does not generate a w-component of my resulting position, so i need to manually set it to 1.0, which then results in my mesh disappearing. What?

I don't know what you are doing but perhaps you should

Position.w = 1.0;
output = ModelviewProjection * Position;

output.w is not necessarily 1.0

Zulfiqar Malik
11-26-2005, 07:57 PM
Originally posted by Jan

The problem is, i want to use quaternions in my shader, and my quaternion does not generate a w-component of my resulting position, so i need to manually set it to 1.0, which then results in my mesh disappearing.

However, the code i use to test it, still uses matrices, which do create a w-component.

I don't get it, why are you performing transformations in post-projection space? (or am i totally wrong?). You can easily apply your quaternion on gl_Vertex (its read only) and then use the resulting vector.
A note on quaternions: Quaternions which indicate rotation, must be, by definition, normalized! I don't understand how a normalized quaternion (which strictly represents a ROTATION ONLY) can mess around with your w-coordinate. Clearly, a 4x4 matrix conversion of a normalized quaternion does not effect the w-coordinate of input vector. Read the Matrix and Quaternion FAQ (http://skal.planet-d.net/demo/matrixfaq.htm) if you have any problems.

Jan
11-27-2005, 02:28 AM
Ok, so with the w-component it seems i have misunderstood something. I always thought, that w will always be 1, so i thought i needed to set it to 1.
About the quaternions: When rotating with quaternions there is no w-component involved, that is why i manually set it afterwards. Whereas with matrices i can rotate my whole 4-component vector, including w.

Anyway, thanks for clearing that up, so it was my fault.

However, loop-unrolling seems not to be done. Here is my shader:


//uniform mat4 BoneMatrices[60];
uniform vec4 BoneRotations[100];
uniform vec3 BoneTranslations[100];

varying vec4 Color;

vec4 mult (vec4 q1, vec4 q2)
{
vec4 r;

r.w = q1.w*q2.w - dot (q1.xyz, q2.xyz);
r.xyz = q1.w * q2.xyz + q2.w * q1.xyz + cross (q1.xyz, q2.xyz);

return (r);
}

vec3 rotate (vec4 q, vec3 v)
{
vec4 r = mult (q, vec4 (v.x, v.y, v.z, 0.0));
r = mult (r, vec4 (-q.x, -q.y, -q.z, q.w));

return (r.xyz);
}

vec3 doit (vec4 q, vec3 t)
{
vec3 r = rotate (q, gl_Vertex.xyz);

return (r + t);
}

void main (void)
{
vec4 Position = vec4 (0.0, 0.0, 0.0, 1.0);

vec4 Weight = gl_MultiTexCoord1;
vec4 Index = gl_MultiTexCoord0;
vec4 Number = gl_MultiTexCoord2;

for (float i = 0.0; i < Number.x; i += 1.0)
{
int iIndex = int (Index.x);

// Position.xyz = (Position + Weight.x * (BoneMatrices[iIndex] * gl_Vertex)).xyz;
Position.xyz = (Position.xyz + Weight.x * doit (BoneRotations[iIndex], BoneTranslations[iIndex])).xyz;

Weight = Weight.yzwx;
Index = Index.yzwx;
}

gl_Position = (gl_ModelViewProjectionMatrix * Position);

Color = vec4 (1.0, 1.0, 0.0, 1.0);
}At the moment i only use 2 bones per vertex. So, when i use "2.0" instead of "Number.x" it could be unrolled, but doesn't. When linking it says "unsupported language element used". However, when i take the loop-body and write it down 2 times, it links fine, says it runs in hardware and actually does, because it is at least 10 times faster.

Also the optimizer (at least for the softwareshader) seems to be quite bad. When calling the "doit" function i now pass the parameters directly. Earlier i first copied them into a temporary variable to make it more readable which could have been optimized away, but seems as if it wasn't done, because by eliminating the temporary variables myself, the shader speed up by a noticable amount (maybe 2 times).

Thanks for your help,
Jan.

PS: I use Catalyst 5.11.

Zulfiqar Malik
11-27-2005, 03:55 AM
Originally posted by Jan

About the quaternions: When rotating with quaternions there is no w-component involved, that is why i manually set it afterwards. Whereas with matrices i can rotate my whole 4-component vector, including w.

That's what i was trying to point out. A normalized quaternion always generates a matrix in which last row and column are zero (except the 1 at the [4][4] diagonal position) so it won't affect the w when multiplied with a 4-D vector. So you can multiply your incoming vertex with such a matrix and be sure that the w-component remains unchanged.

Humus
11-29-2005, 05:37 AM
Originally posted by Jan:
So, when i use "2.0" instead of "Number.x" it could be unrolled, but doesn't.Well, it should. Still, why are you using float instead of int in the loop? With an int it works fine.

Jan
11-29-2005, 03:23 PM
Yeah, just found that out too. I copied the code from some tutorial-program, so i thought it should work fine.

Anyway, thanks.
Jan.