当前位置:编程学习 > wap >>

android openGL 3D纹理真机空白

最近刚刚接手公司的3D luncher开发,在使用openGL的纹理给形状贴图的时候,遇到了模拟器正常,但是真机上始终是一片空白,都快崩溃了,也在网上收集了很多资料如:图片尺寸修改为2的N次方,图片资源文件夹取名为drawable-nodpi,buffer采用ByteBuffer.allocateDirect(arry.length * 4)等,均无法显示,请高手解答,代码如下:
主要代码:

一、模型:Polygon
public class Polygon {
private Context context;

private float edgeWidth;

private float edgeHeight;

// 每一个平面的顶点索引
private ByteBuffer[] indexBuffer;

// 每一个平面的顶点坐标
private FloatBuffer[] faceVertexBuffer;

private static final float U = (float) (Math.sqrt(3.0) / 2);

private static final float S = 0.15f;

public static final int FACENUM = 6;

// 每一个平面的顶点坐标的二维数组
private float[][] faceVertices;

// 保存每一个平面的顶点索引的二维数组
private byte[][] indies = { 
new byte[] { 0, 1, 2, 1, 3, 2 }, 
new byte[] { 0, 1, 2, 1, 3, 2 },
        new byte[] { 0, 1, 2, 1, 3, 2 }, 
        new byte[] { 0, 1, 2, 1, 3, 2 }, 
        new byte[] { 0, 1, 2, 1, 3, 2 },
        new byte[] { 0, 1, 2, 1, 3, 2 }
};

private TextureUtil textureUtil;

private int[] textures;

private FloatBuffer[] textureBuffer;

public Polygon(Context context, float edgeWidth, float edgeHeight) {
this.context = context;
this.edgeWidth = edgeWidth;
this.edgeHeight = edgeHeight;
}

public void init(GL10 gl) {
float tx = 0.5f * this.edgeWidth, tx1 = -(1.0f + U * S) * this.edgeWidth, tx2 = -(0.5f + U * S) * this.edgeWidth, tx4 = -(U + S / 2) * this.edgeWidth ;
float ty = 1.0f * this.edgeHeight;
float tu = -(U + S) * this.edgeWidth, tu1 = -(S / 2) * this.edgeWidth, tu2 = (U + S) * this.edgeWidth;

faceVertices = new float[][] {
        { 
     -tx, -ty, tu, 
     tx, -ty, tu, 
     -tx, ty, tu,
     tx, ty, tu
        },
        {
     tx1, -ty, tu1, 
     tx2, -ty,
            tx4, tx1, 
            ty, tu1, tx2,
            ty, tx4 
        },
       {
     -tx2, -ty, tx4, 
     -tx1, -ty, tu1, 
     -tx2, ty, tx4,
     -tx1, ty, tu1 
        },
       {
     -tx2, -ty, -tx4, 
     -tx1, -ty, -tu1, 
     -tx2, ty, -tx4, 
     -tx1, ty, -tu1 
     }, 
       {// 7
     -tx, -ty, tu2, 
     tx, -ty, tu2, 
     -tx, ty, tu2, 
     tx, ty, tu2 
        }, 
        {// 8
     tx2, -ty, -tx4, 
     tx1, -ty, -tu1,
            tx2, ty, -tx4, 
            tx1, ty, -tu1 
        } 
        };

faceVertexBuffer = new FloatBuffer[FACENUM];
for (int i = 0; i < faceVertices.length; i++) {
faceVertexBuffer[i] = (FloatBuffer) BufferUtil.arrayToBuffer(faceVertices[i]);
}

indexBuffer = new ByteBuffer[FACENUM];
for (int i = 0; i < indies.length; i++) {
indexBuffer[i] = (ByteBuffer) BufferUtil.arrayToBuffer(indies[i]);
}
textureUtil = new TextureUtil(FACENUM);
textures = textureUtil.loadTexture(gl, context);
textureBuffer = textureUtil.getTextureBuffer();
}

public void draw(GL10 gl) {
for (int i = 0; i < FACENUM; i++) {
int txtr = textures[i];
FloatBuffer  fcVtx = faceVertexBuffer[i];
FloatBuffer txtrBf = textureBuffer[i];
int len = indies[i].length;
ByteBuffer bb = indexBuffer[i];

// 生成一个纹理引用,并把它和当前的数组绑定
gl.glBindTexture(GL10.GL_TEXTURE_2D, txtr);
            
            // 设置顶点
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, fcVtx);

// 设置纹理顶点坐标
gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, txtrBf);    

// 绘制平面(openGL绘图时是按照顶点索引数组定义的顺序,按照每次绘制一个三角形的方式进行绘制的)
gl.glDrawElements(GL10.GL_TRIANGLES, len, GL10.GL_UNSIGNED_BYTE, bb);
}
}
}

二、view的Render类:
public class GLRender implements GLSurfaceView.Renderer {
private Polygon polygon;

public float mAngleX;

public float mAngleY;

private boolean keyLF;

private boolean keyUD;

private float xSpeed;

private float xStep = 1.0f;

private float yStep = 6.0f;

private float ySpeed;

private int aminTimes = 0;

public GLRender(Context context) {
this.polygon = new Polygon(context, 4.2f, 1.0f);
}

private void antiAliased(GL10 gl) {
gl.glPointSize(8);
gl.glLineWidth(5);

gl.glEnable(GL10.GL_POINT_SMOOTH);
gl.glEnable(GL10.GL_LINE_SMOOTH);
gl.glHint(GL10.GL_POINT_SMOOTH_HINT, GL10.GL_NICEST);
gl.glHint(GL10.GL_LINE_SMOOTH_HINT, GL10.GL_NICEST);
gl.glEnable(GL10.GL_BLEND);
gl.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA);
}

@Override
public void onDrawFrame(GL10 gl) {
// 清除屏幕和深度缓存
gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);

gl.glTexEnvx(GL10.GL_TEXTURE_ENV, GL10.GL_TEXTURE_ENV_MODE, GL10.GL_MODULATE);

// 重置当前的模型观察矩阵
gl.glLoadIdentity();

// 并移入屏幕 6.0
gl.glTranslatef(0f, 0.0f, -6.0f);

// 设置定点数组
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);

// 纹理的使用与开启颜色渲染一样,需要开启纹理功能
gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);

// 设置旋转
gl.glRotatef(mAngleX, 1, 0, 0);
gl.glRotatef(mAngleY, 0, 1, 0);

// 按照顺时针方向绘制
gl.glFrontFace(GL10.GL_CW);

// 绘制开始
this.polygon.draw(gl);

// 绘制结束
gl.glFinish();

// 取消顶点数组
gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);

// 取消纹理坐标的权限
gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);

if (aminTimes < 10) {
if (keyLF) {
mAngleY += ySpeed;
}
aminTimes++;
} else {
keyLF = false;
float step = yStep * aminTimes;
float rmnd = (mAngleY % step) / step;
if (rmnd != 0.0f) {
mAngleY = Math.round(mAngleY / step) * step;
}
}

if (keyUD) {
mAngleX += xSpeed;
} else {
if (mAngleX > 0) {
mAngleX -= 1.0f;
}
if (mAngleX < 0) {
mAngleX += 1.0f;
}
}
}

@Override
public void onSurfaceChanged(GL10 gl, int width, int height) {
// TODO Auto-generated method stub
float ratio = (float) width / height;

// 设置OpenGL场景的大小
gl.glViewport(0, 0, width, height);

// 设置投影矩阵
gl.glMatrixMode(GL10.GL_PROJECTION);

// 重置投影矩阵
gl.glLoadIdentity();

// 设置视口的大小
gl.glFrustumf(-ratio, ratio, -1, 1, 1, 10);

// 选择模型观察矩阵
gl.glMatrixMode(GL10.GL_MODELVIEW);

// 重置模型观察矩阵
gl.glLoadIdentity();
}

@Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
// 黑色背景
gl.glClearColor(0, 0, 0, 0);

// 启用阴影平滑
gl.glShadeModel(GL10.GL_SMOOTH);

// 启用深度测试
gl.glEnable(GL10.GL_DEPTH_TEST);

// 设置深度缓存
gl.glClearDepthf(1.0f);

// 所作深度测试的类型
gl.glDepthFunc(GL10.GL_LEQUAL);

// 消除锯齿设置
antiAliased(gl);

// 告诉系统对透视进行修正
gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_FASTEST);

// 允许2D贴图
gl.glEnable(GL10.GL_TEXTURE_2D);

// 开启混合模式
gl.glEnable(GL10.GL_BLEND);
gl.glBlendFunc(GL10.GL_ONE, GL10.GL_SRC_COLOR);

// 线形滤波
gl.glTexParameterx(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_LINEAR);
gl.glTexParameterx(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR);

// 设置和绘制正方形
this.polygon.init(gl);
}

public boolean onKeyDown(int keyCode, KeyEvent event) {
switch (keyCode) {
case KeyEvent.KEYCODE_DPAD_UP:
keyUD = true;
aminTimes = 0;
if (ySpeed != 0) {
ySpeed = 0;
}
xSpeed = -xStep;
break;
case KeyEvent.KEYCODE_DPAD_DOWN:
keyUD = true;
aminTimes = 0;
if (ySpeed != 0) {
ySpeed = 0;
}
xSpeed = xStep;
break;
case KeyEvent.KEYCODE_DPAD_LEFT:
keyLF = true;
aminTimes = 0;
if (xSpeed != 0) {
xSpeed = 0;
}
ySpeed = -yStep;
break;
case KeyEvent.KEYCODE_DPAD_RIGHT:
keyLF = true;
aminTimes = 0;
if (xSpeed != 0) {
xSpeed = 0;
}
ySpeed = yStep;
break;
case KeyEvent.KEYCODE_DPAD_CENTER:
// light = !light;
break;
}
return false;
}

public boolean onKeyUp(int keyCode, KeyEvent event) {
if (keyUD) {
keyUD = false;
}
return false;
}
} --------------------编程问答-------------------- 由于类容超长,工具类如下:
三、纹理的工具类:
public class TextureUtil {
private int faceNum;

// 保存纹理的FloatBuffer
private FloatBuffer[] textureBuffer;

// 保存纹理顶点坐标的数组
private float[][] textureVertexArry = { 
new float[] { 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f },
        new float[] { 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f },
        new float[] { 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f },
        new float[] { 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f },
        new float[] { 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f },
        new float[] { 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f } };

public void setTextureVertexArry(float[][] textureArry) {
     this.textureVertexArry = textureArry;
    }

public void setImagesArry(int[] imagesArry) {
     this.imagesArry = imagesArry;
    }

public FloatBuffer[] getTextureBuffer() {
     return textureBuffer;
    }

// 贴图数组
private int[] imagesArry = { 
R.drawable.view_01, 
R.drawable.view_02, 
R.drawable.view_03, 
R.drawable.view_04,
        R.drawable.view_05, 
        R.drawable.view_06 
};

public TextureUtil(int faceNum) {
this.faceNum = faceNum;
this.init();
}

public void init() {
textureBuffer = new FloatBuffer[faceNum];
for (int i = 0; i < faceNum; i++) {
textureBuffer[i] = (FloatBuffer) BufferUtil.arrayToBuffer(textureVertexArry[i]);
}
}

/**
 * 加载和绑定纹理
 * 
 * @param gl
 * @param context
 * @param index
 */
public int[] loadTexture(GL10 gl, Context context) {
int[] textures = new int[faceNum];
// 创建纹理
gl.glGenTextures(faceNum, textures, 0);

for (int i = 0; i < faceNum; i++) {
// 加载位图
Bitmap bitmap = loadBitmap(context, imagesArry[i]);

// 设置要使用的纹理
gl.glBindTexture(GL10.GL_TEXTURE_2D, textures[i]);

// 生成纹理
GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap, 0);

// 回收位图
bitmap.recycle();
}
return textures;
}

/**
 * 加载位图
 * 
 * @param context
 * @param resourceid
 * @return
 */
public Bitmap loadBitmap(Context context, int resourceid) {
InputStream is = context.getResources().openRawResource(resourceid);
try {
// BitmapFactory is an Android graphics utility for images
return BitmapFactory.decodeStream(is);
}
finally {
// Always clear and close
try {
is.close();
is = null;
}
catch (IOException e) {
e.printStackTrace();
}
}
}
}
小弟是新手,望高手指点迷津,不甚感激,谢谢! --------------------编程问答-------------------- 这两天我也在学习opengl,看了看你的代码,不知道你解决了这个问题没有,你应该把GLRender中onSurfaceChanged()方法中的
// 线形滤波
gl.glTexParameterx(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_LINEAR);
gl.glTexParameterx(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR);
放在TextureUtil类中loadTexture()方法
// 设置要使用的纹理
gl.glBindTexture(GL10.GL_TEXTURE_2D, textures[i]);
下面 --------------------编程问答-------------------- 是onSurfaceCreated中的线形滤波 --------------------编程问答-------------------- 我也遇到类似问题. 并不是所有设备都空白,目前发现一款联想机器空白.没找到解决方案.不知楼主解决没有.
补充:移动开发 ,  Android
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,