Sign in to follow this  
blueshogun96

GLSL Procedural Animation bug

Recommended Posts

I've been working on this procedural animation shader for quite some time now, and I've finally almost got it working.  In fact, it works, but only for the first second, before the  geometry rapidly deforms and expands into oblivion.  It's easy to talk about it, but the source should hopefully explain alot more.

 

I made a post similar to this one last year, but since then I've made much better progress.  This GLSL vertex shader is really a port from an NV_vertex_program from 2001.  Translating to ARB_vertex_program was hassle free at least, so that runs on everything almost.

 

Here's what I'm going to do, first show you the desired result, and the actual result.  Then share the source code, and point out where the problem starts.

 

Good: (ARB_vertex_program port)

[attachment=26836:Screen Shot 2015-04-14 at 5.38.54 PM.png]

 

Bad: (GLSL port)

[attachment=26837:Screen Shot 2015-04-14 at 5.37.42 PM.png]

 

So, what's happening is that the geometry begins to rapidly deform and disappear with the GLSL version.  These were taken at the exact same animation intervals, and I can't figure out what is going on.  I know that this is fixable, because someone has done it once before.  In fact, I have the feeling that I had this right at one point, but changed something unknowingly and broke it.

 

This is the shader, with the original assembly version at the bottom:

/* Vertex attributes */
attribute vec4 v_pos;
attribute vec4 v_normal;
varying float v_tex;

/* Texture sampler */
uniform sampler1D texture;

/* General purpose vectors */
vec4 R0, R1, R2, R3, R4, R5, R6;

/* Constants */
uniform vec4 c8;
uniform vec4 c9;
uniform vec4 c10;
uniform vec4 c11;
uniform vec4 c12;
uniform vec4 c13;
uniform vec4 c14;
uniform vec4 c15;
uniform vec4 c16;
uniform vec4 c17;

/* Matrices */
mat4 mvp = gl_ModelViewProjectionMatrix;
mat3 itmm = gl_NormalMatrix;


void main()
{
    R0 = R1 = R2 = R3 = R4 = R5 = R6 = vec4( 0, 0, 0, 0 );
    R0.x = (v_pos.y * c16.x) + c16.z;

    R0.x *= c11.w;
    R0.y = exp( R0.x );
    R2.x = ( R0.y < c11.x ) ? 1.0 : 0.0;
    R2.y = ( R0.y >= c11.y ) ? 1.0 : 0.0;
    R2.z = ( R0.y >= c11.z ) ? 1.0 : 0.0;
    R2.y = dot( R2.xyz, c14.zwz );
    R5.xyz = -R0.y + c10.xyz;
    R5 = R5 * R5;
    R0 = ( c12.xyxy * R5 ) + c12.zwzw;
    R0 = ( R0 * R5 ) + c13.xyxy;
    R0 = ( R0 * R5 ) + c13.zwzw;
    R0 = ( R0 * R5 ) + c14.xyxy;
    R0 = ( R0 * R5 ) + c14.zwzw;
    R1.x = dot( R0.xyz, -R2.xyz );
    //R1.x = sin(R0.x);
    
    R2.x = ( R1.x * c10.w ) + c10.z;
    
    R2.yw = c16.yw;
    R3 = v_pos * R2.xyxw;
    R4.xyz = v_normal.xyz * R2.yxy;
    
    gl_Position = mvp * R3;
    
    R5.xyz = itmm * R4.xyz;
    R5.xyz = normalize(R5.xyz);
    R6.xyz = normalize( c8.xyz + v_pos.xyz );
    R6 = R6 * c10.y;
    
    v_tex = dot( R5.xyz, R6.xyz );
    
    gl_FrontColor = gl_Color;
}

/* Original vertex program:

# R0 = (y coordinate of vertex * k) + (w * t)
MAD R0.x, v[OPOS].y, c[16].x, c[16].z;

# R1 = cos(R0), R0 = any floating point number
MUL R0.x, c[11].w, R0.x; 
EXP R0.y, R0.x; 
SLT R2.x, R0.y, c[11]; 
SGE R2.yz, R0.y, c[11]; 
DP3 R2.y, R2, c[14].zwzw;   
ADD R5.xyz, -R0.y, c[10]; 
MUL R5, R5, R5;
MAD R0, c[12].xyxy, R5, c[12].zwzw; 
MAD R0, R0, R5, c[13].xyxy;      
MAD R0, R0, R5, c[13].zwzw;      
MAD R0, R0, R5, c[14].xyxy;      
MAD R0, R0, R5, c[14].zwzw;      
DP3 R1.x, R0, -R2; 

# R2 = R1 * c[10] + 1.0
MAD R2.x, R1.x, c[10].w, c[10].z;

# R3 = perturbed vertex
# R4 = perturbed normal
MOV R2.yw, c[16];
MUL R3, v[OPOS], R2.xyxw;
MUL R4, v[NRML], R2.yxyw;

# Transform vertices into clip space via modelview-projection matrix
DP4 o[HPOS].x, R3, c[0];
DP4 o[HPOS].y, R3, c[1];
DP4 o[HPOS].z, R3, c[2];
DP4 o[HPOS].w, R3, c[3];

# Transform normals via inverse transpose modelview matrix & normalize
# R5 = transformed normal
DP3 R5.x, R4, c[4];
DP3 R5.y, R4, c[5];
DP3 R5.z, R4, c[6];
DP3 R5.w, R5, R5;
RSQ R5.w, R5.w;
MUL R5, R5, R5.w;

# Get unit length eye vector to vertex....this is how we texture map
# R6 = vector
ADD R6, c[8], v[OPOS];
DP3 R6.w, R6, R6;
RSQ R6.w, R6.w;
MUL R6, R6, R6.w;

# Multiply by 0.5 for texture wrapping
MUL R6, R6, c[10].y;
	    
# Texture coord is dot product of normal and vector from eye to vertex
DP3 o[TEX0].x, R5, R6;

# Pass color through
MOV o[COL0], v[COL0];
*/

One important observation is this line:

R0.x = (v_pos.y * c16.x) + c16.z;

 

If I were to comment out the last bit of this line to look like this:

R0.x = (v_pos.y * c16.x); // + c16.z;

 

Then the deformation above does not happen, but the tentacles stay straight.  One more thing I want to show you:

// Load the view position into c[8]
	glUniform4f( uniform_constants[8], 0.0f, 0.0f, 100.0f, 1.0f);
    
	// Load cosine series constants into c[9]
 	glUniform4f( uniform_constants[9], 1.0f, -1.0f/2.0f, 1.0f/24.0f, -1.0f/720.0f);
    
	// Constants for cosine
	glUniform4f( uniform_constants[10], 0.0f, 0.5f, 1.0f, 0.2f);
	glUniform4f( uniform_constants[11], 0.25f, -9.0f, 0.75f, 1.0f / (2.0f * M_PI) );
	glUniform4f( uniform_constants[12], 24.9808039603f, -24.9808039603f, -60.1458091736f, 60.1458091736f );
	glUniform4f( uniform_constants[13], 85.4537887573f, -85.4537887573f, -64.9393539429f, 64.9393539429f );
	glUniform4f( uniform_constants[14], 19.7392082214f, -19.7392082214f, - 1.0f,	1.0f );
    
	// Light position
	glUniform4f( uniform_constants[15], 0.0f, 0.7f, 0.7f, 1.0f );
	glUniform4f( uniform_constants[17], 0.3f, 0.3f, 0.3f, 1.0f );

...

void Jellyfish::render( )
{
  static float lastTime = 0.0f;
  float dt;
  float time = 0.0f;
  static float ourTime = 0.0f;
  float k = 0.25f;    // inverse wavelength of ripple
  float w = 3.0f;     // inverse period of ripple

  // What follows is the CPU's only per-frame computations
  // for animating the jellyfish
  time = queryElapsedTime( );

  dt = time - lastTime;
  lastTime = time;
  float hfactor = .805f - 0.195f * sinf(w * ourTime);
  if ( cosf(w * ourTime) < 0.0f )
  {
    dt *= 2.0f;
  }
  ourTime += dt;

  // Now send some parameters and draw the jellyfish
#if USE_ARB_VERTEXPROGRAM
  glProgramLocalParameter4fARB(GL_VERTEX_PROGRAM_ARB, 16, k, hfactor, w * ourTime, 1.0f);
#else
    glUseProgram(vertexProgramsNV[0]);
    glUniform4f(uniform_constants[16], k, hfactor, w * ourTime, 1.0f);
#endif
    
  glCallList(jellyfishList);
}

If you comment out the variable ourTime, or replace it with a constant value such as 1.x, you can step through the stages.  Once ourTime goes above 1.5, then it begins to distort.  I've been trying to figure out how this thing works for ages, no success sad.png

 

When I get home, I'll upload the source code so you can see everything that's going on.  What I shared here is the most relevant parts regarding the distortion.  Any ideas?  Thanks.

 

Shogun

Share this post


Link to post
Share on other sites

Okay, so what I've decided to do instead of trying to figure this shader out, I'll leave the constant that's causing the trouble commented out, and add my own sine deformation code.  But my question is... how do you do that??

 

To be more specific, this is what I'm asking.  How do I essentially send ripples downward on a 3D object using sine waves?  I did a bit of googling, but I haven't quite found the results I need yet.

 

I tried doing something like this to modify the final vertex:

 

R3.xz *= sin(c16.z*0.5);

 

This doesn't work; it just shrinks the geometry and turns it inside out, then back.  Any ideas?  Thanks.

 

Shogun.

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