Android 如何使用OpenGL ES 1.1实现多重纹理,以结合单独的RGB和alpha PKM?
我一直在努力减少Android游戏中纹理的内存占用,但没有取得太大成功。根据我所做的研究,似乎一个好方法是使用ETC1压缩我的纹理,因为这是Android设备最广泛支持的格式 我能够使用Mali ARM从我的PNG创建必要的PKM-没有问题。我还可以使用ETC1Utils渲染这些pkm,同样到目前为止没有问题 问题在于如何处理Alpha。我使用Mali为我的png创建了一个单独的alpha文件,即“xxx.png”被压缩为“xxx.pkm”和“xxx_alpha.pkm”。在我提出的另一个问题中,有一种方法建议我使用多重纹理来组合这两种纹理,因为我不能在OpenGL ES 1.1中使用片段着色器 这就是我被困的地方。我对这些东西不太熟悉,也不太熟悉。基本上,只要我尝试结合我的alpha纹理,所有的东西都被渲染成白色 以下是我的代码片段:Android 如何使用OpenGL ES 1.1实现多重纹理,以结合单独的RGB和alpha PKM?,android,opengl-es,multitexturing,Android,Opengl Es,Multitexturing,我一直在努力减少Android游戏中纹理的内存占用,但没有取得太大成功。根据我所做的研究,似乎一个好方法是使用ETC1压缩我的纹理,因为这是Android设备最广泛支持的格式 我能够使用Mali ARM从我的PNG创建必要的PKM-没有问题。我还可以使用ETC1Utils渲染这些pkm,同样到目前为止没有问题 问题在于如何处理Alpha。我使用Mali为我的png创建了一个单独的alpha文件,即“xxx.png”被压缩为“xxx.pkm”和“xxx_alpha.pkm”。在我提出的另一个问题中
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()方法。这段代码是通过我在网上找到的片段组合而成的,再加上我对多重纹理的总体理解不足,我显然在某个地方出了问题。还要注意,渲染纹理时,我调用:
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);
渲染纹理时,我在纹理类上调用bind()方法。如您所见,这绑定到我的全局textureId变量,该变量在加载时用作RGB PKMs ID。我甚至不确定这是否正确。我应该绑定到RGB的ID还是alpha的ID?还是说这还不接近正确的轨道?我的问题还可能与如何使用ETC1Utils加载Alpha有关-我不知道这种方法是否正确
我真的被卡住了,所以任何人帮我指出哪里出了问题,并解释一下如何实现多重纹理以将ETC1 Alpha和RGB结合起来,都会非常棒。我不确定OpenGL ES 1.1中的固定管道是否可以做到这一点,但是对于如何组合1.1和2.0的纹理有一个很好的总结
此外,PowerVR在1.1版中有一个很好的例子,名为oglesmultexture.cpp。我根本没有正确执行多重纹理。但在弄清楚如何做到这一点后,我还发现我想要实现的东西在OpenGLES1.1中是不可能实现的。问题是alpha PKM将其值存储在RGB通道中,而在多重纹理(据我所见)中,无法将这些RGB值组合成单个alpha值。因此,我接受了这个答案,因为@ClayMontgomery确实说过这在OpenGL ES 1.1中是不可能的。