首页 文章

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

提问于
浏览
-1

问题: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 - >通过来自3DS文件的assimp.importer数据加载并提取有关每个网格的索引,颜色,顶点,法线的数据

函数渲染 - >加载数据:关于索引,颜色,顶点,法线的数据

但是当它将数据加载到缓冲区“glBufferData”SegFault时会导致一些问题

Additioanl_func.cpp用于加载着色器和鼠标回调的额外函数

哪里有问题?

1 回答

  • 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, ...)
    

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

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

相关问题