vertex skinning: error index expression must be constant

i have done a vertex skinning animation with 52 bones and all was working fine in the vertex shader before the new webgl spec but now i have this error : []index expression must be constant each time i index my bones matrix array because now its forbidden to put a variable in an array apparently in webgl. here is an example :

outVert += weights4 * (bones[bone4] * curVert);

	 outVert += weights5 * ([b]bones[bone5] [/b]* curVert);/[b]/error index expression must be constant[/b]
	
	 outVert += weights6 * ([b]bones[bone6][/b] * curVert);/[b]/error index expression must be constant[/b]
	
	 outVert += weights7 * [b](bones[bone7] [/b]* curVert);[b]//error index expression must be constant[/b]

any idea to fix it? thanks

My game uses vertex arrays to store bone transforms - probably in code that’s nearly identical to yours - and it’s still working OK under the latest Chrome and Firefox under Linux and Windows today.

It should work just fine with variables as array indices. Check out the OpenGL ES 2 specification here:

http://www.khronos.org/registry/gles/sp … 1.0.17.pdf

…section 4.1.9 doesn’t state any restriction of that kind.

If you’re using 52 bones - you might be exceeding the maximum number of uniform variables that your graphics card supports. The requirement is that the hardware support at least 128 vec4’s…if you’re packing a bone into just two vec4’s and are fairly frugal about other uniforms - then you should have enough space - but if you’re using a 4x4 matrix per bone or something…then you’re going to be in trouble on crappier hardware.

(That doesn’t explain the error message though)

What browser version, what OS and what graphics-hardware are you using? Have you seen this problem on different setups?

– Steve

i used chrome 9 and i downloaded 10 today and the bug is still there
im on windows 64

how did u store your bones in the vertex shader and how did you index them with the influences for each vertex?

I found that sometimes change your code with a equivalent way may be helpful. When I write my hardware skinning in webgl, I use a for loop to traverse all the bones for the vertex, but it does not work. However, when I abandon the loop and use straightforward code, it works. Wish this tip is helpful to you. :smiley:

ok thanks

did u try molehill? what you think about u prefer webgl?

WebGL is not powerful nor convenient to develop, but I think it did help people to get amazing web content more easily, from the phones, iPads, IpTVs and so on. I cannot imagine the future of the web3D technique is dependent on one commercial product instead of a common standard. :smiley:

I didn’t try to pack my bone transforms in any clever way because my characters only need ~24 bones.


#define NUM_BONES 24

attribute vec3 POSITION ;
attribute vec4 BONEINDEX ;
attribute vec3 BONEWEIGHT ;
uniform mat4 BindToModel [NUM_BONES] ;

  mat4 b2mx  = BindToModel [ int(BONEINDEX.x) ] ;
  mat4 b2my  = BindToModel [ int(BONEINDEX.y) ] ;
  mat4 b2mz  = BindToModel [ int(BONEINDEX.z) ] ;
  mat4 b2mw  = BindToModel [ int(BONEINDEX.w) ] ;

  float BONEWEIGHT_w = 1.0 - ( BONEWEIGHT.x + BONEWEIGHT.y + BONEWEIGHT.z ) ;

  bodyPos = b2mx * vec4 ( POSITION, 1.0 ) * BONEWEIGHT.x +
                 b2my * vec4 ( POSITION, 1.0 ) * BONEWEIGHT.y +
                 b2mz * vec4 ( POSITION, 1.0 ) * BONEWEIGHT.z +
                 b2mw * vec4 ( POSITION, 1.0 ) * BONEWEIGHT_w ;

Nothing fancy…but it works everywhere I’ve tried it.

In my implementation, I use four condition branch to check every bone’s availability and I think yours is faster.

ok thanks but how did u upload ypur array of matrixs bindToModel, i know its with gl_uniformMatrix but can u give me the exact syntax please

cause i try like that it doesn’t work:

vertex shader

#define NUM_BONES 20


uniform mat4 bones[NUM_BONES];

…vertex skinning…

-----end vertex shader------------

shaderProgram.bonesMatrixUniform = gl.getUniformLocation(shaderProgram, “bones”);

my_Bones.push(Leg_L.flatten())
my_Bones.push(Shin_L.flatten())
my_Bones.push(Ankle_L.flatten())
my_Bones.push(Foot_L.flatten()))
my_Bones.push(Leg_R.flatten())
my_Bones.push(Shin_R.flatten())
my_Bones.push(Ankle_R.flatten())
my_Bones.push(Foot_R.flatten())
my_Bones.push(Spine1.flatten())

gl.uniformMatrix4fv(shaderProgram.bonesMatrixUniform, false, new Float32Array(my_Bones));

After linking the shader:


  this.BindToModelLocn = gl.getUniformLocation ( this.programObject, "BindToModel" ) ;

Then, before I call gl.drawElements to render the mesh:


  if ( this.BindToModelLocn )
    gl.uniformMatrix4fv(this.BindToModelLocn, false, bones ) ;

…where “seq” is something like:


var bones = new Float32Array ([
1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,.9,1,    // Bone 0
1,0,0,0, 0,1,.1,0 ,0,-.1,1,0, 0,.02,.9,1,   // Bone 1
...
.97,0,-.23,0, .02,.99,.1,0, .23,-.1,.97,0, -.1,.02,.92,1  // Bone 19
]) ;