我试图在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之前自行对图像进行块编码。 –