最近项目中翻折效果,用openGL ES(我刚刚接触openGL),我使用128x128的图片作纹理,在真机和模拟器上都成功了,图片我用768x512的大图(真实网络接口中的图片)做纹理则在真机上无法显示出来,模拟器就可以。不知什么原因!以下是主要代码:public class MyFlipperRenderer implements Renderer {

public float mRotatefAngle;

private Context mContext; private int mTextureID;

public MyFlipperRenderer(Context c) {
mContext = c;
}

@Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
mRotatefAngle = 0f;
GLES10.glDisable(GL10.GL_DITHER);
GLES10.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_FASTEST);
GLES10.glClearColor(1f, 1f, 1f, 0f);
GLES10.glShadeModel(GL_SMOOTH);
GLES10.glEnable(GL_DEPTH_TEST);
GLES10.glEnable(GL_TEXTURE_2D);
GLES10.glEnableClientState(GL10.GL_VERTEX_ARRAY);
GLES10.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
//GLES10.glEnableClientState(GL10.GL_COLOR_ARRAY);
GLES10.glEnable(GL10.GL_CULL_FACE);//剔除表面
GLES10.glFrontFace(GL10.GL_CCW);//逆时针是正面
GLES10.glCullFace(GL10.GL_BACK);//剔除背面
// 启用点平滑与线平滑(抗锯齿)
GLES10.glEnable(GL10.GL_POINT_SMOOTH);
GLES10.glHint(GL10.GL_POINT_SMOOTH_HINT, GL10.GL_FASTEST);
GLES10.glEnable(GL10.GL_LINE_SMOOTH);
GLES10.glHint(GL10.GL_LINE_SMOOTH_HINT, GL10.GL_NICEST);

GLES10.glEnable(GL10.GL_TEXTURE_2D);
int[] textids = new int[1];
GLES10.glGenTextures(1, textids, 0);// 生成纹理id
mTextureID = textids[0];
GLES10.glBindTexture(GL10.GL_TEXTURE_2D, mTextureID);// 绑定纹理到该整数值
GLES10.glTexParameterf(GLES10.GL_TEXTURE_2D, GLES10.GL_TEXTURE_MIN_FILTER, GLES10.GL_LINEAR); 
GLES10.glTexParameterf(GLES10.GL_TEXTURE_2D, GLES10.GL_TEXTURE_MAG_FILTER, GLES10.GL_LINEAR); 
GLES10.glTexParameterf(GLES10.GL_TEXTURE_2D, GLES10.GL_TEXTURE_WRAP_S, GLES10.GL_REPEAT);
GLES10.glTexParameterf(GLES10.GL_TEXTURE_2D, GLES10.GL_TEXTURE_WRAP_T, GLES10.GL_REPEAT);

InputStream is = mContext.getResources().openRawResource(R.raw.robot);
Bitmap bmp = null;
try {
bmp = BitmapFactory.decodeStream(is);
} finally {
try {
is.close();
} catch (IOException e) {
// Ignore.
}
}

// ByteBuffer byteBuffer = ByteBuffer.allocate(bmp.getRowBytes() * bmp.getHeight());
// byteBuffer.order(ByteOrder.nativeOrder());
// bmp.copyPixelsToBuffer(byteBuffer);
// byteBuffer.position(0);
// gl.glTexImage2D(GLES10.GL_TEXTURE_2D, 0, 3, bmp.getWidth(), bmp.getHeight(), 0, GLES10.GL_RGB, GLES10.GL_UNSIGNED_BYTE, byteBuffer);
GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bmp, 0);
//GLUtils.texSubImage2D(GL_TEXTURE_2D, 0, 0, 0, bmp);
bmp.recycle();
}

@Override
public void onSurfaceChanged(GL10 gl, int width, int height) {
GLES10.glViewport(0, 0, width, height);
float ratio = (float)width / height;
GLES10.glMatrixMode(GL10.GL_PROJECTION);
GLES10.glLoadIdentity();
GLES10.glFrustumf(-ratio, ratio, -1, 1, 4, 10);
}

@Override
public void onDrawFrame(GL10 gl) {
glDisable(GL_DITHER);
        glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        glMatrixMode(GL_MODELVIEW);
        GLES10.glLoadIdentity();
GLU.gluLookAt(gl, 0, 0, 4.5f, 0, 0, 0, 0, 1, 0);

GLES10.glColor4f(0.3f, 0.5f, 0.8f, 1f);
float[] texCoordTop_Bottom = {
0f, 1f,
1f, 1f,
0f, .5f,
1f, .5f
};
GLES10.glTexCoordPointer(2, GL10.GL_FLOAT, 0, BufferUtil.arr2FloatBuffer(texCoordTop_Bottom));
float[] rectCoordsFront_Bottom = {
-1f, -.5f, 0f,
1f, -.5f, 0f,
-1f, 0f, 0f,
1f, 0f, 0f
};
drawRect(gl, rectCoordsFront_Bottom);

//**************************************************************************
GLES10.glColor4f(0.5f, 0.5f, 0.2f, 1f);
float[] texCoord_back = {
0f, 1f,
1f, 1f,
0f, 0f,
1f, 0f
};
GLES10.glTexCoordPointer(2, GL10.GL_FLOAT, 0, BufferUtil.arr2FloatBuffer(texCoord_back));
float[] rectCoordsBack = {
-1f, -0.5f, -.01f,
1f, -0.5f, -.01f,
-1f, 0.5f, -.01f,
1f, 0.5f, -.01f
};
drawRect(gl, rectCoordsBack);
//**************************************************************************
GLES10.glRotatef(mRotatefAngle, 1, 0, 0);
float[] texCoord = {
0f, .5f,
1f, .5f,
0f, 0f,
1f, 0f
};
GLES10.glTexCoordPointer(2, GL10.GL_FLOAT, 0, BufferUtil.arr2FloatBuffer(texCoord));
GLES10.glColor4f(0.5f, 0f, 0.5f, 1f);

float[] rectCoordsFront_Top = {
-1f, 0f, 0f,
1f, 0f, 0f,
-1f, 0.5f, 0f,
1f, 0.5f, 0f
};
drawRect(gl, rectCoordsFront_Top);
//**************************************************************************

GLES10.glColor4f(0.5f, 0f, 0.5f, 1f);
float[] texCoordTop_back = {
0f, 1f,
1f, 1f,
0f, .5f,
1f, .5f
};
GLES10.glTexCoordPointer(2, GL10.GL_FLOAT, 0, BufferUtil.arr2FloatBuffer(texCoordTop_back));
float[] rectCoordsTop_back = {
-1f, .5f, 0f,
1f, .5f, 0f,
-1f, 0f, 0f,
1f, 0f, 0f
};
drawRect(gl, rectCoordsTop_back);

}

private FloatBuffer arr2FloatBuffer(float[] arr) {
ByteBuffer vbb = ByteBuffer.allocateDirect(arr.length * 4);
vbb.order(ByteOrder.nativeOrder());
FloatBuffer fbb = vbb.asFloatBuffer();
fbb.put(arr);
fbb.position(0);// 等同c,将指针移到缓冲区的首地址上
return fbb;
}

public void drawRect(GL10 gl, float[] vertexCoords) {
GLES10.glVertexPointer(3, GLES10.GL_FLOAT, 0, arr2FloatBuffer(vertexCoords));
GLES10.glDrawArrays(GLES10.GL_TRIANGLE_STRIP, 0, vertexCoords.length / 3);
}}
openGL ESandroid

解决方案 »

  1.   

    OpenGL中贴图的长宽有"pow of two"原则,就是加载到GPU中的贴图的长宽应该是“2的n次方”。不过有些机器可以接收任意长度(对贴图进行了处理),有些机器不可以(不知道是否和Android的版本有关)。但是最终加载到内存中的贴图的长宽都是“2的n次方”,所以如果长宽不是“2的n次方”,很浪费内存的。比如,768x512的贴图加载到内存,和1024x512的内存是一样多的。