0
\$\begingroup\$

I am currently writing an OpenGL game engine, in which I am currently experiencing a crash every 1 out of 6 times. The error message with Visual Studio 2015 is:

Exception thrown at 0x545579C6 (nvoglv32.dll). Access violation reading location 0x085C2000.

It points to either the end of the main method, or this line of code in the OBJ Loader class:

return renderer::Model3D(
    final_vertices, final_uvs, final_normals, final_indices, position, shader);

I believe that it is a rendering issue on my behalf, relating to an Nvidia driver problem, or a GLFW/GLEW problem.

Here are the Renderer3D init, flush and submit methods:

void Batch::init(std::vector<const Model3D*> models) {
    glGenVertexArrays(1, &pr_VAO);
    glGenBuffers(1, &pr_VBO);

    glBindVertexArray(pr_VAO);
    glBindBuffer(GL_ARRAY_BUFFER, pr_VBO);
    glBufferData(GL_ARRAY_BUFFER, RENDERER_BUFFER_SIZE, NULL, GL_DYNAMIC_DRAW);

    glEnableVertexAttribArray(SHADER_VERTEX_INDEX);
    glEnableVertexAttribArray(SHADER_UV_INDEX);
    glEnableVertexAttribArray(SHADER_NORMAL_INDEX);

    glVertexAttribPointer(SHADER_VERTEX_INDEX, 3, GL_FLOAT, GL_FALSE,
            RENDERER_VERTEX_SIZE, (const GLvoid*)0);
    glVertexAttribPointer(SHADER_UV_INDEX, 2, GL_FLOAT, GL_FALSE,  RENDERER_VERTEX_SIZE, 
            (const GLvoid*)(offsetof(renderer::VertexData, renderer::VertexData::uv)));
    glVertexAttribPointer(SHADER_NORMAL_INDEX, 3, GL_FLOAT, GL_FALSE, 
            RENDERER_VERTEX_SIZE, (const GLvoid*)(3 * sizeof(GL_FLOAT)));

    for (const Model3D* model : models) {
        std::vector<unsigned short> indices = model->getIndices();

        pr_IBO = new buffers::IndexBuffer(indices, RENDERER_INDICIES_SIZE);
    }
    glBindBuffer(GL_ARRAY_BUFFER, 0);
}

void Batch::flush() {
    glBindVertexArray(pr_VAO);
    pr_IBO->bind();

    glDrawElements(GL_TRIANGLES, 128, GL_UNSIGNED_SHORT, NULL);

    pr_IBO->unbind();
    glBindVertexArray(0);

    indexCount = 0;
}

void Batch::submit(const renderer::Model3D* renderable) {
    std::vector<glm::vec3> vertices = renderable->getVertices();
    std::vector<glm::vec2> texCoords = renderable->getTexCoords();
    std::vector<glm::vec3> normals = renderable->getNormals();

    for (int i = 0; i < vertices.size(); i++) {
        pr_Buffer->vertex = vertices.at(i);
        pr_Buffer->uv = texCoords.at(i);
        pr_Buffer->normal = normals.at(i);
        pr_Buffer++;
    }

    indexCount += 6;
}

Here is the OBJLoader's LoadOBJ method:

renderer::Model3D OBJLoader::LoadOBJ
        (const char* filePath, glm::vec3 position, shaders::Shader& shader) {
    std::vector < glm::vec3 > temp_vertices;
    std::vector < glm::vec2 > temp_uvs;
    std::vector < glm::vec3 > temp_normals;
    std::vector < unsigned short> temp_indices;

    std::vector < glm::vec3 > out_vertices;
    std::vector < glm::vec2 > out_uvs;
    std::vector < glm::vec3 > out_normals;
    std::vector < unsigned short> out_indices;

    std::vector < glm::vec3 > final_vertices;
    std::vector < glm::vec2 > final_uvs;
    std::vector < glm::vec3 > final_normals;
    std::vector < unsigned short> final_indices;

    std::vector< unsigned int > vertexIndices, uvIndices, normalIndices;
    FILE * file = fopen(filePath, "r");

    if (file == NULL) {
        printf("Impossible to open the file!\n");
        getchar();
    }

    while (1) {
        char lineHeader[128];

        int res = fscanf(file, "%s", lineHeader);
        if (res == EOF)
            break; 

        if (strcmp(lineHeader, "v") == 0) {
            glm::vec3 vertex;
            fscanf(file, "%f %f %f\n", &vertex.x, &vertex.y, &vertex.z);
            temp_vertices.push_back(vertex);
        }
        else if (strcmp(lineHeader, "vt") == 0) {
            glm::vec2 uv;
            fscanf(file, "%f %f\n", &uv.x, &uv.y);
            uv.y = -uv.y; 
            temp_uvs.push_back(uv);
        }
        else if (strcmp(lineHeader, "vn") == 0) {
            glm::vec3 normal;
            fscanf(file, "%f %f %f\n", &normal.x, &normal.y, &normal.z);
            temp_normals.push_back(normal);
        }
        else if (strcmp(lineHeader, "f") == 0) {
            std::string vertex1, vertex2, vertex3;
            unsigned int vertexIndex[3], uvIndex[3], normalIndex[3];
            int matches = fscanf(file, "%d/%d/%d %d/%d/%d %d/%d/%d\n", &vertexIndex[0], 
                    &uvIndex[0], &normalIndex[0], &vertexIndex[1], &uvIndex[1], 
                    &normalIndex[1], &vertexIndex[2], &uvIndex[2], &normalIndex[2]);

            if (matches != 9) {
                printf("File can't be read\n");
            }

            vertexIndices.push_back(vertexIndex[0]);
            vertexIndices.push_back(vertexIndex[1]);
            vertexIndices.push_back(vertexIndex[2]);
            uvIndices.push_back(uvIndex[0]);
            uvIndices.push_back(uvIndex[1]);
            uvIndices.push_back(uvIndex[2]);
            normalIndices.push_back(normalIndex[0]);
            normalIndices.push_back(normalIndex[1]);
            normalIndices.push_back(normalIndex[2]);
        }
        else {
            char stupidBuffer[1000];
            fgets(stupidBuffer, 1000, file);
        }
    }

    for (unsigned int i = 0; i<vertexIndices.size(); i++) {
        unsigned int vertexIndex = vertexIndices[i];
        unsigned int uvIndex = uvIndices[i];
        unsigned int normalIndex = normalIndices[i];

        glm::vec3 vertex = temp_vertices[vertexIndex - 1];
        glm::vec2 uv = temp_uvs[uvIndex - 1];
        glm::vec3 normal = temp_normals[normalIndex - 1];

        out_vertices.push_back(vertex);
        out_uvs.push_back(uv);
        out_normals.push_back(normal);
    }

    indexVBO(out_vertices, out_uvs, out_normals, final_indices, 
            final_vertices, final_uvs, final_normals);

    return renderer::Model3D
            (final_vertices, final_uvs, final_normals, final_indices, position, shader);
    }
}

Finally, the main method:

int main() {
    Window window(800, 600, "Proton");
    Shader shader("src/shaders/vertexShader.txt", "src/shaders/fragmentShader.txt");
    shader.enable();

    shader.setUniform3f("lightPosition", glm::vec3(4, 3, 3));
    shader.setUniform3f("lightColour", glm::vec3(1, 1, 1));

    GLuint texture = Texture::loadImage("res/textures/texture.bmp");
    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D, texture);

    shader.setUniform1i("texture1", 0);

    Model3D model = 
            OBJLoader::LoadOBJ("res/models/cube.obj", glm::vec3(0, 0, 0), shader);

    std::vector<const Model3D*> models;

    models.push_back(&model);

    Batch renderer(models);

    std::cout << glGetError() << std::endl;

    while (!window.shouldClose()) {
        window.clear();

        glm::mat4 pr_matrix = 
                glm::perspective(glm::radians(70.0f), 800.0f / 600.0f, 0.1f, 100.0f);
        glm::mat4 vw_matrix = 
                glm::lookAt(glm::vec3(12, 9, 9), glm::vec3(0, 0, 0), glm::vec3(0, 1, 0));
        glm::mat4 matrix = glm::mat4(1.0f);

        shader.setUniformMat4("ml_matrix", matrix);

        shader.setUniformMat4("pr_matrix", pr_matrix);
        shader.setUniformMat4("vw_matrix", vw_matrix);

        renderer.begin();

        renderer.submit(&model);

        renderer.end();

        renderer.flush();

        window.update();
    }

    shader.disable();

    return 0;
}
\$\endgroup\$
  • 1
    \$\begingroup\$ >> "You're running a 32-bit app according to the DLL name. Does the same thing happen in a 64-bit version?" \$\endgroup\$ – Gnemlock Oct 9 '16 at 6:01
1
\$\begingroup\$

Access violations during glDrawArrays or glDrawElements are most often due to incorrectly enabled vertex attribute arrays. Please check your current state of the enabled vertex attributes very carefully. One which is left enabled inadvertently without providing any or enough data will result in these kinds of errors when sourcing data out of bounds during the draw call.

If that's not it, maybe there is some problem with memory consumption. You're running a 32-bit app according to the DLL name. Does the same thing happen in a 64-bit version?

\$\endgroup\$
  • 1
    \$\begingroup\$ Please keep in mind that answers are a bad place to ask for clarification. If you need clarification, ask in comments. \$\endgroup\$ – Gnemlock Oct 9 '16 at 6:01

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.