Forums - Skeletal animation on GPU

1 post / 0 new
Skeletal animation on GPU
Join Date: 7 Mar 11
Posts: 2
Posted: Mon, 2011-03-07 19:17

I'm implementing skeletal animation in my android phone, and here is how I do it:

1. Calcualte all bone transformation matrices on the CPU side

2. Create a float texture to store these matrices (so this is done at the beginning of each frame)

3. In vertex shader, fetch matrix from this texture and apply to vertex position

This approach works fine in my another phone using a POWERVR GPU. But when I run it on a Qualcomm snapdragon, there are many triangles disappeared (randomly), so it seems the model is flickering.

I also tried to reduce the scene complexity by rendering only one animated model, and the flicker become less but still exists. Does anyone know what I may be doing wrong?

You can see the snapshots here (the first two pictures is correct, and the later two are wrong). The APK file of my grogram can be downloaded here.

Here is the vertex shader I used:


struct light {
lowp vec4 position; // light position for a point/spot light or
// normalized dir. for a directional light
lowp vec4 ambient_color;
lowp vec4 diffuse_color;
lowp vec4 specular_color;
lowp vec3 spot_direction;
lowp vec3 attenuation_factors;
lowp float spot_exponent;
lowp float spot_cutoff_angle;
bool compute_distance_attenuation;

struct material {
lowp vec4 ambient_color;
lowp vec4 diffuse_color;
lowp vec4 specular_color;
lowp vec4 emissive_color;
lowp float specular_exponent;

// uniforms used by the vertex shader
uniform highp mat4 u_mvMatrix;
uniform highp mat4 u_projMatrix;
uniform bool u_enable_lighting;
uniform light u_light_state;
uniform material u_material_state;
uniform bool u_enable_texture;
uniform highp sampler2D s_jointTex; // use highp for float texture

// attributes input to the vertex shader
attribute highp vec3 a_position;
attribute lowp vec3 a_normal;
attribute mediump vec2 a_texCoord;
attribute highp float a_jointID;

// varying variables – input to the fragment shader
varying lowp vec4 v_front_color;
varying mediump vec2 v_texCoord;

vec2 mapTo2D(float idx)
vec2 st = vec2(idx + 0.5, 0.5);
return st / 256.0;

void main()
mat4 joint = mat4(1.0);

if(a_jointID >= 0.0)
float idx = a_jointID * 4.0;
joint = mat4( texture2D(s_jointTex, mapTo2D(idx)),
texture2D(s_jointTex, mapTo2D(idx+1.0)),
texture2D(s_jointTex, mapTo2D(idx+2.0)),
texture2D(s_jointTex, mapTo2D(idx+3.0)) );
gl_Position = (u_projMatrix * u_mvMatrix) * joint * vec4(a_position, 1.0); // hint compiler to extract uniform calculation
gl_Position = (u_projMatrix * u_mvMatrix) * vec4(a_position, 1.0); // hint compiler to extract uniform calculation

lowp vec4 computed_color = vec4(0.0);
vec3 normal = normalize( vec3(u_mvMatrix * joint * vec4(a_normal, 0.0) ) );
vec3 lightDir = normalize( vec3(u_mvMatrix * u_light_state.position) );
float NdotL = max(dot(normal, lightDir), 0.0);

computed_color += u_light_state.ambient_color * u_material_state.ambient_color + NdotL * u_light_state.diffuse_color * u_material_state.diffuse_color;

if(NdotL > 0.0) {
vec3 half_vec = normalize(lightDir + vec3(0.0, 0.0, 1.0));
float NdotHV = dot(normal, half_vec);
if(NdotHV > 0.0)
computed_color += u_light_state.specular_color * u_material_state.specular_color * pow(NdotHV, u_material_state.specular_exponent);
v_front_color = computed_color;
v_front_color = vec4(1.0, 1.0, 1.0, 1.0);

v_texCoord = a_texCoord;

  • Up0
  • Down0

Opinions expressed in the content posted here are the personal opinions of the original authors, and do not necessarily reflect those of Qualcomm Incorporated or its subsidiaries (“Qualcomm”). The content is provided for informational purposes only and is not meant to be an endorsement or representation by Qualcomm or any other party. This site may also provide links or references to non-Qualcomm sites and resources. Qualcomm makes no representations, warranties, or other commitments whatsoever about any non-Qualcomm sites or third-party resources that may be referenced, accessible from, or linked to this site.