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 9 of 9

Thread: Storing vector list to be accessed in shader

  1. #1
    Junior Member Newbie
    Join Date
    Jan 2013
    Posts
    13

    Storing vector list to be accessed in shader

    I have a large vector list of values that I want to send once to the GPU, but I'm not sure how to go about it. It's not a vertex attribute.

    I'm not sure if I'm suppose use gluniform (does it send over the data everytime?)

    sorry I'm still relatively new to shaders :P

  2. #2
    Senior Member OpenGL Guru Dark Photon's Avatar
    Join Date
    Oct 2004
    Location
    Druidia
    Posts
    3,191
    Yes, a uniform array is a good place to start. If it doesn't change, you only provide it to the driver once, not every time you want to run with the shader.

  3. #3
    Junior Member Newbie
    Join Date
    Jan 2013
    Posts
    13
    Wait are you saying I'd have to uniform each array element individually? We're talking about a std list consisting of over 2000 elements :/

    I'm trying to do GPU skinning, is there a way to pass a std::vector through 1 uniform call?

    and I realize that I have no choice but to send it over each draw call because the vector list is per mesh rather than the entire object...

  4. #4
    Senior Member OpenGL Guru Dark Photon's Avatar
    Join Date
    Oct 2004
    Location
    Druidia
    Posts
    3,191
    Quote Originally Posted by KennyW View Post
    Wait are you saying I'd have to uniform each array element individually?
    Heck no! That'd be ugly.

    We're talking about a std list consisting of over 2000 elements :/
    I hope we're not talking about a std::list, because that's typically implemented as a doubly-linked list with lots of pointer chasing and plenty of cache misses to show for it. Forget efficient memcpy uploads with that thing.

    I'm trying to do GPU skinning, is there a way to pass a std::vector through 1 uniform call?
    Absolutely. Let's suppose you have a standard uniform array of mat4s in the shader:

    uniform mat4 transforms[ MAX_LENGTH ];

    Then you just populate them with:

    glUniformMatrix4fv( loc, array_len, false, ptr )

    where array_len is the number of matrices to update (which is <= MAX_LENGTH). There are similar glUniform* calls for other element types.

    Note that I am not suggesting you upload your skinning transforms as mat4s. You could, but if you're only doing linear blend skinning (LBS), you could also consider using mat4x3s for a 25% space savings (avoids sending the 0,0,0,1 row). Or you could use a mat2x4 containing a dual quaternion (or a quaternion-translation pairs) and decode/blend them in the shader (if you're doing Dual Quaternion or Spherical Blend Skinning). Up to you.

    Also, while you could upload these to an ordinary uniform array using the above, if in your skeletal/rendering system you have the possibility for reusing a set of transforms multiple times, then you'll probably be better off to upload these transforms into a texture or a buffer object. These can then be uploaded once and then rebound to one or more shaders for reuse fairly quickly.

    ...and I realize that I have no choice but to send it over each draw call because the vector list is per mesh rather than the entire object...
    See my last paragraph. You don't have to send it over for each draw call necessarily, but can send it only when it is updated and reuse it across multiple shader invocations.

  5. #5
    Junior Member Newbie
    Join Date
    Jan 2013
    Posts
    13
    thanks for the helpful info

    I'm trying to pass in a vector of weight data but it doesn't seem to be working

    glUniform4fv(glGetUniformLocation(this->meshes[m]._shader, "weights_ID"), 1158,&meshes[m].weight_jointIDs[0]);

    (shader)
    uniform float weights_ID[1158];

    I've tried a bit of debugging and the values in the shader program are still missing I'm not sure what I'm doing wrong.

    other uniform calls seems to pass in the value just fine, just not with the vector above

  6. #6
    Senior Member OpenGL Guru Dark Photon's Avatar
    Join Date
    Oct 2004
    Location
    Druidia
    Posts
    3,191
    Quote Originally Posted by KennyW View Post
    I'm trying to pass in a vector of weight data but it doesn't seem to be working

    glUniform4fv(glGetUniformLocation(this->meshes[m]._shader, "weights_ID"), 1158,&meshes[m].weight_jointIDs[0]);
    If you're doing smooth skinning, your joint weights and indices should be vertex attributes on your mesh. So I would pass those in as vertex attributes not uniforms.

  7. #7
    Junior Member Newbie
    Join Date
    Jan 2013
    Posts
    13
    If you're doing smooth skinning
    I'm not sure which form of skinning I'm currently using but I've implemented the skeletal animation system from this web page (http://3dgep.com/?p=1053) where CPU skinning is used.


    your joint weights and indices should be vertex attributes on your mesh.
    The joint weights and indices contain multiple weights per vertex, so the number of elements for the weights vector (1158) doubles the amount of vertices passed (576). I don't think it will work if I pass it as a vertex attribute since each weight element doesn't directly correspond with the same index vertex element.


    this is the skinning algorithm used taken from the site

    bool MD5Model::PrepareMesh( Mesh& mesh, const MD5Animation::FrameSkeleton& skel )
    {
    for ( unsigned int i = 0; i < mesh.m_Verts.size(); ++i )
    {
    const Vertex& vert = mesh.m_Verts[i];
    glm::vec3& pos = mesh.m_PositionBuffer[i];
    glm::vec3& normal = mesh.m_NormalBuffer[i];

    pos = glm::vec3(0);
    normal = glm::vec3(0);

    for ( int j = 0; j < vert.m_WeightCount; ++j )
    {
    const Weight& weight = mesh.m_Weights[vert.m_StartWeight + j];
    const MD5Animation::SkeletonJoint& joint = skel.m_Joints[weight.m_JointID];

    glm::vec3 rotPos = joint.m_Orient * weight.m_Pos;
    pos += ( joint.m_Pos + rotPos ) * weight.m_Bias;

    normal += ( joint.m_Orient * vert.m_Normal ) * weight.m_Bias;
    }
    }
    return true;
    }


    Unfortunately the transforms aren't done with matrices, instead they are calculated with quaternions and vector3s.

    I can pass in the vertices and vertex weight counts as vertex attributes, but I need to figure out how I can pass in my weights and joints vectors into the vertex shader.

    so far I'm trying to pass in the weights and joint data into the shader but no luck as you've seen in my last post.

    yeah like I said I'm a noob with shaders lol as I've only begun learning it late last year, but as soon I can get the weights and joints into the shader all I have to do is perform the same calculations above in the GPU.
    Last edited by KennyW; 01-02-2014 at 03:33 PM.

  8. #8
    Junior Member Newbie
    Join Date
    Jan 2013
    Posts
    13
    hmm I've been looking around and it seems that I can just store my weights in a vector4 per vertex. I'll try that soon

  9. #9
    Junior Member Newbie
    Join Date
    Jan 2013
    Posts
    13
    sweet I got it working! thanks for the help

Posting Permissions

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