c++ - 自定义 OpenGL 缓冲类不显示任何内容

标签 c++ opengl glfw glew

我想创建一个类来处理 OpenGL 缓冲区,例如顶点缓冲区对象或颜色缓冲区。

这里是 buffer.h:

#pragma once
#include <GL/glew.h>

class glBuffer
{
public:
    glBuffer(GLenum target);
    void setdata(const void *data, GLenum mode);
    void bind(GLuint index, GLint valuePerVertex, GLenum variableType = GL_FLOAT, GLsizei stride = 0, int offset = 0);
    void unbind();
    GLuint getBufferID() const;
    ~glBuffer();

private:
    bool m_active;
    GLuint m_buffer;
    GLuint m_index;
    GLenum m_target;
};

和buffer.cpp:

#include "buffer.h"
#include <GL/glew.h>
#include <iostream>


glBuffer::glBuffer(GLenum target)
{
    m_target = target;
    m_active = false;
    glGenBuffers(1, &m_buffer);
}

void glBuffer::setdata(const void *data, GLenum mode)
{
    glBindBuffer(m_target, m_buffer);
    glBufferData(m_target, sizeof(data), data, mode);
    glBindBuffer(m_target, 0);
}

void glBuffer::bind(GLuint index, GLint valuePerVertex, GLenum variableType, GLsizei stride, int offset)
{
    m_active = true;
    m_index = index;
    glEnableVertexAttribArray(m_index);
    glBindBuffer(m_target, m_buffer);
    glVertexAttribPointer(
        m_index,
        valuePerVertex,     
        variableType,       
        GL_FALSE,           //normalized?
        stride,             
        (void*)offset       //buffer offset
    );
}

void glBuffer::unbind()
{   
    m_active = false;
    glBindBuffer(m_target, 0);
    glDisableVertexAttribArray(m_index);
}

GLuint glBuffer::getBufferID() const
{
    return m_buffer;
}


glBuffer::~glBuffer()
{
    if (!m_active){
        unbind();
    }
    glDeleteBuffers(1, &m_buffer);
}

这是我在我的应用程序中使用它的方法,我在其中 #include "buffer.h" :

glBuffer vbo(GL_ARRAY_BUFFER);
vbo.setdata(color_buffer_data, GL_STATIC_DRAW);
vbo.bind(0, 3);

替换:

GLuint vbo;
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertex_buffer_data), vertex_buffer_data, GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glVertexAttribPointer(
    0,                  // attribute 0. No particular reason for 0, but must match the layout in the shader.
    3,                  // size
    GL_FLOAT,           // type
    GL_FALSE,           // normalized?
    0,                  // stride
    (void*)0            // array buffer offset
);

当我编译并运行它时,我得到一个没有绘制任何东西的黑色窗口。

发生了什么事?

PS:我用的是vs,glfw3,glew。

最佳答案

这是设置缓冲区数据的工作代码

glBufferData(GL_ARRAY_BUFFER, sizeof(vertex_buffer_data), vertex_buffer_data, GL_STATIC_DRAW);

我假设您的 vertex_buffer_data 是一个数组,这就是它起作用的原因。由于您将其转换为 void* ,因此您不能简单地在指针上调用 sizeof 。您需要的是整个数组的大小(以字节为单位)。

这是你的类中的函数,它不起作用

void glBuffer::setdata(const void *data, GLenum mode)
{
    glBindBuffer(m_target, m_buffer);
    glBufferData(m_target, sizeof(data), data, mode);
    glBindBuffer(m_target, 0);
}

这是因为 sizeof(data) 与第一种情况不同。正如@genpfault 所指出的,它是 4(32 位)或 8(64 位)。简单的解决方案是如下更改您的功能。

void glBuffer::setdata(const void *data, int numElements, size_t elementSize, GLenum mode)
{
    glBindBuffer(m_target, m_buffer);
    glBufferData(m_target, numElements * elementSize, data, mode);
    glBindBuffer(m_target, 0);
}

在此函数中,“numElements”是您的 void* 数据指向的数组中元素的数量,“elementSize”是每个元素的大小。

这是上述功能的示例代码

float vertex_buffer_data[9] = {0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f};
glBuffer vbo(GL_ARRAY_BUFFER);
vbo.setdata(vertex_buffer_data, 9, sizeof(float), GL_STATIC_DRAW);
vbo.bind(0, 3); 

它应该可以工作。如果您仍然感到困惑,这里有一个小示例程序来演示为什么您的代码不起作用。

#include "stdafx.h"

int _tmain(int argc, _TCHAR* argv[])
{
    int a[5] = {1, 2, 3, 4, 5};
    void* ptr = a;
    printf( " sizeof(a) = %d \n", sizeof(a));
    printf( " sizeof(a[0]) = %d \n", sizeof(a[0]));
    printf( " sizeof(ptr) = %d \n", sizeof(ptr));
    getchar();

    return 0;
}

输出:

sizeof(a) = 20 
sizeof(a[0]) = 4 
sizeof(ptr) = 4

注意:这是在 visual studio 中的 32 位 Windows 上编译的,因此指针大小为 4 个字节。如果我用 64 位编译它,它将是 8。

关于c++ - 自定义 OpenGL 缓冲类不显示任何内容,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38088057/

相关文章:

c++ - 使用 OpenGL 渲染的立方体在集成显卡上获得更高的帧速率

c - 显示某些内容需要 Mac OpenGL 窗口移动

c++ - 为什么 OpenGL GLFW 渲染形状不起作用?

c++ - 在 Objective-C 中使用宏记录函数名和行号

c++ - 在 OMNeT++ 中通过无线 channel 连接两个 UDP 模块

c++ - 使用 64 位编译器在 C++ 中读取 ini 文件

objective-c - cocoa OpenGL总是白色

python - 如何使用 opencv 和 opengl 获取面部网格?

c++ - 以 union 作为方法参数

c++ - 为 Sprite 混合设置 alpha 上限