重用 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