Vertex Skinning with GLSLShaderObjectsState and Uniforms

First, I am sorry if this post is covered elsewhere, please point in the right direction if so.

Thanks in advance.



On to my question…



We are building the next-gen avatar and animation system on Sun’s Wonderland Project and are planing on using H/W shaders on the avatars.  So far we have made decent progress with jME but as we close in on our technique of choice I am finding an issue with GLSLShaderObjectsState.



I see two problems bubbling up.



The first is that I’d like to pass in a Matrix4f (or other form) [] (i.e. array) as a Uniform.  This would be the joint transformations needed in the vertex shader for skinning deformation.  You can do that in the vertex shader, but there is no setUniform( Matrix4f[],…) only float[].  Now the float array could work as an alternative, but in the actual source it’s mapping that float[] to a matrix2f in the shader…



What is the preferred way to set up a Matrix4f(3f)[] in jME + GLSL?



Second, calling setUniform for each uniform each frame seems a bit overheady.  It is working fine for now, but I am wondering where if any is there a part of the API where I can get back the Uniform offset or count (or an object handle if wrapped) so the setUniform doesn’t have to match by name each time, each frame, each object, we update with data.



Thanks for any help!

OK since there's been no response I imagine the worst… :slight_smile:



So i have dug down through GLSLShaderObjectsState into ShaderVariable then on to the LWJGLShaderUtil where the shader uniforms are actually being sent down the pipe and sure enough there is no implementation for array type anywhere.



In pure OpenGL you'd typically use glUniform4fv to load up an array of vec4 but I see there is no reference to the call anywhere in jME(i.e through LWJGL's version of the call).  So I have two new questions.


  1. Is there any/other newer version of jME that we should be working with that may have this completely implemented?


  2. We are prepare to hacked this in, as it is a show stopper for our avatar system progress.  I suppose we may need to get linked into the formal development process to feed this back if need be but let me know what the next step is.



    Thanks!

There is no support for Matrix4f uniform arrays in jME, i too had to implement it in my own version. Just look at ShaderVariableMatrix4.java , what you need is implement handling of "matrixBuffer" so that it can hold more Matrix4f, not just one.

vear said:

There is no support for Matrix4f uniform arrays in jME, i too had to implement it in my own version. Just look at ShaderVariableMatrix4.java , what you need is implement handling of "matrixBuffer" so that it can hold more Matrix4f, not just one.

You say you've implemented your own?  I have checked the ShaderVariable stuff maybe I'm looking for the wrong thing but....

I need to set glUniformMatrix4fvARB, but I don't even see that call in LWJGL, let alone jME wrappers.
First I need to make my own ShaderVariableMatrix4v (array type) then I'd need to update GLSLShaderObjectState as well as LWJGLShaderUtil with wrapper calls but finally I'd hit the ARBShaderObjects.glUniformXXX methods that apply (wrap) the GL calls. But ARBShaderObjects is a LWJGL class and has no support for glUniformMatrix4fvARB in the code I'm seeing.

If you did this, can you give some more detail on how :)  Either I'm missing a different path, or I'd have to change LWJGL as well!

Thanks for any help!


        matrixBuffer.rewind();
        ARBShaderObjects.glUniformMatrix4ARB(variableID,transpose, matrixBuffer);



This is how you set the matrices. Each matrix is 16 floats, so in total matrixBuffer.limit()/16 matrices will be set.

Are you using ShaderVariableMatrix4 as your variableID and/or the same class for packing the matrices?



It looks like we'd have to make a new ShaderVariableMatrix4X class since ShaderVariableMatrix4 sets the FloatBuffer size to 16.

Is that what you did? and again what variableID did you use? :slight_smile:



Thanks!



[edit]

Ok I missed what the variableID was, this is the GL variable ref right?  So I get that we won't set that, but then that means this must still be either the ShaderVariableMatrix4 or a new derived ShaderVariableMatrix4XXX class, no?



[edit]

Ok I got it! :slight_smile: and thanks for the tips.

Now I just need to post the example here in case anyone else runs into this! :wink:

I presume you don't need a new class, you just need to handle matrixBuffer so that its size is not fixed to 16, and implement methods to put more matrices into it. I have shader handling different than in jME. Still, to get some idea, here is what i use:



public class ShaderVariableMatrix4Buffer extends ShaderVariable {
    public FloatBuffer matrixBuffer = null;
    public boolean transpose;
   
    @Override
    public void update() {
        matrixBuffer.rewind();
        ARBShaderObjects.glUniformMatrix4ARB(variableID,
                transpose, matrixBuffer);
        //GL20.glUniformMatrix4(variableID, transpose, matrixBuffer);
    }
   
    public void allocate(int numMatrices, boolean transpose ) {
        this.transpose = transpose;
        matrixBuffer = BufferUtils.createFloatBuffer(16*numMatrices);
    }
   
    public void set(int index, Matrix4f value) {
        matrixBuffer.position(index*16);
        value.putFloatBufferRowMajor(matrixBuffer);
    }
   
    public void put(Matrix4f value) {
        value.putFloatBufferRowMajor(matrixBuffer);
    }
   
    public void rewind() {
        matrixBuffer.rewind();
    }
   
    public void position(int index) {
        matrixBuffer.position(index*16);
    }

    public int limit() {
        if(matrixBuffer==null)
            return 0;
        return matrixBuffer.limit()/16;
    }
}