我正在尝试自学OpenGL,并希望重用opengl纹理。我想要做的是加载视频,然后将每个视频帧绑定到纹理,并在opengl窗口中显示它。我知道有一个Pixel Buffer Object可能更合适,但我的想法是学习OpenGL。
所以,我写了一个简单的C ++纹理类,如下所示:
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删除此纹理并每次生成新纹理?
答案 0 :(得分:2)
必须区分两件事:纹理对象本身和与之关联的图形内存。
如果您只想重用纹理对象,那么您的代码就可以了。但是这个代码在每次加载调用时都会分配(取决于实现)新内存,因为使用了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。