GLSL的GPU皮肤问题

Fra*_*era 5 opengl shader gpu glsl

我一直在使用openGL几个月,现在我自己学习它.现在我已经开始渲染位置,纹理坐标模型

我正在尝试使用动画模型,我将在显卡上进行动画蒙皮过程.

顺便说一句,如果有人想帮我1对1让我知道我不介意更直接的方法.

这是我的顶点格式

struct VERTEX_ANIMATED
{
    float3 position;
    float3 normal;
    float2 texCoord;
    float weights[4];
    unsigned boneIndices[4];
};
Run Code Online (Sandbox Code Playgroud)

这就是我将我的顶点添加到gpu缓冲区句柄的方法(这些函数中的任何未初始化的变量都位于".h"中)

bool CVertexBuffer::IncreaseVerts( const unsigned int uiNumVerts )
{
    //create our increase by value
    unsigned uiIncrement = (uiNumVerts / BUFFER_INCREASE_SIZE) * BUFFER_INCREASE_SIZE + BUFFER_INCREASE_SIZE;
    m_uiNumVerts += uiIncrement;

    //bind to our buffer
    void* buffer1; 
    if (GLEW_ARB_vertex_shader)
    {
        glBindBufferARB( GL_ARRAY_BUFFER_ARB, m_uiVertBufferHandle );

        //make sure our buffer exists
        buffer1 = glMapBufferARB( GL_ARRAY_BUFFER_ARB, GL_READ_WRITE );
    }
    else
    {
        glBindBuffer( GL_ARRAY_BUFFER, m_uiVertBufferHandle );

        //make sure our buffer exists
        buffer1 = glMapBuffer( GL_ARRAY_BUFFER, GL_READ_WRITE );
    }

    if( buffer1 )
    {
        //collection of all our data
        void* buffer2 = new char[ (m_uiNumVerts)*sizeof(VertexFormat) ];
        memset( buffer2, 0, (m_uiNumVerts)*sizeof(VertexFormat) );
        memcpy( buffer2, buffer1, (m_uiNumVerts - uiIncrement)*sizeof(VertexFormat)     );

        //create a new buffer
        //unsigned uiNewHandle;

        if (GLEW_ARB_vertex_shader)
        {
            //allocate our new storage space, and store our data in there
            glBufferDataARB( GL_ARRAY_BUFFER_ARB, (m_uiNumVerts*sizeof(VertexFormat)), buffer2, GL_DYNAMIC_READ );

            //lock our buffer
            //void* buffer2 = glMapBuffer( GL_ARRAY_BUFFER_ARB, GL_READ_WRITE );    

            //unlock our buffer2
            //if( glUnmapBufferARB( GL_ARRAY_BUFFER_ARB ) == GL_FALSE )
            //  return false;
            //}

            //reset what we are bound to
            glBindBufferARB( GL_ARRAY_BUFFER_ARB, 0 );
        }
        else
        {
            //allocate our new storage space, and store our data in there
            glBufferDataARB( GL_ARRAY_BUFFER_ARB, (m_uiNumVerts*sizeof(VertexFormat)), buffer2, GL_DYNAMIC_READ );

            //reset what we are bound to
            glBindBufferARB( GL_ARRAY_BUFFER_ARB, 0 );
        }

        //delete our buffer
        free( buffer2 );

        //Unmap our currently mapped buffer
        glUnmapBuffer( GL_ARRAY_BUFFER );

    return true;
}

unsigned int CVertexBuffer::AddVerts(const VERTEX_ANIMATED* pVerts, unsigned int iNumVerts)
{
    //Save the location to copy to
    unsigned int uiVertLocation = m_uiVertsUsed;

    m_uiVertsUsed += iNumVerts;

    if(m_uiVertsUsed > m_uiNumVerts)
    {
        IncreaseVerts(m_uiVertsUsed - m_uiNumVerts);
    }

    if(GLEW_ARB_vertex_program)
    {
        //bind the buffer we're gonna mess with
        glBindBufferARB( GL_ARRAY_BUFFER_ARB, m_uiVertBufferHandle );

        //get the pointer position where we can add verts
        void* pPositionBuffer = glMapBufferARB( GL_ARRAY_BUFFER_ARB, GL_READ_WRITE     );

        //now copy into our memory spot
        //which we need to move to the right position
        memcpy( ((char*)pPositionBuffer) + ( uiVertLocation*sizeof(VertexFormat) ), pVerts, iNumVerts*sizeof(VertexFormat));

        //now stop mapping
        glUnmapBufferARB(GL_ARRAY_BUFFER_ARB);
    }
    else
    {
        //bind the buffer we're gonna mess with
        glBindBuffer( GL_ARRAY_BUFFER, m_uiVertBufferHandle );

        //get the pointer position where we can add verts
        void* pPositionBuffer = glMapBuffer( GL_ARRAY_BUFFER, GL_READ_WRITE );

        //now copy into our memory spot
        //which we need to move to the right position
        memcpy( ((char*)pPositionBuffer) + ( uiVertLocation*sizeof(VertexFormat) ), pVerts, iNumVerts*sizeof(VertexFormat));

        //now stop mapping
        glUnmapBuffer(GL_ARRAY_BUFFER);
    }

    return uiVertLocation;
}
Run Code Online (Sandbox Code Playgroud)

我假设我的错误来自于我如何初始化我的数据或如何将数据传递给着色器.

这是对我的着色器程序创建的简单调用,它接受顶点着色器文件名和片段着色器文件名,然后是希望指定的主变量的变量,例如"position,normals,texCoords"

CreateProgram( "animTriangle.vp",
               "animTriangle.fp",
               5,
               VERTEX_ATTRIB, "vVertexPos",
               NORMAL_ATTRIB, "vVertexNormal",
               TEXTURE_COORD_ATTRIB0, "vTexCoord",
               COLOR_ATTRIB, "vBlendWeights",
               COLOR2_ATTRIB, "vBoneIndices" );
Run Code Online (Sandbox Code Playgroud)

在这个函数中,我在创建和编译着色器程序之后进行参数解析

 //make sure to use our program to setup our handles
glUseProgram( m_uiProgramHandle );

//start from this parameter
va_start( parseList, szFragmentShaderName );

//read in number of variables if any
uiNum = va_arg( parseList, unsigned );

//for loop through our attribute pairs
int enumType = 0;
for( unsigned x = 0; x < uiNum; ++x )
{
    //specify our attribute locations
    enumType = va_arg( parseList, int );
    char* name = va_arg( parseList, char* );
    glBindAttribLocation( m_uiProgramHandle, enumType, name );
}

//end our list parsing
va_end( parseList );
Run Code Online (Sandbox Code Playgroud)

这是我的顶点着色器开头的变量列表

in vec3 vVertexPos;     // position
in vec3 vVertexNormal;  // normal
in vec2 vTexCoord;      // texture coordinate....
in vec4 vBlendWeights;  // the weights pull of the related bone
in ivec4 vBoneIndices;  // the indicators of which bones we are influenced by
Run Code Online (Sandbox Code Playgroud)

这是我的顶点步幅

 //set which vertices we will be using
 glBindBuffer( GL_ARRAY_BUFFER, m_uiVertBufferHandle );

 //enable these vertex attributes
 glEnableVertexAttribArray( VERTEX_ATTRIB );
 glEnableVertexAttribArray( NORMAL_ATTRIB );
 glEnableVertexAttribArray( TEXTURE_COORD_ATTRIB0 );
 glEnableVertexAttribArray( COLOR_ATTRIB );
 glEnableVertexAttribArray( COLOR2_ATTRIB );

 //specify our vertex attribute
 glVertexAttribPointer( VERTEX_ATTRIB, 3, GL_FLOAT, GL_FALSE, sizeof( VERTEX_ANIMATED ), BUFFER_OFFSET(0) );

 //specify our normal attribute
 glVertexAttribPointer( NORMAL_ATTRIB, 3, GL_FLOAT, GL_FALSE, sizeof( VERTEX_ANIMATED ), BUFFER_OFFSET(12) );

 //specify our texture attribute
 glVertexAttribPointer( TEXTURE_COORD_ATTRIB0, 2, GL_FLOAT, GL_FALSE, sizeof( VERTEX_ANIMATED ), BUFFER_OFFSET(24) );

 //specify our bone weight attribute location
 glVertexAttribPointer( COLOR_ATTRIB, 4, GL_FLOAT, GL_FALSE, sizeof( VERTEX_ANIMATED ), BUFFER_OFFSET(32) );

 //specify our bone indice attribute location
 glVertexAttribPointer( COLOR2_ATTRIB, 4, GL_INT, GL_FALSE, sizeof( VERTEX_ANIMATED ), BUFFER_OFFSET(48) );
Run Code Online (Sandbox Code Playgroud)

现在我可以加载静态模型就好了.当我加载我的动画模型时,我会得到一半的模型或一半的模型,在那一半上缺少一些块.之前我曾使用过DirectX,当gpu正确读取缓冲区时,我才遇到过这个问题.

如果你们想了解更多信息,请告诉我们.我在这个奇怪的问题上待了将近两个星期,我真的很想了解我的问题.

And*_*man 3

看来您可能忘记NORMAL_ATTRIB在代码中进行初始化。您的调用CreateProgram (...)不包括顶点着色器中的NORMAL_ATTRIB与的关联。vVertexNormal

如果您的顶点着色器需要顶点法线用于动画目的,并且您没有正确将此顶点指针连接到适当的属性槽,则结果将是未定义的。

同样,该问题也可能是由于NORMAL_ATTRIB另一属性未初始化而产生别名所致。例如,顶点属性 0 通常是位置,如果NORMAL_ATTRIB在此代码中未初始化,则可能会使用普通指针重新定义顶点位置指针。