使用 WebGL 将 DDS (DXT3) 纹理转换为 ImageData
Converting DDS (DXT3) texture to ImageData using WebGL
我正在尝试使用 WebGL 转换 DDS texture (DXT1 and DXT3 mainly) to ImageData。这是我的尝试...
let ext = <WEBGL_compressed_texture_s3tc>gl.getExtension('WEBGL_compressed_texture_s3tc');
let texture = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, texture);
let fb = gl.createFramebuffer();
gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0);
gl.compressedTexImage2D(gl.TEXTURE_2D, 0, ext.COMPRESSED_RGBA_S3TC_DXT3_EXT, width, height, 0, sourceImage);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
let data = new Uint8Array(width * height * 4);
gl.readPixels(0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, data);
gl.deleteFramebuffer(fb);
let image = new ImageData(new Uint8ClampedArray(data), width, height);
其中 gl 是 WebGLRenderingContext,sourceImage (Uint8Array) 是 DXT3 格式的纹理。没有任何 mipmaps 或其他东西。我敢肯定,因为我尝试使用 this 片段渲染此纹理并且它正在工作。
代码在 readPixels 函数处失败并出现以下错误 (Google Chrome):
[.Offscreen-For-WebGL-000001F2F3C04690]GL ERROR
:GL_INVALID_FRAMEBUFFER_OPERATION : glReadPixels: framebuffer
incomplete
当然,我正在寻找答案,但没有成功。也许 this 可能会有所帮助。如果需要,我可以提供一些示例纹理。
您无法渲染压缩纹理格式,因此将它们附加到帧缓冲区会引发无效操作错误。您需要将一个未压缩的纹理附加到您的帧缓冲区,然后从 DXT 纹理绘制一个 screen-space 四边形采样。像这样:
let ext = <WEBGL_compressed_texture_s3tc>gl.getExtension('WEBGL_compressed_texture_s3tc');
// create framebuffer attachment texture
let colorTarget = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, colorTarget);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
gl.texImage2D(
gl.TEXTURE_2D,
0,
gl.RGBA,
width,
height,
0,
gl.RGBA,
gl.UNSIGNED_BYTE,
null
);
// setup framebuffer
let fb = gl.createFramebuffer();
gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, colorTarget, 0);
// create and upload compressed texture
let compressedTexture = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, compressedTexture);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
gl.compressedTexImage2D(gl.TEXTURE_2D, 0, ext.COMPRESSED_RGBA_S3TC_DXT3_EXT, width, height, 0, sourceImage);
gl.viewport(0,0,width,height);
//draw screenspace quad here
// read back uncompressed color data
let data = new Uint8Array(width * height * 4);
gl.readPixels(0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, data);
gl.deleteFramebuffer(fb);
let imageData = new ImageData(new Uint8ClampedArray(data), width, height);
我正在尝试使用 WebGL 转换 DDS texture (DXT1 and DXT3 mainly) to ImageData。这是我的尝试...
let ext = <WEBGL_compressed_texture_s3tc>gl.getExtension('WEBGL_compressed_texture_s3tc');
let texture = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, texture);
let fb = gl.createFramebuffer();
gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0);
gl.compressedTexImage2D(gl.TEXTURE_2D, 0, ext.COMPRESSED_RGBA_S3TC_DXT3_EXT, width, height, 0, sourceImage);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
let data = new Uint8Array(width * height * 4);
gl.readPixels(0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, data);
gl.deleteFramebuffer(fb);
let image = new ImageData(new Uint8ClampedArray(data), width, height);
其中 gl 是 WebGLRenderingContext,sourceImage (Uint8Array) 是 DXT3 格式的纹理。没有任何 mipmaps 或其他东西。我敢肯定,因为我尝试使用 this 片段渲染此纹理并且它正在工作。
代码在 readPixels 函数处失败并出现以下错误 (Google Chrome):
[.Offscreen-For-WebGL-000001F2F3C04690]GL ERROR :GL_INVALID_FRAMEBUFFER_OPERATION : glReadPixels: framebuffer incomplete
当然,我正在寻找答案,但没有成功。也许 this 可能会有所帮助。如果需要,我可以提供一些示例纹理。
您无法渲染压缩纹理格式,因此将它们附加到帧缓冲区会引发无效操作错误。您需要将一个未压缩的纹理附加到您的帧缓冲区,然后从 DXT 纹理绘制一个 screen-space 四边形采样。像这样:
let ext = <WEBGL_compressed_texture_s3tc>gl.getExtension('WEBGL_compressed_texture_s3tc');
// create framebuffer attachment texture
let colorTarget = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, colorTarget);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
gl.texImage2D(
gl.TEXTURE_2D,
0,
gl.RGBA,
width,
height,
0,
gl.RGBA,
gl.UNSIGNED_BYTE,
null
);
// setup framebuffer
let fb = gl.createFramebuffer();
gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, colorTarget, 0);
// create and upload compressed texture
let compressedTexture = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, compressedTexture);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
gl.compressedTexImage2D(gl.TEXTURE_2D, 0, ext.COMPRESSED_RGBA_S3TC_DXT3_EXT, width, height, 0, sourceImage);
gl.viewport(0,0,width,height);
//draw screenspace quad here
// read back uncompressed color data
let data = new Uint8Array(width * height * 4);
gl.readPixels(0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, data);
gl.deleteFramebuffer(fb);
let imageData = new ImageData(new Uint8ClampedArray(data), width, height);