glDrawElements causes access violation reading location 0x0000000000000000

For context, this is on Windows and all OpenGL functions are either included from GL.h or the Kronos extension headers where I also have to use wglGetProcAddress. I am using VS Code as my editor and MSVC build tools as my compiler.

Here is an example of how I load my OpenGL 1.1+ functions:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code>// header file
inline PFNGLACTIVETEXTUREPROC glActiveTexture = nullptr;
...
// source file
glActiveTexture = reinterpret_cast<PFNGLACTIVETEXTUREPROC>(wglGetProcAddress("glActiveTexture"));
if (glActiveTexture == nullptr)
std::cerr << "Error: Failed to load glActiveTexture." << std::endl;
...
</code>
<code>// header file inline PFNGLACTIVETEXTUREPROC glActiveTexture = nullptr; ... // source file glActiveTexture = reinterpret_cast<PFNGLACTIVETEXTUREPROC>(wglGetProcAddress("glActiveTexture")); if (glActiveTexture == nullptr) std::cerr << "Error: Failed to load glActiveTexture." << std::endl; ... </code>
// header file
inline PFNGLACTIVETEXTUREPROC glActiveTexture = nullptr;
...

// source file
glActiveTexture = reinterpret_cast<PFNGLACTIVETEXTUREPROC>(wglGetProcAddress("glActiveTexture"));
if (glActiveTexture == nullptr)
    std::cerr << "Error: Failed to load glActiveTexture." << std::endl;
...

Now, for the problem. When I call glDrawElements I get this error message: Exception thrown at 0x00000204DBDFFF5A in Project.exe: 0xC0000005: Access violation reading location 0x0000000000000000. Also, glGetError returns 0.

Here is where in the code the error occurs:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code>void Renderer::render(const Texture& texture) {
texture.bind();
shader.setUniform("image", static_cast<GLint>(texture.unit - GL_TEXTURE0));
std::cout << glGetError() << std::endl;
glDrawElements(GL_TRIANGLES, elements.getCount(), GL_UNSIGNED_INT, nullptr);
}
</code>
<code>void Renderer::render(const Texture& texture) { texture.bind(); shader.setUniform("image", static_cast<GLint>(texture.unit - GL_TEXTURE0)); std::cout << glGetError() << std::endl; glDrawElements(GL_TRIANGLES, elements.getCount(), GL_UNSIGNED_INT, nullptr); } </code>
void Renderer::render(const Texture& texture) {
    texture.bind();
    shader.setUniform("image", static_cast<GLint>(texture.unit - GL_TEXTURE0));
    std::cout << glGetError() << std::endl;
    glDrawElements(GL_TRIANGLES, elements.getCount(), GL_UNSIGNED_INT, nullptr);
}

Here is where I assign the image data to the texture:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code>void Texture::setData(const std::string& file) {
bind();
stbi_set_flip_vertically_on_load(1);
int width, height, bpp;
stbi_uc* image = stbi_load(file.c_str(), &width, &height, &bpp, 0);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA,
GL_UNSIGNED_INT, image);
stbi_image_free(image);
}
</code>
<code>void Texture::setData(const std::string& file) { bind(); stbi_set_flip_vertically_on_load(1); int width, height, bpp; stbi_uc* image = stbi_load(file.c_str(), &width, &height, &bpp, 0); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_INT, image); stbi_image_free(image); } </code>
void Texture::setData(const std::string& file) {
    bind();

    stbi_set_flip_vertically_on_load(1);
    
    int width, height, bpp;
    stbi_uc* image = stbi_load(file.c_str(), &width, &height, &bpp, 0);
    
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA,
        GL_UNSIGNED_INT, image);

    stbi_image_free(image);
}

Here is how I set my vertex and element buffer data:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code>void VertexBuffer::addVertices(const std::vector<GLfloat>& vertices) {
bind();
glBufferData(GL_ARRAY_BUFFER,
static_cast<GLsizeiptr>(sizeof(GLfloat) * vertices.size()),
vertices.data(), GL_STATIC_DRAW);
}
void ElementBuffer::addElements(const std::vector<GLuint>& elements) {
bind();
count = static_cast<GLsizei>(elements.size());
glBufferData(GL_ELEMENT_ARRAY_BUFFER,
static_cast<GLsizeiptr>(sizeof(GLuint) * count), elements.data(),
GL_STATIC_DRAW);
}
</code>
<code>void VertexBuffer::addVertices(const std::vector<GLfloat>& vertices) { bind(); glBufferData(GL_ARRAY_BUFFER, static_cast<GLsizeiptr>(sizeof(GLfloat) * vertices.size()), vertices.data(), GL_STATIC_DRAW); } void ElementBuffer::addElements(const std::vector<GLuint>& elements) { bind(); count = static_cast<GLsizei>(elements.size()); glBufferData(GL_ELEMENT_ARRAY_BUFFER, static_cast<GLsizeiptr>(sizeof(GLuint) * count), elements.data(), GL_STATIC_DRAW); } </code>
void VertexBuffer::addVertices(const std::vector<GLfloat>& vertices) {    
    bind();
    glBufferData(GL_ARRAY_BUFFER,
        static_cast<GLsizeiptr>(sizeof(GLfloat) * vertices.size()),
        vertices.data(), GL_STATIC_DRAW);
}

void ElementBuffer::addElements(const std::vector<GLuint>& elements) {
    bind();
    count = static_cast<GLsizei>(elements.size());
    glBufferData(GL_ELEMENT_ARRAY_BUFFER,
        static_cast<GLsizeiptr>(sizeof(GLuint) * count), elements.data(),
        GL_STATIC_DRAW);
}

Here is how I assign vertex array data:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code>void BufferLayout::push(unsigned int count) {
layout.push_back(count);
}
size_t BufferLayout::getCount() const {
return layout.size();
}
unsigned int BufferLayout::getCount(size_t index) const {
if (index >= layout.size())
return 0;
return layout.at(index);
}
unsigned int BufferLayout::getStride() const {
unsigned int stride = 0;
for (unsigned int count : layout)
stride += count;
return stride;
}
unsigned int BufferLayout::getOffset(size_t index) const {
if (index >= layout.size())
return 0;
unsigned int offset = 0;
for (unsigned int i = 0; i < index; ++i)
offset += layout.at(i);
return offset;
}
void VertexArray::addBuffer(const VertexBuffer& vertices,
const BufferLayout& layout) {
bind();
vertices.bind();
for (size_t i = 0; i < layout.getCount(); ++i) {
glEnableVertexAttribArray(static_cast<GLuint>(i));
glVertexAttribPointer(static_cast<GLuint>(i),
static_cast<GLint>(layout.getCount(i)), GL_FLOAT, GL_FALSE,
static_cast<GLsizei>(sizeof(GLfloat) * layout.getStride()), i > 0 ?
reinterpret_cast<void*>(sizeof(GLfloat) * layout.getOffset(i)) :
nullptr);
}
}
</code>
<code>void BufferLayout::push(unsigned int count) { layout.push_back(count); } size_t BufferLayout::getCount() const { return layout.size(); } unsigned int BufferLayout::getCount(size_t index) const { if (index >= layout.size()) return 0; return layout.at(index); } unsigned int BufferLayout::getStride() const { unsigned int stride = 0; for (unsigned int count : layout) stride += count; return stride; } unsigned int BufferLayout::getOffset(size_t index) const { if (index >= layout.size()) return 0; unsigned int offset = 0; for (unsigned int i = 0; i < index; ++i) offset += layout.at(i); return offset; } void VertexArray::addBuffer(const VertexBuffer& vertices, const BufferLayout& layout) { bind(); vertices.bind(); for (size_t i = 0; i < layout.getCount(); ++i) { glEnableVertexAttribArray(static_cast<GLuint>(i)); glVertexAttribPointer(static_cast<GLuint>(i), static_cast<GLint>(layout.getCount(i)), GL_FLOAT, GL_FALSE, static_cast<GLsizei>(sizeof(GLfloat) * layout.getStride()), i > 0 ? reinterpret_cast<void*>(sizeof(GLfloat) * layout.getOffset(i)) : nullptr); } } </code>
void BufferLayout::push(unsigned int count) {
    layout.push_back(count);
}

size_t BufferLayout::getCount() const {
    return layout.size();
}

unsigned int BufferLayout::getCount(size_t index) const {
    if (index >= layout.size())
        return 0;
    return layout.at(index);
}

unsigned int BufferLayout::getStride() const {
    unsigned int stride = 0;
    for (unsigned int count : layout)
        stride += count;

    return stride;
}

unsigned int BufferLayout::getOffset(size_t index) const {
    if (index >= layout.size())
        return 0;

    unsigned int offset = 0;
    for (unsigned int i = 0; i < index; ++i)
        offset += layout.at(i);

    return offset;
}

void VertexArray::addBuffer(const VertexBuffer& vertices,
    const BufferLayout& layout) {    
    bind();
    vertices.bind();
    for (size_t i = 0; i < layout.getCount(); ++i) {
        glEnableVertexAttribArray(static_cast<GLuint>(i));
        glVertexAttribPointer(static_cast<GLuint>(i),
            static_cast<GLint>(layout.getCount(i)), GL_FLOAT, GL_FALSE,
            static_cast<GLsizei>(sizeof(GLfloat) * layout.getStride()), i > 0 ?
            reinterpret_cast<void*>(sizeof(GLfloat) * layout.getOffset(i)) :
            nullptr);
    }
}

Here is where I set up my OpenGL objects:
(This happens before any calls to glDrawElements)

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code>// header file
class Renderer {
...
private:
VertexArray vertices;
ElementBuffer elements;
Shader shader;
};
// source file
Renderer::Renderer() {
const std::vector<GLfloat> vertexData = {
-0.5f, -0.5f, 0.0f, 0.0f, 1.0f,
0.5f, -0.5f, 0.0f, 1.0f, 1.0f,
0.5f, 0.5f, 0.0f, 1.0f, 0.0f,
-0.5f, 0.5f, 0.0f, 0.0f, 0.0f
};
const std::vector<GLuint> elementData = {
0, 1, 2,
2, 3, 0
};
const std::string vertexShader = R"(
#version 330 core
layout (location = 0) in vec3 aPosition;
layout (location = 1) in vec2 aTexCoord;
out vec2 texCoord;
void main() {
gl_Position = vec4(aPosition, 1.0);
texCoord = aTexCoord;
}
)";
const std::string fragmentShader = R"(
#version 330 core
in vec2 texCoord;
out vec4 color;
uniform sampler2D image;
void main() {
color = texture(image, texCoord);
}
)";
VertexBuffer buffer;
buffer.addVertices(vertexData);
BufferLayout layout;
layout.push(3);
layout.push(2);
vertices.addBuffer(buffer, layout);
elements.addElements(elementData);
shader.compile(vertexShader, fragmentShader);
vertices.bind();
elements.bind();
shader.bind();
}
</code>
<code>// header file class Renderer { ... private: VertexArray vertices; ElementBuffer elements; Shader shader; }; // source file Renderer::Renderer() { const std::vector<GLfloat> vertexData = { -0.5f, -0.5f, 0.0f, 0.0f, 1.0f, 0.5f, -0.5f, 0.0f, 1.0f, 1.0f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, -0.5f, 0.5f, 0.0f, 0.0f, 0.0f }; const std::vector<GLuint> elementData = { 0, 1, 2, 2, 3, 0 }; const std::string vertexShader = R"( #version 330 core layout (location = 0) in vec3 aPosition; layout (location = 1) in vec2 aTexCoord; out vec2 texCoord; void main() { gl_Position = vec4(aPosition, 1.0); texCoord = aTexCoord; } )"; const std::string fragmentShader = R"( #version 330 core in vec2 texCoord; out vec4 color; uniform sampler2D image; void main() { color = texture(image, texCoord); } )"; VertexBuffer buffer; buffer.addVertices(vertexData); BufferLayout layout; layout.push(3); layout.push(2); vertices.addBuffer(buffer, layout); elements.addElements(elementData); shader.compile(vertexShader, fragmentShader); vertices.bind(); elements.bind(); shader.bind(); } </code>
// header file
class Renderer {
...
private:
    VertexArray vertices;
    ElementBuffer elements;
    Shader shader;
};

// source file
Renderer::Renderer() {
    const std::vector<GLfloat> vertexData = {
        -0.5f, -0.5f, 0.0f, 0.0f, 1.0f,
         0.5f, -0.5f, 0.0f, 1.0f, 1.0f,
         0.5f,  0.5f, 0.0f, 1.0f, 0.0f,
        -0.5f,  0.5f, 0.0f, 0.0f, 0.0f
    };

    const std::vector<GLuint> elementData = {
        0, 1, 2,
        2, 3, 0
    };

    const std::string vertexShader = R"(
        #version 330 core

        layout (location = 0) in vec3 aPosition;
        layout (location = 1) in vec2 aTexCoord;

        out vec2 texCoord;

        void main() {
            gl_Position = vec4(aPosition, 1.0);
            texCoord = aTexCoord;
        }
    )";

    const std::string fragmentShader = R"(
        #version 330 core

        in vec2 texCoord;

        out vec4 color;

        uniform sampler2D image;

        void main() {
            color = texture(image, texCoord);
        }
    )";

    VertexBuffer buffer;
    buffer.addVertices(vertexData);

    BufferLayout layout;
    layout.push(3);
    layout.push(2);

    vertices.addBuffer(buffer, layout);
    elements.addElements(elementData);
    shader.compile(vertexShader, fragmentShader);
    
    vertices.bind();
    elements.bind();
    shader.bind();
}

I’ve used the majority of this code, especially the wrapper classes for OpenGL, in other projects. I’ve never had this issue before. I’ve tried placing calls to glGetError() throughout the code as the issue continued but would always get a return value of 0. I am not sure what I am doing differently here that’s triggering it. I’d be happy to share more code if needed. Thank you in advance!

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa
Thiết kế website Thiết kế website Thiết kế website Cách kháng tài khoản quảng cáo Mua bán Fanpage Facebook Dịch vụ SEO Tổ chức sinh nhật