PDA

View Full Version : is something wrong with this Cg shader?

therealremi
01-28-2007, 06:43 AM
I know this is not OpenGL but I don't know any other 3D programming forum with so many experts ready to help. And I am desperate cause I see no further possibility to debug my application and shader.

I am trying to implement animation using vertex shader. And it ALMOST works. I mean I want my object to move smoothly with time. And I basically does this but there is some small artifact that I cannot track down. Here are the details:
Every position is described by a 3x4 matrix - every vertex of an object must be multiplied by this matrix for this object to be in this position.
I have 3 such matrices - one at each point of time.

matrixA = {1,0,0,0, 0,1,0,0, 0,0,1,0};
at point in time 0 ms

matrixB = {1,0,0,0, 0,1,0,1, 0,0,1,0};
at point in time 1000 ms

matrixC = {1,0,0,0, 0,1,0,2, 0,0,1,0};
at point in time 2000 ms

My app keeps track of current time and updates shader parameters accordingly. These 3 (uniform in Cg) parameters are: 2 matrices and a weight factor. The weight factor is used to linearly interpolate between two matrices, so it changes it's value from 0.0 to 1.0 during the flow of animation from 0 ms to 1000 ms, and again from 0.0 to 1.0 during animation from 1000 ms to 2000 ms. The 2 matrices send to a vertex shader are updated when 1000 ms have passed - so it is now blending between matrixB and matrixC.
Such interpolation between matrices in a vertex shader guarantees that the motion is smooth. And it is smooth. Except for one small problem: at the point in time when matrices are updated (1000 ms) the animated object for a fraction of second takes the position of the next matrix - that is, at time 1000 ms the object is for a fraction of second at position implied by matrixC, then instantly comes back to a position close to matrixB (which is the right position at this point in time) and continues to move smoothly towards position implied by matrixC.

struct vertex_input
{
float4 position : POSITION;
};

struct vertex_output
{
float4 position : POSITION;
};

vertex_output vertex_program(vertex_input IN, uniform float4x4 model_view_proj, uniform float3x4 previous_matrix, uniform float3x4 next_matrix, uniform float weight)
{
vertex_output OUT;
float3 previous_position = mul( previous_matrix, IN.position );
float3 next_position = mul( next_matrix, IN.position );
float3 position = lerp(previous_position, next_position, weight);//here is the interpolation
OUT.position = mul(model_view_proj, float4(position, 1.0f));
return OUT;
} I thought I pass in parameters with wrong values so I printed them out just before sending them to the shader. Here is a fragment of the output at this problematic moment around 1000 ms.

previous_matrix : 1000 0100 0010
next_matrix : 1000 0101 0010
weight : 0.982

previous_matrix : 1000 0100 0010
next_matrix : 1000 0101 0010
weight : 0.999

previous_matrix : 1000 0101 0010
next_matrix : 1000 0102 0010
weight : 0.016

previous_matrix : 1000 0101 0010
next_matrix : 1000 0102 0010
weight : 0.034

You see it's correct!!
Please I want to hear that I did some very stupid mistake!

Komat
01-28-2007, 07:22 AM
Did the jump happened when this printout was generated or did the slowdown introduced by printing prevented it from happening (e.g. by skipping some problematic time)?

therealremi
01-28-2007, 07:50 AM
No, the jump happens every time at 1000 ms whether I print something or not (actually if I have more positions it happens every time when the matrices are updated). It looks like somehow (??) the weight at this particular time was not yet updated whereas the matrices were already updated - that would explain this one-frame jump.

therealremi
01-28-2007, 08:03 PM
To make things even more interesting: when I render only the moving object and disable vertical synchronization (and get FPS around 600) the moving object SOMETIMES renders correctly - without one-frame jump to the next position. (I thought this can be due to the high FPS, which prevented me from seeing this jump, but as I said this SOMETIMES works, and the volatility in FPS is very low).
I thought about some shader debugger but it seems that there is none OpenGL-compliant that works on ATI cards.

therealremi
01-28-2007, 11:03 PM
I finally hacked it: setting weight and matrices AFTER the drawing seems to get rid of that jump. But this is a hack and I don't have a clue as to why this is necessary.

Komat
01-28-2007, 11:24 PM
Originally posted by therealremi:
I thought about some shader debugger but it seems that there is none OpenGL-compliant that works on ATI cards. You can use the GLintercept to record low level calls made by the CG runtime.

therealremi
01-29-2007, 12:26 AM
Actually I doubt I would understand these low level calls;) I remember using GLintercept and rendering with some simple shader and for each frame it produced awful amount of some commands I didn't understand.