0

私が書いた Android ゲームのテクスチャのメモリ フットプリントを減らそうとしましたが、あまり成功しませんでした。私が行った調査に基づいて、ETC1 を使用してテクスチャを圧縮するのが良い方法のようです。これは、Android デバイスで最も広くサポートされている形式であるためです。

Mali ARM を使用して、PNG から必要な PKM を作成できます。問題はありません。ETC1Utils を使用して、これらの PKM を適切にレンダリングすることもできます。ここでも問題はありません。

問題は、アルファを処理しようとすると発生します。Mali を使用して、PNG 用に別のアルファ ファイルを作成しました。つまり、"xxx.png" は "xxx.pkm" と "xxx_alpha.pkm" に圧縮されます。OpenGL ES 1.1 ではフラグメント シェーダーを使用できないため、マルチテクスチャリングを使用してこれら 2 つのテクスチャを結合するという別の質問で提案された 1 つのアプローチです。

そして、これが私が立ち往生しているところです。私はこのことにあまり詳しくなく、あまり進んでいません。基本的に、アルファ テクスチャと結合しようとするとすぐに、すべてが白くレンダリングされます。

ここに私のコードのスニペットがあります:

public class Texture {

    GLGraphics glGraphics;
    FileIO fileIO;
    String fileName;
    int textureId;
    int minFilter;
    int magFilter;

    public int width;
    public int height;

    private boolean loaded = false;

    public Texture(GLGame glGame, String fileName) {
        this.glGraphics = glGame.getGLGraphics();
        this.fileIO = glGame.getFileIO();
        this.fileName = fileName;
        load();
    }

    public void load() {
        GL10 gl = glGraphics.getGL();
        int[] textureIds = new int[2];
        gl.glGenTextures(2, textureIds, 0);
        textureId = textureIds[0];

        InputStream inputStream = null;

        try {
            inputStream = fileIO.readAsset(fileName + ".pkm");

            int rgbTexture = textureId;

            gl.glActiveTexture(GLES10.GL_TEXTURE0);
            gl.glBindTexture(GLES11.GL_TEXTURE_2D, rgbTexture);
            gl.glTexEnvf(GLES11.GL_TEXTURE_ENV, GLES11.GL_TEXTURE_ENV_MODE, GLES11.GL_MODULATE);

            ETC1Texture etcTexture = ETC1Util.createTexture(inputStream);
            ETC1Util.loadTexture(GLES11.GL_TEXTURE_2D, 0, 0, GLES11.GL_RGB, GLES11.GL_UNSIGNED_SHORT_5_6_5, etcTexture);

            int alphaTexture = textureId[1];

            gl.glActiveTexture(GLES11.GL_TEXTURE1);
            gl.glBindTexture(GLES11.GL_TEXTURE_2D, alphaTexture);
            gl.glTexEnvf(GLES11.GL_TEXTURE_ENV, GLES11.GL_TEXTURE_ENV_MODE, GLES11.GL_COMBINE);
            gl.glTexEnvf(GLES11.GL_TEXTURE_ENV, GLES11.GL_COMBINE_RGB, GLES11.GL_REPLACE);
            gl.glTexEnvf(GLES11.GL_TEXTURE_ENV, GLES11.GL_SRC0_RGB, GLES11.GL_PREVIOUS);
            gl.glTexEnvf(GLES11.GL_TEXTURE_ENV, GLES11.GL_OPERAND0_RGB, GLES11.GL_SRC_COLOR);
            gl.glTexEnvf(GLES11.GL_TEXTURE_ENV, GLES11.GL_COMBINE_ALPHA, GLES11.GL_MODULATE);
            gl.glTexEnvf(GLES11.GL_TEXTURE_ENV, GLES11.GL_SRC0_ALPHA, GLES11.GL_TEXTURE);
            gl.glTexEnvf(GLES11.GL_TEXTURE_ENV, GLES11.GL_OPERAND0_ALPHA, GLES11.GL_SRC_ALPHA);
            gl.glTexEnvf(GLES11.GL_TEXTURE_ENV, GLES11.GL_SRC1_ALPHA, GLES11.GL_PREVIOUS);
            gl.glTexEnvf(GLES11.GL_TEXTURE_ENV, GLES11.GL_OPERAND1_ALPHA, GLES11.GL_SRC_ALPHA);

            InputStream inputStreamAlpha = fileIO.readAsset(fileName + "_alpha.pkm");
            ETC1Texture etcAlphaTexture = ETC1Util.createTexture(inputStreamAlpha);
            ETC1Util.loadTexture(GLES11.GL_TEXTURE_2D, 0, 0, GLES11.GL_RGB, GLES11.GL_UNSIGNED_SHORT_5_6_5, etcAlphaTexture);

            setFilters(GL10.GL_NEAREST, GL10.GL_NEAREST);
            gl.glBindTexture(GL10.GL_TEXTURE_2D, 0);

            width = etcTexture.getWidth();
            height = etcTexture.getHeight();
        } catch (IOException e) {
            throw new RuntimeException("Couldn't load texture '" + fileName + "'", e);
        } finally {
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    // do nothing
                }
            }
        }

        loaded = true;
    }

    public void reload() {
        load();
        bind();
        setFilters(minFilter, magFilter);
        glGraphics.getGL().glBindTexture(GL10.GL_TEXTURE_2D, 0);
    }

    public void setFilters(int minFilter, int magFilter) {
        this.minFilter = minFilter;
        this.magFilter = magFilter;

        GL10 gl = glGraphics.getGL();
        gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, minFilter);
        gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, magFilter);
    }

    public void bind() {
        GL10 gl = glGraphics.getGL();
        gl.glBindTexture(GL10.GL_TEXTURE_2D, textureId);
    }

    public void dispose() {
        loaded = false;

        GL10 gl = glGraphics.getGL();
        gl.glBindTexture(GL10.GL_TEXTURE_2D, textureId);
        int[] textureIds = { textureId };
        gl.glDeleteTextures(1, textureIds, 0);
        gl.glBindTexture(GL10.GL_TEXTURE_2D, 0);
    }

    public boolean isLoaded() {
        return loaded;
    }

    public void setLoaded(boolean loaded) {
        this.loaded = loaded;
    }
}

私の主な関心事は load() メソッドです。このコードは、私が Web で見つけたスニペットを使用してまとめられたものであり、一般的なマルチテクスチャリングに対する理解の欠如と相まって、どこかで明らかに間違っています。また、テクスチャをレンダリングするときに次を呼び出すことに注意してください。

GL10 gl = glGraphics.getGL();
gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
gl.glEnable(GL10.GL_TEXTURE_2D);        

camera.setViewportAndMatrices();
gl.glEnable(GL10.GL_BLEND);
gl.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA);

// call some objects that do my rendering stuff here

gl.glDisable(GL10.GL_BLEND);
gl.glDisable(GL10.GL_TEXTURE_2D);

テクスチャをレンダリングするときは、Texture クラスで bind() メソッドを呼び出します。ご覧のとおり、これはロード時に RGB PKM ID として使用されたグローバル textureId 変数にバインドされます。これが正しいかどうかさえわかりません。RGB の ID またはアルファの ID にバインドする必要がありますか? それとも、正しい軌道に乗っているとは言えませんか? 私の問題は、ETC1Utils を使用してアルファをロードする方法にも関連している可能性があります。このアプローチが正しいかどうかはわかりません。

私は本当にかなり行き詰まっているので、どこが間違っているのかを指摘し、ETC1 アルファと RGB を組み合わせるためにマルチテクスチャリングをどのように実装する必要があるかについての何らかの説明があれば、本当に素晴らしいでしょう.

4

1 に答える 1

0

OpenGL ES 1.1 の固定パイプラインでこれが可能かどうかはわかりませんが、1.1 と 2.0 の両方のテクスチャを組み合わせる方法の概要がここにあります

また、PowerVR SDKには、OGLESMultitexture.cpp と呼ばれる 1.1 の優れた例があります。

于 2014-05-30T01:18:25.910 に答える