Canvasの透過情報をOpenGLで綺麗に反映させるには

SDKのビットマップデータは内部でアルファ値を合成してしまうため、生のデータをそのままOpen GLのテクスチャに貼り付けると、乗算値が暗い色となって画面ににじみ出てしまう。gl.glBlendFunc(GL10.GL_ONE, GL10.GL_ONE_MINUS_SRC_ALPHA);で乗算合成するという手もあるが、そうすると透明なテクスチャ同士を重ね合わせると色が変わってしまうことがある。

Bitmap.getPixels()で乗算しない状態のバッファを取得できるらしいが、これで取得できる配列はARGB。一方OpenGLの32bitテクスチャはRGBA配列でどっちみち変換に手間がかかるため、NDKで直接RGBA配列を取得し、そこから乗算値を差し引く方法を試みてみた。コードはC言語のイメージであることにご承知おきを。
gl.cpp
inline unsigned char removePremulti(unsigned char n, unsigned char a)
{
    if(a == 0) return 255;
    return (unsigned char)(255 * n / a);
}

if(AndroidBitmap_lockPixels(env, bmp, (void**)&temp) < 0) return NULL;
for(int y = 0; y < bh; y++){
    for(int x = 0; x < bw; x++){
        unsigned char a = temp[bp + 3];
        texbits[tp + 3] = a;
        texbits[tp + 0] = removePremulti(temp[bp + 0], a);
        texbits[tp + 1] = removePremulti(temp[bp + 1], a);
        texbits[tp + 2] = removePremulti(temp[bp + 2], a);
    }
}
glBindTexture(GL_TEXTURE_2D, texid);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, bw, bh, 0, GL_RGBA, GL_UNSIGNED_BYTE, texbits);
プログラムの実行結果がこちら。文字列はCanvasにdrawTextしたものをテクスチャに変換したものだが、アンチエイリアスもばっちり。
2012/10/31