2011-04-18 56 views
10

我有一個應用程序,我一直在android中一直玩,它使用opengl-es。Android Opengl-es加載2紋理的非電源

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

//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中初始化沒有數據的紋理?

在這個問題previously asked建議調用glTexImage2D()沒有數據,然後填寫它。

但是在android中調用「GLUtils.texImage2D(GL10.GL_TEXTURE_2D,0,bmp,0);」你不指定寬度/高度。它從我假設的位圖中讀取。

這樣做的最好方法是什麼?我可以創建一個新的2位大小權利的位圖,只有空白,沒有填充任何數據,並使用它來初始化紋理,然後使用subImage粘貼到它?或者我應該創建一個新的位圖以某種方式將我想要的像素(不確定是否可以輕鬆地執行此操作)複製到此新位圖(離開邊界),然後使用它?

編輯:澄清我正在使用opengl。

回答

4

我想如果你嘗試創建一個2軸大小的位圖的位圖,然後添加你的位圖,它應該工作得很好。也許類似

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

除此之外,我會說,通過Photoshop的過程中受苦。你有多少張照片?

+0

沒有太多,只是我們希望能在以後的日子裏改變它們,如果調整大小做的很好,它會變得更容易!這種方法說它需要nonPOTBitmap的一個子集,這是否意味着如果子集位圖小於指定的xSize和ySize,它會有空白邊緣?還是會拉伸它? (我會嘗試,但可悲的是不在我的編碼電腦)。 – iexus 2011-04-19 16:16:44

+0

除非將它們扔到createScaledBitmap方法,否則位圖不應伸展。剩餘的空間將是空的。 – AedonEtLIRA 2011-04-20 02:19:33

+0

對不起,延遲迴復,我已經與其他事情一起,但是我到處去實際執行這個,它不能通過這種方法工作。你不能將一個位圖分成一個比它看起來更大尺寸的位圖...我現在處於一個不知所措的狀態。 – iexus 2011-05-05 15:55:10

2

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

你可以做的一件事就是創建一個兩倍大小的封裝紋理,然後使用glTexSubimage2D上傳紋理以僅覆蓋其中的一部分,然後相應地調整紋理座標。這個明顯的缺點是你不能在這種情況下使用紋理包裝。如果您絕對必須支持包裝,您可以在調用glTexImage2D之前將您的紋理調整到最接近2的冪的大小,儘管這通常會引入取樣僞像並使事情變得模糊,尤其是如果您嘗試執行像素精確的2D工作。

如果你不需要支持包裝,你可能會考慮的另一件事是創建一個「紋理地圖集」,在其中你將所有的紋理壓縮成幾個大的紋理,並且你的多邊形只映射到紋理圖譜的一些部分。生成MIPmaps時必須小心,但除此之外,它通常會提供相當不錯的性能優勢,並且可以更有效地使用紋理內存,因爲您不會在填充或縮放的圖像上浪費太多空間。

+0

正如我的問題所述,雖然你如何在Android中創建一個包裝紋理,你進入了樣品?什麼是最好的方法來做到這一點? – iexus 2011-04-29 13:04:59

+0

查看glTexSubimage2D的文檔。 – fluffy 2011-06-03 16:59:44

0

呃爲什麼你不創建兩個位圖。加載第一個,然後使用createBitmapScaled將該位圖轉換爲二的冪。性能方面我不知道這是否是最快的方法,但它可行。

2

我有兩個解決方案,我用這個問題。我可以在必要時更具體的,但在概念上,您可以: -

  1. 使圖像2的冪,以及部分裁剪您填寫100%的alpha通道,並啓用阿爾法加載圖像。

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

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

作爲基質(顯然這是用於將圖像加載到一個2平方triangled),因子回由比要裁剪的區域,例如。

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

,是精確,你的數學或惡意位可能出血的,否則你會切出一些真正的形象。很顯然,這個數組是在即時計算的,而不是像我在這裏展示的那樣進行硬編碼。

0

您可以使用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; 
}