2014-12-08 72 views
2

每當我想在opengl中使用mipmap時,我需要將最高分辨率的位圖上傳爲mipmap級別0,然後在較高的mipmap級別上傳較低分辨率的位圖。opengl:向紋理中添加更高分辨率的mipmapps

我本來希望能夠添加更高分辨率的mipmap以及更低分辨率的mipmap。目前我知道的唯一硬件方法是開始一個新的mipmap-ed紋理並重新上傳所有以前上傳的位圖。

任何其他硬件方式來做到這一點?

編輯:
看來GL_TEXTURE_BASE_LEVEL和GL_TEXTURE_MAX_LEVEL不會更改的OpenGL將分配內存在紋理製作所有質感紋理映射層級的事實,因此它不能在這種情況下使用,因爲它是不可能知道哪個紋理會需要更高分辨率的mipmap並且不會,所以會導致極大的內存浪費。

看起來,在硬件中執行此操作的唯一方法是使用新生成的mipmap級別爲0的較高分辨率mipmap重新創建新紋理,然後在較低mipmap級別複製所有先前較低分辨率的mipmap。

據我所知,唯一的辦法是將所有以前生成的mipmap級別保存在內存中,以防我需要重新上傳它們(而不是浪費這麼多內存),重新生成所有mipmap級別(不會做,太慢),使用gltexsubimage2d將以前的紋理mipmap級別複製到系統內存,然後將它們上傳到新紋理(這很慢),或者將它們從原紋理直接複製到新紋理。

那麼,有沒有辦法將紋理的選定mipmap複製到不同紋理的mipmap,如「glcopytexture(texture_id_1,texture_mipmap_1,texture_id_2,texture_mipmap_2);」

EDIT2:
似乎有幾分最近的擴展,這是否準確(https://www.opengl.org/wiki/Texture_Storage#Texture_copy),但本合同的要求之一是支持電腦長達10歲的(擴展〜2009年成爲〜2012年核心) 。

+1

它通常意味着驅動程序需要重新分配整個紋理,因爲它在創建低分辨率mipmap時沒有考慮到更高的分辨率 – 2014-12-08 00:30:38

+0

在這一點上,它很可能是以前的評論可能是唯一不會浪費紋理內存的硬件答案。我在我的最初問題中添加了一個跟蹤問題,並找到了信息。 – Marladu 2014-12-08 18:13:49

+0

@Marladu:實際上,對於真正的現代GPU,還有其他可能性,特別是[GL_ARB_sparse_texture](https://www.opengl.org/registry/specs/ARB/sparse_texture.txt)。這當然不是10年前的系統所需要的。 – derhass 2014-12-08 21:20:24

回答

1

沒有要求上傳完整的mipmap鏈以便使用紋理。您可以通過設置GL_TEXTURE_BASE_LEVELGL_TEXTURE_MAX_LEVEL來控制使用的電平範圍。

當您最初創建紋理時,您必須決定基本級別的大小[1]。但是,您可以推遲加載最低級別的數據,或者根本不加載它們。例如,假設你想要一個最大尺寸爲1024x1024的完整分辨率的紋理,但你知道你不需要0和1級,因爲它所用的對象距離攝像機很遠。您可以創建紋理開始2級:

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 2); 
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_LOD, 2); 
glTexImage2D(GL_TEXTURE_2D, 2, GL_RGBA8, 256, 256, 0, GL_RGBA, GL_UNSIGNED_BYTE, data); 
glGenerateMipmap(GL_TEXTURE_2D); 

然後,如果你以後決定您需要的質地一路現在平0:

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0); 
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_LOD, 0); 
glTexImage2D(GL_TEXTURE_2D, 2, GL_RGBA8, 1024, 1024, 0, GL_RGBA, GL_UNSIGNED_BYTE, data); 
glGenerateMipmap(GL_TEXTURE_2D); 

我不認爲設置GL_TEXTURE_MIN_LOD是必要的,但它不能傷害。在這兩種代碼序列中,您當然可以逐個提供您自己的mipmap,而不必調用glGenerateMipmap()

主要需要注意的是,您需要能夠指定大於0的數據。因此,您需要在運行時生成自己的mipmap,或者使用包含mipmap的預先烘焙的資源。

另外,即使您沒有爲這些級別指定數據,實現也可能決定將全部紋理分配到0級。所以你可能會也可能不會以這種方式節省內存。唯一能指望的是它加速了最初的紋理上傳。

[1]這並不嚴格,因爲對於給定的更高級別的大小,基礎級別有多個有效大小。例如,如果級別2的大小爲16,級別1的大小可以是32或33,級別0可以是64,65,66或67.

+0

這是超級有趣的,我不知道這個,謝謝!但是,還有什麼機會可以爲未使用的mipmaps分配內存?問題在於,我無法提前知道哪些紋理需要哪些mipmap級別,並且我可能想要改進很多紋理(即時生成紋理mipmap)。在我正在處理的應用程序中,一個示例是1000個紋理,大小爲32x32或更低,大約100個大小爲64x64或更高,但不知道在分配時需要多於32x32的分辨率,因此您必須對此進行描述所有。 – Marladu 2014-12-08 01:50:09

+0

閱讀:https://www.khronos.org/opengles/sdk/docs/man3/docbook4/xhtml/glTexParameter.xml我導致認爲使用GL_TEXTURE_MIN_LOD不是必需的。 – Marladu 2014-12-08 02:28:43

+0

在我的2臺家用電腦上,使用gDEBugger我可以確認OpenGL不會爲使用本答案中提出的方法準備的紋理分配未使用的mipmap級別的內存。我已經添加了一個問題http://stackoverflow.com/questions/27352305/,以幫助我找出如何找到這個沒有gDEBugger,所以我可以更廣泛地分發這個測試,並得到結果來確認/否認這個答案的方法是我正在尋找的答案。 – Marladu 2014-12-08 06:12:06