非常大的背景纹理

very large background textures

对于我正在开发的游戏,我必须使用大背景图像。这些图像大约为 5000x3000。当试图将其显示为单个纹理时,我会在 GWT 和 Android 中得到黑框。我创建了一个 class 将图像拆分为纹理网格:

public class LargeImage extends LoadableGroup {
private boolean smooth=true;
public String filename;
private int trueWidth,trueHeight;
private ArrayList<Image> tiles=new ArrayList<Image>();
private ArrayList<Texture> textures=new ArrayList<Texture>();
private final int maxTextureSize = 512;
public LargeImage(String filename, CallbackAssetManager manager)
{
    super();
    this.filename=filename;

    PixmapParameter param=new PixmapParameter();
    param.format=Pixmap.Format.RGBA8888;
    addAsset(new AssetDescriptor(filename, Pixmap.class,param));

    manager.add(this);
}
public LargeImage(Pixmap map, boolean smooth)
{
    super();
    this.smooth=smooth;
    fromPixMap(map);
}

public void loaded(CallbackAssetManager manager)
{
    if(!manager.isLoaded(filename))
    {
        Gdx.app.log("Load Error",filename);
        return;
    }
    Pixmap source = manager.get(filename, Pixmap.class);
    fromPixMap(source);

}
private void fromPixMap(Pixmap source)
{


    for (int x = 0;x < source.getWidth(); x+=maxTextureSize) {
        for (int y = 0;y < source.getHeight(); y+=maxTextureSize) {
            Pixmap p = new Pixmap(maxTextureSize, maxTextureSize, Pixmap.Format.RGBA8888);
            p.drawPixmap(source, 0, 0, x, y, maxTextureSize, maxTextureSize);
            Texture t=new Texture(new PixmapTextureData(p, Pixmap.Format.RGBA8888, true, false, true));
            textures.add(t);
            if(smooth)
                t.setFilter(Texture.TextureFilter.MipMapLinearNearest, Texture.TextureFilter.Linear);
            UncoloredImage tile = new UncoloredImage(t);
            tile.setTouchable(Touchable.disabled);
            tile.setX(x);
            tile.setY(source.getHeight()-y-tile.getHeight());
            p.dispose();
            this.addActor(tile);
            tiles.add(tile);

        }
    }        
    super.setWidth(source.getWidth());
    super.setHeight(source.getHeight());
    trueWidth=source.getWidth();
    trueHeight=source.getHeight();
}



@Override
public void setWidth(float width) {
    setScaleX(width/trueWidth);
    super.setWidth(Math.abs(width));
}
public void setHeight(float height) {
    setScaleY(height / (float)trueHeight);
    super.setHeight(Math.abs(height));
}

@Override
public void dispose(CallbackAssetManager m) {
    super.dispose(m);
    for(int i=0;i<textures.size();i++)
        textures.get(i).dispose();
}
}

当我需要加载其他关卡时,问题就来了。大约 6 次加载后,我得到 GL 或内存错误。我保留对我创建的每个纹理的引用,并在加载新关卡时处理所有内容。为什么即使我处理了旧纹理,我还是 运行 内存不足?

也许有 make 处理这部分 "source":

Pixmap source = manager.get(filename, Pixmap.class);
    fromPixMap(source);

也许有帮助you.if你不用多

我发现了问题。我忘了处理 1x1 背景填充。我忘记了我使用 class 通过发送 Pixmap 来创建 1x1 图像。 1x1 被转换为 512x512 并且通过关卡不断累积直到达到极限。我为正在创建的背景填充图像添加了一个处置,并解决了整个问题。

我还更新了图块生成器以使用所需的最小纹理尺寸,并且也达到了 GL_MAX_TEXTURE_SIZE。这样 1x1 图像实际上是 1x1,而 5000x3000 的图块更少,具体取决于图形硬件。这是新代码:

public class LargeImage extends LoadableGroup {
private boolean smooth=true;
public String filename;
public int trueWidth,trueHeight;
private ArrayList<Image> tiles=new ArrayList<Image>();
private ArrayList<Texture> textures=new ArrayList<Texture>();
private int maxTextureSize;
public LargeImage(String filename, CallbackAssetManager manager)
{
    super();
    this.filename=filename;
    PixmapParameter param=new PixmapParameter();
    param.format=Pixmap.Format.RGBA8888;
    addAsset(new AssetDescriptor(filename, Pixmap.class,param));
    manager.add(this);
}
public LargeImage(Pixmap map, boolean smooth)
{
    super();
    this.smooth=smooth;
    fromPixMap(map);
}

public void draw(Batch batch, float parentAlpha)
{
    //setCullingArea(new Rectangle(0,0,200,200));
    batch.setColor(getColor());
    super.draw(batch,parentAlpha);
}
public void loaded(CallbackAssetManager manager)
{
    if(!manager.isLoaded(filename))
    {
        Gdx.app.log("Load Error",filename);
        return;
    }
    Pixmap source = manager.get(filename, Pixmap.class);
    fromPixMap(source);

}
private void fromPixMap(Pixmap source)
{
    if(Gdx.app.getType()== Application.ApplicationType.WebGL)
        maxTextureSize=512;
    else
        maxTextureSize=Gdx.gl.GL_MAX_TEXTURE_SIZE;
    for (int x = 0;x < source.getWidth(); x+=maxTextureSize) {
        for (int y = 0;y < source.getHeight(); y+=maxTextureSize) {
            int tSize=getTextureSize(source.getWidth()-x,source.getHeight()-y);
            Pixmap p = new Pixmap(tSize, tSize, Pixmap.Format.RGBA8888);
            p.drawPixmap(source, 0, 0, x, y, tSize, tSize);
            Texture t=new Texture(new PixmapTextureData(p, Pixmap.Format.RGBA8888, true, false, true));
            textures.add(t);

            if(smooth)
                t.setFilter(Texture.TextureFilter.MipMapLinearNearest, Texture.TextureFilter.Linear);
            UncoloredImage tile = new UncoloredImage(t);
            tile.setTouchable(Touchable.disabled);
            tile.setX(x);
            tile.setY(source.getHeight()-y-tile.getHeight());
            p.dispose();
            this.addActor(tile);
            tiles.add(tile);

        }
    }
    super.setWidth(source.getWidth());
    super.setHeight(source.getHeight());
    trueWidth=source.getWidth();
    trueHeight=source.getHeight();
}
public int getTextureSize(int width, int height)
{
    int n=Math.max(width,height);
    if(n>=maxTextureSize)
        return maxTextureSize;
    n--;
    n |= n >> 1;
    n |= n >> 2;
    n |= n >> 4;
    n |= n >> 8;
    n |= n >> 16;
    n++;
    return n;
}


@Override
public void setWidth(float width) {
    setScaleX(width/trueWidth);
    super.setWidth(Math.abs(width));
}
public void setHeight(float height) {
    setScaleY(height / (float)trueHeight);
    super.setHeight(Math.abs(height));
}

@Override
public void dispose(CallbackAssetManager m) {

    super.dispose(m);
    for(int i=0;i<textures.size();i++) {
        textures.get(i).dispose();
    }

}

public void softDispose(CallbackAssetManager m) {
    for(int i=0;i<textures.size();i++) {
        textures.get(i).dispose();
    }

}
}