Search code examples
c++opengllibrariesopengl-3stb-image

Access violation in nvoglv64.dll when using OpenGL


My code is giving me this error:

Exception thrown at 0x00007FFCF428A6CF (nvoglv64.dll) in program.exe: 0xC0000005: Access violation reading location 0x000001D6B603F000.

In the debug output window of Visual Studio I also see pdb not loaded for the nvoglv64.dll file.

since i've added this code to my openGL app:

data = stbi_load("src/pickaxe.png", &width, &height, &nrChannels, 0);
if (!data) {
        std::cout << "swords image loaded incorrectly " << std::endl;
    }
    else {
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
        glGenerateMipmap(GL_TEXTURE_2D);
    }

Is it caused because of loading the image or by function GLTEXIMAGE_2D ? Here is my full code:

    #include <glad/glad.h>
#include <GLFW/glfw3.h>
#include <iostream>
#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"

// global variables
int p_WIDTH = 1280;
int p_HEIGHT = 960;
int succes;
char info[512];
// buffers


// shader sources
const char* vertexShaderSource =
"#version 330 core\n"
"layout(location = 0)in vec3 _verts;\n"
"layout(location = 1)in vec2 _texCoords;\n"
"out vec2 texCoords;\n"
"void main(){\n"
"gl_Position = vec4(_verts, 1.0f);\n"
"texCoords = _texCoords;\n"
"};\0"
;

const char* fragmentShaderSource =
"#version 330 core\n"
"in vec2 texCoords;\n" 
"out vec4 fragColor;\n"
"uniform sampler2D _texture1;\n"
"uniform sampler2D _texture2;\n"
"void main(){\n"
"fragColor = mix(texture(_texture1, texCoords), texture(_texture2, texCoords), 0.5f);\n"
"};\0"
;


// functions
void window_resize_callback(GLFWwindow* window, int width, int height) {
    glViewport(0, 0, width, height);
}


int main() {
    glfwInit();
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); 
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
    glfwWindowHint(GLFW_OPENGL_ANY_PROFILE, GLFW_OPENGL_CORE_PROFILE);
    GLFWwindow* window = glfwCreateWindow(p_WIDTH, p_HEIGHT, "getting_started_completed", NULL, NULL);
    glfwMakeContextCurrent(window);
    glfwSetFramebufferSizeCallback(window, window_resize_callback);
    if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
    {
        std::cout << "Failed to initialize GLAD" << std::endl;
        return -1;
    }

    // shaders 
    GLuint vertexShader, fragmentShader;
    vertexShader = glCreateShader(GL_VERTEX_SHADER);
    glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);
    glCompileShader(vertexShader);
    glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &succes);
    if (!succes) {
        glGetShaderInfoLog(vertexShader, 512, NULL, info);
        std::cout << "VERTEX_SHADER_COMP_ERROR: " << info << std::endl;
    }

    fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
    glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);
    glCompileShader(fragmentShader);
    glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &succes);
    if (!succes) {
        glGetShaderInfoLog(fragmentShader, 512, NULL, info);
        std::cout << "FRAGMENT_SHADER_COMP_ERROR: " << info << std::endl;
    }

    GLuint program = glCreateProgram();
    glAttachShader(program, vertexShader);
    glAttachShader(program, fragmentShader);
    glLinkProgram(program);
    glGetProgramiv(program, GL_COMPILE_STATUS, &succes);
    if (!succes) {
        glGetProgramInfoLog(program, 512, NULL, info);
        std::cout << "PROGRAM_LINK_ERROR: " << info << std::endl;
    }
    glDeleteShader(vertexShader);
    glDeleteShader(fragmentShader);

    // vertices
    float vertices[] = {
        -0.5f, -0.5f, 0.f,      0,0,    // 0  
        0.5f, -0.5f, 0.f,       1,0,    // 1
        0.5f, 0.5f, 0.f,        1,1,    // 2
        -0.5f, 0.5f, 0.f,       0,1     // 3
    };

    unsigned int indices[] = {
        0,1,2,
        0,2,3
    };
    
    // buffers etc.
    GLuint vbo, vao, ebo;
    glGenVertexArrays(1, &vao);
    glGenBuffers(1, &vbo);
    glGenBuffers(1, &ebo);

    glBindVertexArray(vao);
    glBindBuffer(GL_ARRAY_BUFFER, vbo);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);

    glEnableVertexAttribArray(0);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5*sizeof(float), (void*)0);
    glEnableVertexAttribArray(1);
    glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(3 * sizeof(float)));

    // textures
    unsigned int texture1, texture2;
    glGenTextures(1, &texture1);
    glBindTexture(GL_TEXTURE_2D, texture1);

    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);

    int width, height, nrChannels;
    stbi_set_flip_vertically_on_load(true);
    unsigned char* data = stbi_load("src/dirt.jpg", &width, &height, &nrChannels, 0);
    if (!data) {
        std::cout << "dirt image loaded incorectly " << std::endl;
    }
    else {
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
        glGenerateMipmap(GL_TEXTURE_2D);
    }
    stbi_image_free(data);

    glGenTextures(1, &texture2);
    glBindTexture(GL_TEXTURE_2D, texture2);
    
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    
    data = stbi_load("src/pickaxe.png", &width, &height, &nrChannels, 0);
    
    if (!data) {
        std::cout << "swords image loaded incorrectly " << std::endl;
    }
    else {
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
        glGenerateMipmap(GL_TEXTURE_2D);
    }   

    glUseProgram(program);
    glUniform1i(glGetUniformLocation(program, "_texture1"), 0);
    glUniform1i(glGetUniformLocation(program, "_texture2"), 1);


    while (!glfwWindowShouldClose(window)) {

        glClearColor(0.f, 0.1f, 0.1f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT);       

        glActiveTexture(GL_TEXTURE0);
        glBindTexture(GL_TEXTURE_2D, texture1);
        glActiveTexture(GL_TEXTURE1);
        glBindTexture(GL_TEXTURE_2D, texture2);

        glUseProgram(program);

        glBindVertexArray(vao);
        glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);


        glfwPollEvents();
        glfwSwapBuffers(window);
    }
    glDeleteVertexArrays(1, &vao);
    glDeleteBuffers(1, &vbo);
    glDeleteBuffers(1, &ebo);

    glfwTerminate();
    //std::cin.get();
    return 0;
}

Solution

  • You want to load and image with 4 channels (GL_RGBA). There is no guarantee that the STB library generates an image with 4 channels. The actual number of channels is returned by the 4th argument of stbi_load. If the image doesn't have 4 channels, the subsequent call of glTexImage2D expects a larger buffer than you actually provide. That causes the access violation.
    To solve the problem, you can force stbi_load to generate an image with 4 color channels by explicitly passing 4 as the last parameter:

    data = stbi_load("src/pickaxe.png", &width, &height, &nrChannels, 4);