代码之家  ›  专栏  ›  技术社区  ›  DavidG

OpenGL子文本

  •  8
  • DavidG  · 技术社区  · 17 年前

    我有图像数据,我想得到它的子图像作为OpenGL纹理使用。

    glGenTextures(1, &m_name);
    glGetIntegerv(GL_TEXTURE_BINDING_2D, &oldName);
    glBindTexture(GL_TEXTURE_2D, m_name);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_width, m_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, m_data);
    

    我怎样才能得到一个加载为纹理的图像的子图像。我认为它与使用gltexsubimage2d有关,但我不知道如何使用它来创建一个可以加载的新纹理。打电话:

    glTexSubImage2D(GL_TEXTURE_2D, 0, xOffset, yOffset, xWidth, yHeight, GL_RGBA, GL_UNSIGNED_BYTE, m_data);
    

    什么也看不到,调用glcopyTexSubImage2d只是我的frameBuffer的一部分。 谢谢

    2 回复  |  直到 7 年前
        1
  •  28
  •   Mike F    17 年前

    编辑: 使用glpixelstorei。你用它来设定 GL_UNPACK_ROW_LENGTH 整个图像的宽度(像素)。然后调用glteximage2d(或其他),将指针传递给子图像的第一个像素以及子图像的宽度和高度。

    别忘了恢复 GL U解包\行\长度 完成后返回0。

    Ie:

    glPixelStorei( GL_UNPACK_ROW_LENGTH, img_width );
    char *subimg = (char*)m_data + (sub_x + sub_y*img_width)*4;
    glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, sub_width, sub_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, subimg );
    glPixelStorei( GL_UNPACK_ROW_LENGTH, 0 );
    

    或者,如果你对指针数学过敏:

    glPixelStorei( GL_UNPACK_ROW_LENGTH, img_width );
    glPixelStorei( GL_UNPACK_SKIP_PIXELS, sub_x );
    glPixelStorei( GL_UNPACK_SKIP_ROWS, sub_y );
    
    glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, sub_width, sub_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, m_data );
    
    glPixelStorei( GL_UNPACK_ROW_LENGTH, 0 );
    glPixelStorei( GL_UNPACK_SKIP_PIXELS, 0 );
    glPixelStorei( GL_UNPACK_SKIP_ROWS, 0 );
    

    编辑2: 为了完整起见,我应该指出,如果您使用的是OpenGLES,那么您不会 GL U解包\行\长度 . 在这种情况下,您可以(a)自己将子映像提取到一个新的缓冲区中,或者(b)…

    glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, sub_width, sub_height, 0, GL_RGBA, GL_UNSIGNED_BYTES, NULL );
    
    for( int y = 0; y < sub_height; y++ )
    {
        char *row = m_data + ((y + sub_y)*img_width + sub_x) * 4;
        glTexSubImage2D( GL_TEXTURE_2D, 0, 0, y, sub_width, 1, GL_RGBA, GL_UNSIGNED_BYTE, row );
    }
    
        2
  •  4
  •   vedranm    8 年前

    对于那些被困的人 OpenGL ES 1.1/2.0版 2018年及以后,我用不同的方法做了一些测试,如何从图像数据中更新部分纹理(图像与纹理大小相同)。

    方法1: 复制整个图像 GLTEXIGE2D :

    glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, mWidth, mHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, m_Pixels );
    

    方法2: 复制整个图像 格子亚图像2D :

    glTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, mWidth, mHeight, GL_RGBA, GL_UNSIGNED_BYTE, m_Pixels );
    

    方法3: 在循环中逐行复制图像部件:

    auto *ptr = m_Pixels + (x + y * mWidth) * 4;
    for( int i = 0; i < h; i++, ptr += mWidth * 4 ) {
        glTexSubImage2D( GL_TEXTURE_2D, 0, x, y+i, w, 1, GL_RGBA, GL_UNSIGNED_BYTE, ptr );
    }
    

    方法4: 复制图像的整个宽度,但只垂直复制已更改的部分:

    auto *ptr = m_Pixels + (y * mWidth) * 4;
    glTexSubImage2D( GL_TEXTURE_2D, 0, 0, y, mWidth, h, GL_RGBA, GL_UNSIGNED_BYTE, ptr );
    

    下面是在PC机上进行的测试结果,通过100000次更新纹理的不同部分,这些部分大约是整个纹理的1/5大小。

    • 方法1-38.17秒
    • 方法2-26.09秒
    • 方法3-54.83秒-最慢
    • 方法4-5.93秒- 赢家

    不足为奇,方法4速度最快,因为它只复制图像的一部分,并且只调用gltex…()函数。

    推荐文章