2
\$\begingroup\$

I have no problem doing the "vertex skinning" for three-dimensional animation. All goes well when using the emulator (and genymotion). However, when run on a real device (such as Samsung and Lenovo) looks messy.

Screenshoot (Emulator)

Emulator

Screenshoot (Real device)

Device

Passing skin transform matrix

int location = ...;
int arrayCount = ...;
float[] skinTransform = ...;
GL.UniformMatrix4(location, arrayCount, false, skinTransform);

GLSL vertex

uniform mat4 World;
uniform mat4 View;
uniform mat4 Projection;
uniform mat4 Bones[20];

attribute vec4 Position;
attribute vec4 BoneIndices;
attribute vec4 BoneWeights;
attribute vec2 UV;
varying vec4 v_Position;
varying vec2 v_UV;

void main()
{
    mat4 skinTransform;
    int boneIndex = int(BoneIndices.x);
    skinTransform += Bones[boneIndex] * BoneWeights.x;
    boneIndex = int(BoneIndices.y);
    skinTransform += Bones[boneIndex] * BoneWeights.y;
    boneIndex = int(BoneIndices.z);
    skinTransform += Bones[boneIndex] * BoneWeights.z;
    boneIndex = int(BoneIndices.w);
    skinTransform += Bones[boneIndex] * BoneWeights.w;
    vec4 skinPos = Position * skinTransform;
    vec4 worldPosition = skinPos * World;
    vec4 viewPosition = worldPosition * View;
    v_Position = viewPosition * Projection;
    v_UV = UV;
    gl_Position = v_Position;
}

APK

http://1drv.ms/1BzYV3Q Touch screen to on/off animation.

Info

  1. Xamarin.Android = 4.10.x.x
  2. Emulator Target = API 16 or 4.1
  3. Real device Target = API 16 or 4.1
  4. App Target = API 10 or 2.3 (tested also in API 14 and API 16), results remain the same

Is there any solution to solve this problem?

Best regards and thank you.

\$\endgroup\$

2 Answers 2

1
\$\begingroup\$

I guess that the problem is in the uninitialized variable skinTransform. You should always explicitly initialize all your variables. So, you need to define and initialize the variable skinTransform like this:

mat4 skinTransform(0.0);

See The OpenGL ES Shading Language documentation at section 5.4.2 Vector and Matrix Constructors for more information.

In addition, linear blending of transformation matrices is not a good idea for several reasons. Try to blend position values instead.

\$\endgroup\$
1
  • \$\begingroup\$ I think the result of mutiplying the position by the weighted sum of the matrices is exactly the same as calculating a weighted sum of the products of the position and each matrix. But you're right about initializing the matrix to zero. \$\endgroup\$
    – GuyRT
    Commented Feb 12, 2015 at 17:19
1
\$\begingroup\$

This is a known bug in Adreno GPUs.

Your problem is this little snippet of code:

Bones[boneIndex]

Many Adreno GPUs have a bug when accessing mat4 uniform arrays with non-constant indices. They will always silently return the first element in the array. This discussion on the qualcomm forums has some more background on this problem.

This bug applies only to uniform arrays of mat4. A known workaround is to encode each matrix as four vec4 instead, as proposed in this answer

Another way to solve this problem is to encode your matrices in OES_texture_float textures, as proposed in this answer. However, not all devices support OES_texture_float, and not all devices (including many Samsung devices) support accessing texture units from the vertex shader.

There is some more information in this question I posted a while ago.

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .