簡體   English   中英

Android Opengl-es加載非2冪的紋理

[英]Android Opengl-es loading a non-power of 2 texture

我有一個在android中反復使用過的應用程序,它使用opengl-es。

目前,我從位圖加載紋理,如下所示:

//Load up and flip the texture - then dispose the temp
    Bitmap temp = BitmapFactory.decodeResource(Deflecticon.getContext().getResources(), resourceID);
    Bitmap bmp = Bitmap.createBitmap(temp, 0, 0, temp.getWidth(), temp.getHeight(), flip, true);
    temp.recycle();

    //Bind the texture in memory
    gl.glBindTexture(GL10.GL_TEXTURE_2D, id);

    //Set the parameters of the texture.
    gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_LINEAR);
    gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR);

    //On to the GPU
    GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bmp, 0);

明顯的問題是,我使用的紋理必須是2的冪。此刻,我正在photoshop中將紋理預編輯為2的冪,並且僅具有空邊框。 但是,這有點乏味,我希望能夠按原樣加載它們..認識到它們不是2的冪,然后將它們加載到紋理中。

我知道我可以將位圖縮放為2的冪並僅拉伸紋理,但我不希望拉伸紋理,在某些情況下可能希望將多個紋理放入一個“圖集”中。

我知道我可以使用glTexSubImage2D()將想要的數據粘貼到紋理中。 這很棒!

但是我不知道如何在Android中初始化沒有數據的紋理?

在此問題中, 先前提出的建議是調用沒有數據的glTexImage2D(),然后填充它。

但是在android中,當您調用“ GLUtils.texImage2D(GL10.GL_TEXTURE_2D,0,bmp,0);”時, 您未指定寬度/高度。 它從我假設的位圖讀取此內容。

做這個的最好方式是什么? 我可以創建一個正確的2冪次冪的新位圖,它只有空白並且沒有填充任何數據,然后使用它來初始化紋理,然后使用subImage粘貼到其中嗎? 還是我應該制作一個新的位圖,以某種方式將我想要的像素(不確定是否可以輕松地做到這一點)復制到這個新的位圖中(留有邊界),然后使用它?

編輯:闡明我正在使用opengl。

我認為,如果您嘗試使用2軸大小的力量創建一個位圖,然后添加您的位圖,它應該可以正常工作。 也許像

Bitmap.createBitmap(notPowerOf2Bitmap, offx, offy, xsize, ysize, bitmapFlag)

除此之外,我會說在Photoshop程序中受苦。 你有幾張照片?

在某些GLES平台上支持非2的冪(NPOT)位圖,但是您必須檢查是否存在適當的擴展名。 但是請注意,至少在PowerVR SGX上,即使支持NPOT,也仍然存在其他一些相當隨意的限制;請參見第5章。 例如,您的紋理寬度必須是2的倍數(如果不是2的冪)。 此外,在許多GPU上,NPOT渲染速度往往會稍慢一些。

您可以做的一件事就是創建一個包裝材質,它是2的冪次方,然后使用glTexSubimage2D上傳紋理以僅覆蓋其中一部分,然后相應地調整紋理坐標。 這樣做的明顯缺點是在這種情況下不能使用紋理包裹。 如果您絕對必須支持環繞,則可以在調用glTexImage2D之前將紋理縮放到最接近的2的冪次方,盡管這通常會引入采樣偽像並使事情變得模糊,特別是如果您嘗試進行像素精確的2D工作。

如果不需要支持包裝,您可能會考慮的另一件事是制作“紋理圖集”,其中將所有紋理壓縮為幾個大紋理,然后將多邊形映射到僅一部分紋理圖集。 生成MIP貼圖時必須要小心,但除此之外,它通常會提供相當不錯的性能優勢,並且由於您不會在填充或縮放的圖像上浪費太多,因此可以更有效地使用紋理內存。

我已經為這個問題采用了2個解決方案。 如果需要,我可以更具體一些,但從概念上講,您可以:-

  1. 使圖像的2次冪,並以100%alpha通道填充要裁剪的部分,並在啟用了alpha的情況下加載圖像。

  2. 調整您的紋理矢量/緩沖區,使其不會加載該部分。 因此,而不是使用默認

     float texture[] = { 0.0f, 1.0f, // 1.0f, 1.0f, // 0.0f, 0.0f, // 1.0f, 0.0f, // }; 

作為矩陣(顯然,這是為了將圖像加載到2個三角形的正方形),例如,按面積與作物的比例進行折算。

    float texture[] = { 
        0.0f, 0.75f, //
        0.9f, 0.75f, //
        0.0f, 0.0f, //
        0.9f, 0.0f, //
     };

當然,請精確計算數學,否則可能會滲入多余的部分,否則您將切掉一些真實的圖像。 顯然,此數組是即時計算的,並且不像我在此處演示的那樣進行硬編碼。

您可以使用GLES20.glTexImage2D()創建具有指定寬度和高度的空紋理。 示例代碼是

public static int genTexture(int texWidth, int texHeight) {
    int[] textureIds = new int[1];
    GLES20.glGenTextures(1, textureIds, 0);
    assertNoError();
    int textureId = textureIds[0];
    texWidth = Utils.nextPowerOf2(texWidth);
    texHeight = Utils.nextPowerOf2(texHeight);

    GLES20.glBindTexture(GL11.GL_TEXTURE_2D, textureId);
    GLES20.glTexParameteri(
            GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR);
    GLES20.glTexParameteri(
            GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR);
    GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D,
            GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE);
    GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D,
            GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE);

    GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGBA,
            texWidth, texHeight, 0, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, null);

    return textureId;
}

嗯,為什么不創建兩個位圖。 在執行操作時加載第一個,然后使用createBitmapScaled將該位圖轉換為2的冪。 在性能方面,我不知道這是否是最快的方法,但是它可以工作。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM