Part of the Khronos Group
OpenGL.org

The Industry's Foundation for High Performance Graphics

from games to virtual reality, mobile phones to supercomputers

Results 1 to 3 of 3

Thread: Vertex shader help pt.2

  1. #1
    Junior Member Newbie
    Join Date
    Nov 2014
    Posts
    10

    Vertex shader help pt.2

    This code is for skeletal animation

    so say i have this code
    Code :
    #define NUM_BONES 50
    uniform mat4 bones[NUM_BONES];
    uniform vec4 weights[NUM_BONES];
    uniform ivec4 attachments[NUM_BONES];
     
    in vec4 position;
     
    void main() {
        vec4 position4 = vec4(position, 1.0);
        vec4 worldPosition = vec4(0.0);
        for (int i = 0; i < 4; i++)
            worldPosition += weights[attachments[gl_VertexID][i]] * (bones[attachments[gl_VertexID][i]] * position);
        gl_Position = gl_ModelViewProjectionMatrix * worldPosition;
    }

    1.Why is the weights a vec4? Isn't a weight only one value, like a float?

    2.in the vertex shader, why am i only able to use 1D arrays? I have to make about 8 uniform arrays in order to use all the information i need.

    3. When a parent bone rotates, the matrix of the bone is given a slight change in rotation(Im converting the matrix to quanternion and then multiplying quanternions), how do i correctly rotate the child bones. For example, if i rotate the shoulder, the rest of the arm has to rotate the same amount. Could somebody explain this further? / in more detail.

    4. with the code below, it shows only 4 bones per vertex. What if i want more than just 4? And once again i dont understand the vec4 weight thing.

    Code :
    in vec3 position;
    in vec2 textureCoords;
    in vec3 normal;
    in vec4 BoneIndex;
    in vec4 Weights;
    uniform mat4 bones[10];
     
    void main()
    {
    vec4 newvertex;
    vev3 newNormal;
    new newvertex += bones[int(BoneIndex.x)]*gl_Vertex*Weights.x;
    new newNormal+= mat3(bones[int(BoneIndex.x)])*gl_Normal*Weights.x;
     
    new newvertex += bones[int(BoneIndex.y)]*gl_Vertex*Weights.y;
    new newNormal+= mat3(bones[int(BoneIndex.y)])*gl_Normal*Weights.y;
     
    new newvertex += bones[int(BoneIndex.z)]*gl_Vertex*Weights.z;
    new newNormal+= mat3(bones[int(BoneIndex.z)])*gl_Normal*Weights.z;
     
    new newvertex += bones[int(BoneIndex.w)]*gl_Vertex*Weights.w;
    new newNormal+= mat3(bones[int(BoneIndex.w)])*gl_Normal*Weights.w;
     
    gl_Position = Projection*View*Transform*newvertex ;
    newNormal = mat4(Transform)*newNormal ;
    }

    Currently i have this code as my vertex shader:

    Code :
    #version 400 core
     
    in vec3 position;
    in vec2 textureCoords;
    in vec3 normal;
     
    out vec2 pass_textureCoords;
    out vec3 surfaceNormal;
    out vec3 toLightVector;
    out vec3 toCameraVector;
     
    uniform mat4 transformationMatrix;
    uniform mat4 projectionMatrix;
    uniform mat4 viewMatrix;
    uniform vec3 lightPosition;
    uniform int boneCount;
    uniform mat4 bonesMatrix[21];
    uniform float boneWeights[2013];
     
    void main(void){
    	float bonepos_x = transformationMatrix[3][0];
    	float bonepos_y = transformationMatrix[3][1];
    	float bonepos_z = transformationMatrix[3][2];
    	vec4 worldPosition = (transformationMatrix* vec4(position,1.0));
    	gl_Position = projectionMatrix * viewMatrix * worldPosition; 
    	pass_textureCoords = textureCoords;
    	surfaceNormal = (transformationMatrix * vec4(normal,0.0)).xyz;
    	toLightVector = lightPosition - worldPosition.xyz;
    	toCameraVector = (inverse(viewMatrix) * vec4(0.0,0.0,0.0,1.0)).xyz - worldPosition.xyz;
    }

    as you can see i have an array of boneWeights, but i think it needs to be in vec4 to work? but i dont know.

    If you can help me out in any way go ahead! Thanks .

  2. #2
    Senior Member OpenGL Guru
    Join Date
    Jun 2013
    Posts
    2,402
    Quote Originally Posted by noahn567 View Post
    1.Why is the weights a vec4? Isn't a weight only one value, like a float?
    This assumes that each vertex may be affected by up to four bones. If you want more, you need to use some other approach. if each vertex is only affected by a single bone, you don't need weights.

    Quote Originally Posted by noahn567 View Post
    2.in the vertex shader, why am i only able to use 1D arrays?
    GLSL only supports 1D arrays. You can't have arrays of arrays.

    You can have arrays of vectors or arrays of matrices. You can "unravel" larger arrays yourself. E.g. given

    float data[rows][cols];

    You can use

    float data[rows*cols];

    and translate data[r][c] to data[cols*r+c].

    Or you can use a texture as an array.

    Quote Originally Posted by noahn567 View Post
    3. When a parent bone rotates, the matrix of the bone is given a slight change in rotation(Im converting the matrix to quanternion and then multiplying quanternions), how do i correctly rotate the child bones. For example, if i rotate the shoulder, the rest of the arm has to rotate the same amount. Could somebody explain this further? / in more detail.
    Normally, each transformation is relative to the parent, e.g. the shoulder rotation is the rotation of the upper arm relative to the shoulder blades. A joints absolute transformation is obtained by multiplying the parent's absolute transformation by the joint's relative transformation.

    So given a hierarchy of joints, you start with either an identity matrix or an absolute transformation for the object as a whole. You then perform a recursive traversal over the hierarchy, generating the absolute transformation for each joint (you always visit the parent before visiting its children, so the parent's absolute transformation is already available when you need to calculate that of the child).

    Quote Originally Posted by noahn567 View Post
    4. with the code below, it shows only 4 bones per vertex. What if i want more than just 4? And once again i dont understand the vec4 weight thing.
    Having four weights is convenient because it's enough for many cases while being relatively simple to implement given GLSL's limitation of 1D arrays. One problem with having many bone attachments per vertex is that performance is dictated by the maximum number rather than the average number (i.e. if most vertices only have one bone but some have 20, you'll end up performing 20 iterations for every vertex).

    That code basically unwraps the loop, and accesses the weights using .x, .y, .z, .w. You can access vector elements using either structure notation (.x, .y etc) or array notation ([0], [1]) etc. Using array notation lets you use a loop.

  3. #3
    Junior Member Newbie
    Join Date
    Nov 2014
    Posts
    10
    Thank you once again!

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •