GLSL的GPU皮肤问题

时间:2013-07-03 02:34:17

标签: opengl glsl shader gpu

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

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

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

这是我的顶点格式

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;
}

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

这是对我的着色器程序创建的简单调用,它接受顶点着色器文件名和片段着色器文件名,然后是希望指定的主变量的变量,如“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" );

在此函数中,我在创建和编译着色器程序

之后进行参数解析
 //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 个答案:

答案 0 :(得分:3)

您可能忘记在代码中初始化NORMAL_ATTRIB。您对CreateProgram (...)的来电未在您的顶点着色器中包含NORMAL_ATTRIBvVertexNormal的关联。

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

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

答案 1 :(得分:0)

我的整体问题原来是我的抽签。我正在指定要绘制的原始三角形的数量,而不是指数的数量,这些指数只是我的&#34;三角形数* 3&#34;。

这可以解释为什么一些模型会显示出来,但它会被分块。