重用opengl纹理

时间:2015-03-12 12:28:34

标签: c++ opengl opengl-es

我正在尝试自学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删除此纹理并每次生成新纹理?

1 个答案:

答案 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