5

我已经使用 openGL 工作了几个月,现在只是自己学习。现在我已经开始渲染位置、纹理坐标模型了

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

顺便说一句,如果有人想一对一地帮助我,请告诉我,我不介意更直接的方法。

这是我的顶点格式

struct VERTEX_ANIMATED
{
    float3 position;
    float3 normal;
    float2 texCoord;
    float weights[4];
    unsigned boneIndices[4];
};

这就是我将顶点添加到 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;
}

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

这是对我的着色器程序创建的简单调用,它接受顶点着色器文件名和片段着色器文件名,然后是希望指定的主要变量的变量,例如“位置、法线、texCoords”

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

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

 //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 );

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

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

这是我的顶点步幅

 //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) );

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

如果你们想了解更多信息,请告诉我。我在这个奇怪的问题上待了将近 2 周,并且真的很想了解我的问题。

4

2 回答 2

3

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

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

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

于 2013-08-27T08:46:19.070 回答
0

我的整体问题原来与我的抽奖电话有关。我指定了要绘制的原始三角形的数量,而不是我的“三角形计数 * 3”的索引数量。

这可以解释为什么某些模型会出现但会被分块。

于 2014-08-18T15:49:53.490 回答