OpenGL - 加载顶点数据时对glBufferData()的SegFault

时间:2014-09-07 21:02:27

标签: c++ opengl segmentation-fault

问题:glBufferData上的分段错误。

关于libs&输入数据:

 3ds file contains a few models.
 GLEW - 1.11.0
 GLFW - 3.0.4
 GLM - 0.9.5.4
 ASSIMP - 3.1.1

 OS - Windows 7 x64 lastest PS

 GPU: nvidia 770

输出:

Wersja OpenGL: 4.4.0
    Kompilacja shadera...
Compiling shader : vert.vs
- Success
Compiling shader : frag.fs
 - Success
        Ustawianie Model - Widok - Projekcja...
Wczytywanie wczeťniej wygenerowanych obiektˇw...
        Ladowanie Mesha nr.0...
Rozmiary - 2 | 108 | 108
a
b
c

这是代码:

Mesh_Loader.cpp

GLfloat **vertexData, **normalData, **colorsData_buffer;

GLushort** indexData;

/** Bufory */
GLuint* vertexBuffer, *colorBuffer, *indexBuffer;


int mesh_size = 0;

unsigned int* count_of_vertex; //Licznik ile vertex-ów na danym meshie jest
int* count_of_index; //Licznik indeksów
unsigned int suma_vertexow = 0; //Suma wszystkich vertexow... normalnie się powinno to inaczej obejść. Ale kij.


const struct aiFace* tmp_face;
int tmp_index = 0;


//[...]
bool mesh_load(const std::string& Filename)
{

    Assimp::Importer Importer;

    const aiScene* pScene = Importer.ReadFile(Filename.c_str(), aiProcess_Triangulate | aiProcess_GenSmoothNormals | aiProcess_FlipUVs);

    /** Sprawdzenie czy wczytał scene */
    if (pScene) {
        init_from_scene(pScene);
        return true;
    }
    else
    {
        std::cout << "Wystąpił błąd podczas wczytywania: " << Importer.GetErrorString() << std::endl;
        return false;
    }

}


void pre_reserve_memory(const aiMesh* paiMesh, int cur_poz)
{

    count_of_index[cur_poz] = 0;

    for (unsigned int i = 0; i < paiMesh->mNumFaces; i++) {

        tmp_face = &paiMesh->mFaces[i];

        count_of_index[cur_poz] += tmp_face->mNumIndices;

    }

    indexData[cur_poz] = new GLushort[count_of_index[cur_poz]];
}




void init_from_scene(const aiScene* pScene)
{

    mesh_size = pScene->mNumMeshes;


    //Pre Rezerwacja miejsca
    vertexData = new GLfloat*[mesh_size];
    colorsData_buffer = new GLfloat*[mesh_size];
    normalData = new GLfloat*[mesh_size];

    indexData = new GLushort*[mesh_size];

    //Buffory
    vertexBuffer = new GLuint[mesh_size];
    colorBuffer = new GLuint[mesh_size];
    indexBuffer = new GLuint[mesh_size];

    count_of_vertex = new unsigned int[mesh_size];
    count_of_index = new int[mesh_size];



    for (unsigned int i = 0; i < pScene->mNumMeshes; i++)
    {
        pre_reserve_memory(pScene->mMeshes[i], i);

         // [...]

        przepare_mesh(pScene->mMeshes[i], vertexData[i], colorsData_buffer[i], normalData[i], indexData[i], &count_of_vertex[i]);

    }



}

void przepare_mesh(const aiMesh* paiMesh, GLfloat* vertexData, GLfloat* colorsData_buffer, GLfloat* normalData, GLushort* indexData, unsigned int* count_of_vertex)
{
    int counter;


    vertexData = (GLfloat *)&paiMesh->mVertices;
    colorsData_buffer = (GLfloat *)&paiMesh->mColors;
    normalData = (GLfloat *)&paiMesh->mNormals;
    *count_of_vertex = paiMesh->mNumVertices;



    for (unsigned int i = 0; i < paiMesh->mNumFaces; i++) {

        tmp_face = &paiMesh->mFaces[i];

        for (unsigned int j = 0; j < tmp_face->mNumIndices; j++)
        {
            counter = i + j;

            indexData[counter] = tmp_face->mIndices[j];
        }
    }
}


/** TODO: RE-LIGHTING, MOUSE */
void render_scene()
{

    glLinkProgram(program); // jak skompilowalem kod to moge go polaczyc z bibliotekami - linkowanie
    glUseProgram(program); // od tego momentu wszystko co zrobie bedzie uzywac tego programu (tej kombinacji shaderow)

    glClearColor(0.0f, 0.0f, 0.4f, 0.0f); // ustala kolor wyczyszczonego okna

    glEnable(GL_CULL_FACE); // wewnetrzne flagi opengl
    glEnable(GL_DEPTH_TEST);
    glDepthFunc(GL_LESS);
    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

    /** Model - View - Projection */
    glm::mat4 Model = glm::mat4(1.0f); // tworzenie macierzy obiektu
    glm::mat4 View = glm::lookAt(glm::vec3(0.0f, 2.0f, -5.0f), glm::vec3(), glm::vec3(0.0f, 1.0f, 0.0f)); // widoku
    glm::mat4 Projection = glm::perspective(60.0f, 16.0f / 9.0f, 0.1f, 1000.0f); // projekcji
    glm::mat4 MVP; // zmienna na pozniej

    GLuint MVPUniformLoc = glGetUniformLocation(program, "MVP"); // daje wskaznik gdzie MVP znajduje sie w pamieci


    /** Addresy Pamięci */
    GLuint positionAttribLoc = glGetAttribLocation(program, "position"); // wytlumaczenie cpu jak sie dostac do adresu pamieci gpu
    GLuint colorAttribLoc = glGetAttribLocation(program, "color");


    /** tworzenie tablicy przechowujacej vertexy */
    GLuint vertexArrayObject; 
    glGenVertexArrays(1, &vertexArrayObject);
    glBindVertexArray(vertexArrayObject);



    for (int i = 0; i < mesh_size; i++)
    {


        suma_vertexow += count_of_vertex[i];

        glGenBuffers(1, &vertexBuffer[i]);

        glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer[i]);

        glBufferData(GL_ARRAY_BUFFER, (sizeof(GLfloat)* count_of_vertex[i]), vertexData[i], GL_STATIC_DRAW); //Problem Area

        if (colorsData_buffer[i] != NULL)
        {
            glGenBuffers(1, &colorBuffer[i]);
            glBindBuffer(GL_ARRAY_BUFFER, colorBuffer[i]);
            glBufferData(GL_ARRAY_BUFFER, (sizeof(GLfloat) * count_of_vertex[i]), colorsData_buffer[i], GL_DYNAMIC_DRAW);

        }




        glGenBuffers(1, &indexBuffer[i]);
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer[i]);
        glBufferData(GL_ELEMENT_ARRAY_BUFFER, (sizeof(GLushort)* count_of_index[i]), indexData[i], GL_DYNAMIC_DRAW);
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, NULL);


        glEnableVertexAttribArray(positionAttribLoc); // atrybuty wskazinikow (bufory)
        glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer[i]);
        glVertexAttribPointer(
            positionAttribLoc,       // attribute. No particular reason for 0, but must match the layout in the shader.
            3,        // size
            GL_FLOAT,        // type
            NORMALIZED,  // normalized?
            0,      // stride - wierzcholki oznaczajace pozycje sa w tym buforze jeden za drugim (odstep miedzy kolejnymi wierzcholkami)
            (GLvoid*)0      // array buffer offset - w ktorym miejscu bufora zaczyna sie inf o wierzcholkach
            );

        glBindBuffer(GL_ARRAY_BUFFER, NULL);

        if (colorsData_buffer[i] != NULL)
        {
            glEnableVertexAttribArray(colorAttribLoc);
            glBindBuffer(GL_ARRAY_BUFFER, colorBuffer[i]);
            glVertexAttribPointer(
                colorAttribLoc,       // attribute. No particular reason for 0, but must match the layout in the shader.
                3,        // size
                GL_FLOAT,        // type
                NORMALIZED,  // normalized?
                0,      // stride
                (GLvoid*)0      // array buffer offset
                );

        }
        glBindBuffer(GL_ARRAY_BUFFER, NULL);





    }
   //[...]
}

Mesh_Loader - &gt;通过来自3DS文件的assimp.importer数据加载 并提取有关每个网格的索引,颜色,顶点,法线的数据

function render - &gt;加载有关索引,颜色,顶点,法线的数据

但是当它将数据加载到缓冲区时会引起一些问题&#34; glBufferData&#34; 段错误

Additioanl_func.cpp 负载着色器和附件的额外功能;鼠标回调

哪里有问题?

1 个答案:

答案 0 :(得分:3)

我不认为这是一个OpenGL问题。代码只是使用未初始化的指针。如果用于任何事情,这可能会导致崩溃。它恰好是传递给glBufferData()

的情况

通过使用vertexData,它被声明为指向GLfloat的指针:

GLfloat **vertexData;

然后分配:

vertexData = new GLfloat*[mesh_size];

vertexData现在指向mesh_size指针GLfloat。请注意,这些指针未初始化。

然后将这些指针作为参数传递给函数:

przepare_mesh(..., vertexData[i], ...);

在函数内部,然后为函数参数赋值(我正在重命名原始代码中的参数,以避免在我的解释中出现名称混淆):

void przepare_mesh(..., GLfloat* vertices, ...)
{
    ...
    vertices = (GLfloat *)&paiMesh->mVertices;

由于指针是按值传递给函数的,因此该赋值仅更改参数的本地值,并且不为最初传入的指针设置值。因此vertexData[i]仍将是未初始化的当这个函数返回时。

稍后,vertexData[i]被用作glBufferData()的参数,并导致崩溃,因为它未初始化。

解决此问题的最简单方法是将函数参数的声明更改为引用:

void przepare_mesh(..., GLfloat*& vertices, ...)

一旦参数是引用,在函数内部为它赋值将改变调用者传入的指针的值。

代码中还有其他相同问题的情况,我只是用第一个来说明问题。