我試圖在WebGL中加載圖像,然後將它們上傳到GPU。我想使用壓縮紋理格式,即使原始圖像是未壓縮/無損的。加載PNG圖像,但在WebGL中使用它們作爲COMPRESSED_RGBA_S3TC_DXT5_EXT?
要上傳,這是我在做什麼:
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, textureSource);
在上面的代碼,textureSource
是加載(比如說, 「texture.png」)。
它一切正常,但我想加載WEBGL_compressed_texture_s3tc
格式(COMPRESSED_RGB_S3TC_DXT1_EXT
)以壓縮方式存儲圖像。
我要確保延長可用並已啓用...
var ext = gl.getExtension("WEBGL_compressed_texture_s3tc");
var fmt = ext.COMPRESSED_RGBA_S3TC_DXT5_EXT;
console.log(fmt); // 33779
但我不能把它作爲一種格式。使用texImage2D()
不起作用:
gl.texImage2D(gl.TEXTURE_2D, 0, fmt, fmt, gl.UNSIGNED_BYTE, textureSource);
// WebGL: INVALID_ENUM: texImage2D: invalid texture format
// [.WebGLRenderingContext]RENDER WARNING: texture bound to texture unit 0 is not renderable. It maybe non-power-of-2 and have incompatible texture filtering or is not 'texture complete'
預期的方法是compressedTexImage2D()
,但是這不是非常有幫助或者:
gl.compressedTexImage2D(gl.TEXTURE_2D, 0, fmt, 256, 256, 0, texture.source);
// Uncaught TypeError: Failed to execute 'compressedTexImage2D' on 'WebGLRenderingContext': parameter 7 is not of type 'ArrayBufferView'.
這顯然是因爲compressedTexImage2D()
預計與實際DDS/DXT數據Uint8Array
,不是像我傳遞的JavaScript圖像。
顯而易見的解決方案是以本地DDS格式上傳文件 - 在其他地方壓縮過的文件。但是這正是我想要避免的:在我目前的工作流程中,將圖像設置爲原始格式而不是預先壓縮它們(或重複)是有意義的。
然後我的問題是這樣的:我還可以使用原始的PNG圖像,加載它們,並讓它們以壓縮格式上傳到GPU中?換句話說,我可以將紋理壓縮到DXT1/5格式嗎?
我在視頻內存方面受到了一些限制,所以任何保存都會很棒。我設法通過使用UNSIGNED_SHORT_4_4_4_4
和其他數據類型來最小化紋理使用的空間,這是一個好的開始,但我也想嘗試使用本地壓縮。
我還沒有找到關於這個主題的很多文檔,也沒有在其他流行的庫(Three.js,Pixi等)上找到相關的代碼,這導致我相信我的請求是超級愚蠢的,但我想理解爲什麼。 This page暗示許可問題,這可能是WebGL不具備正確壓縮文件的方式,也不允許瀏覽器支持圖像對象的原因。
該擴展只允許您上傳預壓縮的圖像數據。將原始RGB [A]數據編碼到DXT中不是OpenGL ES/WebGL的一部分。如果您想使用PNG進行存儲,則必須在將圖像傳遞給WebGL之前自行對圖像進行塊編碼。 –