繁体   English   中英

OpenGL 瓷砖/Blitting/Clipping

[英]OpenGL Tiles/Blitting/Clipping

在 OpenGL 中,我如何从使用IMG_Load()加载的图像文件中 select 区域? (我正在为一个简单的 2D 游戏制作瓷砖地图)

我使用以下原理将图像文件加载到纹理中:

GLuint loadTexture( const std::string &fileName ) {

    SDL_Surface *image = IMG_Load(fileName.c_str());

    unsigned object(0);                        
    glGenTextures(1, &object);                 
    glBindTexture(GL_TEXTURE_2D, object);   

    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, image->w, image->h, 0, GL_RGBA, GL_UNSIGNED_BYTE, image->pixels);

    SDL_FreeSurface(image);
    return object;
}

然后我使用以下内容在我的渲染部分中实际绘制纹理:

glColor4ub(255,255,255,255);                
glBindTexture(GL_TEXTURE_2D, texture);      
glBegin(GL_QUADS);                          
glTexCoord2d(0,0);  glVertex2f(x,y);
glTexCoord2d(1,0);  glVertex2f(x+w,y);
glTexCoord2d(1,1);  glVertex2f(x+w,y+h);
glTexCoord2d(0,1);  glVertex2f(x,y+h);
glEnd(); 

现在我需要的是一个 function ,它允许我从GLuint中 select 某些矩形部分,这些部分是我通过调用loadTexture( const std::string &fileName )得到的,这样我就可以使用上面的代码将这些部分绑定到矩形,然后将它们绘制到屏幕上。 就像是:

GLuint getTileTexture( GLuint spritesheet, int x, int y, int w, int h )

Go 提前并将整个拼贴加载到纹理中。 然后 select 在渲染几何时使用glTexCoord的子集。

glTexSubImage2D不会有任何帮助。 它允许您将多个文件添加到单个纹理,而不是从单个文件创建多个纹理。

示例代码:

void RenderSprite( GLuint spritesheet, unsigned spritex, unsigned spritey, unsigned texturew, unsigned textureh, int x, int y, int w, int h )
{
    glColor4ub(255,255,255,255);                
    glBindTexture(GL_TEXTURE_2D, spritesheet);
    glBegin(GL_QUADS);                          
    glTexCoord2d(spritex/(double)texturew,spritey/(double)textureh);
    glVertex2f(x,y);
    glTexCoord2d((spritex+w)/(double)texturew,spritey/(double)textureh);
    glVertex2f(x+w,y);
    glTexCoord2d((spritex+w)/(double)texturew,(spritey+h)/(double)textureh);
    glVertex2f(x+w,y+h);
    glTexCoord2d(spritex/(double)texturew,(spritey+h)/(double)textureh);
    glVertex2f(x,y+h);
    glEnd(); 
}

尽管 Ben Voigt 的回答是 go 的常用方法,但如果您真的想要瓷砖的额外纹理(这可能有助于在边缘进行过滤),您可以使用glGetTexImage并使用glPixelStore参数进行一些操作:

GLuint getTileTexture(GLuint spritesheet, int x, int y, int w, int h)
{
    glBindTexture(GL_TEXTURE_2D, spritesheet);

    // first we fetch the complete texture
    GLint width, height;
    glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &width);
    glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &height);
    GLubyte *data = new GLubyte[width*height*4];
    glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);

    // now we take only a sub-rectangle from this data
    GLuint texture;
    glGenTextures(1, &texture);
    glBindTexture(GL_TEXTURE_2D, texture);
    glTexParameteri(GL_TEXTURE_2D, /*filter+wrapping*/, /*whatever*/);
    glPixelStorei(GL_UNPACK_ROW_LENGTH, width);
    glTexImage2D(GL_TEXTURE_2D, 0, RGBA, w, h, 0, 
        GL_RGBA, GL_UNSIGNED_BYTE, data+4*(y*width+x));

    // clean up
    glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
    delete[] data;
    return texture;
}

但请记住,这个 function 总是将整个纹理图集读入 CPU memory,然后将一个子部分复制到新的较小纹理中。 因此,最好在一个 go 中创建所有需要的精灵纹理,并且只读取一次数据。 在这种情况下,您也可以完全删除图集纹理,仅将图像读入系统 memory 并使用IMG_Load将其分配到各个精灵纹理中。 或者,如果你真的需要大纹理,那么至少使用 PBO 将其数据复制到(使用GL_DYNAMIC_COPY或类似的东西),所以它不需要离开 GPU memory。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM