画像を WebGL に読み込んでから GPU にアップロードしようとしています。元の画像は圧縮されていない/可逆ですが、圧縮されたテクスチャ形式を使用したいと思います。
アップロードするには、これが私がやっていることです:
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'.
これは明らかに、私が渡しているような JavaScript イメージではなく、実際の DDS/DXT データをcompressedTexImage2D()
期待しているためです。Uint8Array
明らかな解決策は、ファイルをネイティブの DDS 形式 (別の場所で圧縮されたファイル) でアップロードすることです。しかし、それは私が避けようとしているものです。現在のワークフローでは、画像を事前に圧縮する (または複製する) よりも、元の形式で画像を保持する方が理にかなっています。
私の質問は次のとおりです。元のPNG画像を引き続き使用してロードし、圧縮形式でGPUにアップロードできますか? つまり、テクスチャをオンザフライで DXT1/5 形式に圧縮できますか?
私がやっていることは、ビデオ メモリによって少し制限されているので、節約できれば素晴らしいことです。と他のデータ型を使用して、テクスチャが使用するスペースを最小限に抑えることができましたUNSIGNED_SHORT_4_4_4_4
。これは良いスタートですが、ネイティブ圧縮も使用してみたいと思います。
このトピックに関するドキュメントはあまり見つかりませんし、他の人気のあるライブラリ (Three.js、Pixi など) に関連するコードも見つかりませんでした。このページは、ライセンスの問題を示唆しています。これが、WebGL がファイルを適切に圧縮する方法を備えておらず、画像オブジェクトのブラウザー サポートを許可していない理由である可能性があります。