自定义 OpenGL 缓冲区类不显示任何内容
Posted
技术标签:
【中文标题】自定义 OpenGL 缓冲区类不显示任何内容【英文标题】:Custom OpenGL buffer class doesn't display anything 【发布时间】:2016-06-28 23:48:03 【问题描述】:我想创建一个类来处理 OpenGL 缓冲区,例如顶点缓冲区对象或颜色缓冲区。
这里是缓冲区.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。
【问题讨论】:
在minimal reproducible example 中编辑。据我们所知,您处于核心环境中并且忘记了 VAO。 另外,在大多数平台上,glBuffer::setdata()
中的sizeof(data)
将是4
或8
,而不是您希望的data
的长度。传入单独的size
参数或使用std::array<>
/std::vector<>
之类的容器。
【参考方案1】:
这是设置缓冲区数据的工作代码
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。
【讨论】:
谢谢!我设法让它使用向量工作。真的很酷! 无论您使用哪种方法,您都可以随时打印尺寸并验证其正确性。 @genpfault 在较早的评论中建议使用std::vector
。一旦有人理解为什么一段代码不能按预期工作,从那里就很容易了。祝你好运。
是的,这很容易。对于我使用我定义的 T 模板的 data.size()*sizeof(T) 的大小:)以上是关于自定义 OpenGL 缓冲区类不显示任何内容的主要内容,如果未能解决你的问题,请参考以下文章