重用 opengl 纹理
reusing an opengl texture
我正在尝试自学 OpenGL 并希望重用 opengl 纹理。我想做的是加载一个视频,然后将每个视频帧绑定到一个纹理,然后在 opengl window 中显示它。我知道有一个像素缓冲区对象可能更合适,但我的想法是学习 OpenGL。
于是,我写了一个简单的C++纹理class如下:
class Texture
{
public:
Texture(GLenum target=GL_TEXTURE_2D);
~Texture();
void load(int rows, int cols, uchar * data);
protected:
GLenum _texture_target;
GLuint _texture_obj;
};
实现如下:
Texture::Texture(GLenum target)
{
_texture_target = target;
glGenTextures(1, &_texture_obj);
}
void Texture::load(int rows, int cols, uchar * data)
{
glBindTexture(_texture_target, _texture_obj);
glTexImage2D(_texture_target, 0, GL_BGRA, cols, rows, 0,
GL_BGRA, GL_UNSIGNED_BYTE, data);
glTexParameterf(_texture_target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterf(_texture_target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
}
我的问题是,当我获得后续视频帧时,我能否使用新帧数据调用我的 load() 函数,这是否会正确地重用纹理对象?这是使用纹理执行此操作的首选方法还是我应该使用 glDeleteTextures 删除此纹理并每次都生成新纹理?
必须区分两件事:纹理对象本身,以及与之关联的图形内存。
如果您只是想重用纹理对象,那么您的代码就可以了。但是由于使用了 glTexImage2D,此代码会在每次加载调用时分配(取决于实现)新内存。
如果您现在从一开始就认为纹理大小不会改变(视频就是这种情况),那么像这段代码这样的代码会更好。这里的区别在于,在纹理的初始化内存中被请求。在随后的加载调用中,仅更新此内存的内容,但不会请求新内存。
Texture::Texture(GLenum target, int rows, int cols)
{
_texture_target = target;
glGenTextures(1, &_texture_obj);
glBindTexture(_texture_target, _texture_obj);
glTexImage2D(_texture_target, 0, GL_BGRA, cols, rows, 0,
GL_BGRA, GL_UNSIGNED_BYTE, (GLvoid*)NULL);
glTexParameterf(_texture_target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterf(_texture_target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
}
void Texture::load(int rows, int cols, uchar * data)
{
glBindTexture(_texture_target, _texture_obj);
glTexSubImage2D(_texture_target, 0, 0, 0, cols, rows,
GL_BGRA, GL_UNSIGNED_BYTE, data);
}
有关详细信息,请查看 glTexSubImage2D。
我正在尝试自学 OpenGL 并希望重用 opengl 纹理。我想做的是加载一个视频,然后将每个视频帧绑定到一个纹理,然后在 opengl window 中显示它。我知道有一个像素缓冲区对象可能更合适,但我的想法是学习 OpenGL。
于是,我写了一个简单的C++纹理class如下:
class Texture
{
public:
Texture(GLenum target=GL_TEXTURE_2D);
~Texture();
void load(int rows, int cols, uchar * data);
protected:
GLenum _texture_target;
GLuint _texture_obj;
};
实现如下:
Texture::Texture(GLenum target)
{
_texture_target = target;
glGenTextures(1, &_texture_obj);
}
void Texture::load(int rows, int cols, uchar * data)
{
glBindTexture(_texture_target, _texture_obj);
glTexImage2D(_texture_target, 0, GL_BGRA, cols, rows, 0,
GL_BGRA, GL_UNSIGNED_BYTE, data);
glTexParameterf(_texture_target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterf(_texture_target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
}
我的问题是,当我获得后续视频帧时,我能否使用新帧数据调用我的 load() 函数,这是否会正确地重用纹理对象?这是使用纹理执行此操作的首选方法还是我应该使用 glDeleteTextures 删除此纹理并每次都生成新纹理?
必须区分两件事:纹理对象本身,以及与之关联的图形内存。
如果您只是想重用纹理对象,那么您的代码就可以了。但是由于使用了 glTexImage2D,此代码会在每次加载调用时分配(取决于实现)新内存。
如果您现在从一开始就认为纹理大小不会改变(视频就是这种情况),那么像这段代码这样的代码会更好。这里的区别在于,在纹理的初始化内存中被请求。在随后的加载调用中,仅更新此内存的内容,但不会请求新内存。
Texture::Texture(GLenum target, int rows, int cols)
{
_texture_target = target;
glGenTextures(1, &_texture_obj);
glBindTexture(_texture_target, _texture_obj);
glTexImage2D(_texture_target, 0, GL_BGRA, cols, rows, 0,
GL_BGRA, GL_UNSIGNED_BYTE, (GLvoid*)NULL);
glTexParameterf(_texture_target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterf(_texture_target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
}
void Texture::load(int rows, int cols, uchar * data)
{
glBindTexture(_texture_target, _texture_obj);
glTexSubImage2D(_texture_target, 0, 0, 0, cols, rows,
GL_BGRA, GL_UNSIGNED_BYTE, data);
}
有关详细信息,请查看 glTexSubImage2D。