在 android 中使用 opengl 在 glsurfaceview 中显示 3D 模型的问题

Posted

技术标签:

【中文标题】在 android 中使用 opengl 在 glsurfaceview 中显示 3D 模型的问题【英文标题】:Problems showing a 3D model inside a glsurfaceview with opengl in android 【发布时间】:2014-10-14 22:50:32 【问题描述】:

我正在尝试在 glsurfaceview 中绘制一个简单的立方体,但我没有得到清晰的表示。我只想画一个简单的立方体。

我自己的渲染器

import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;

import android.opengl.GLSurfaceView.Renderer;
import android.opengl.GLU;

public class MyRenderer implements Renderer

Cube cube = new Cube();

@Override
public void onSurfaceCreated(GL10 gl, EGLConfig arg1) 

    //set background color
    gl.glClearColor(0.0f, 0.0f, 0.0f, 1f);

    gl.glShadeModel(GL10.GL_SMOOTH);

    // Buffer depth
    gl.glClearDepthf(1.0f);

    gl.glEnable(GL10.GL_DEPTH_TEST);

    gl.glDepthFunc(GL10.GL_LEQUAL);

    gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_NICEST);


@Override
public void onDrawFrame(GL10 gl) 

    // Clean the screen and the buffer depth
    gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);

    // replace actual matrix with the identity matrix
    gl.glLoadIdentity();

    // Move object 8 units in Z axis
    gl.glTranslatef(0, 0, -8);

    // Draw the cube
    cube.draw(gl);


@Override
public void onSurfaceChanged(GL10 gl, int width, int height) 

    gl.glViewport(0, 0, width, height);

    // Select proyection matrix
    gl.glMatrixMode(GL10.GL_PROJECTION);

    // Reset proyection matrix
    gl.glLoadIdentity();

    // Calculates the proportion of the window
    GLU.gluPerspective(gl, 45.0f, (float) width / (float) height, 0.1f,100.0f);

    // Model matrix view
    gl.glMatrixMode(GL10.GL_MODELVIEW);

    // Reset model3d matrix
    gl.glLoadIdentity(); 


我自己的 3D 模型

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.nio.ShortBuffer;

import javax.microedition.khronos.opengles.GL10;

public class Cube 

private float vertices[] = //(x,y,z)
 
1.000000f, -1.000000f, -1.000000f,
1.000000f, -1.000000f, 1.000000f,
-1.000000f, -1.000000f, 1.000000f,
-1.000000f, -1.000000f, -1.000000f,
1.000000f, 1.000000f, -0.999999f,
0.999999f, 1.000000f, 1.000001f,
-1.000000f, 1.000000f, 1.000000f,
-1.000000f, 1.000000f, -1.000000f
;

private short caras[] = //

        2, 3, 4,
        8, 7, 6,
        1, 5, 6,
        2, 6, 7,
        7, 8, 4,
        1, 4, 8,
        1, 2, 4,
        5, 8, 6,
        2, 1, 6,
        3, 2, 7,
        3, 7, 4,
        5, 1, 8
;

private float colors[] =

    1f, 0f, 0f, 1f
;

private FloatBuffer vertexBuffer;
private FloatBuffer colorBuffer;
private ShortBuffer indexBuffer;

public Cube() 

    ByteBuffer vbb = ByteBuffer.allocateDirect(vertices.length * 4);
    vbb.order(ByteOrder.nativeOrder());
    vertexBuffer = vbb.asFloatBuffer();
    vertexBuffer.put(vertices);
    vertexBuffer.position(0);

    ByteBuffer ibb = ByteBuffer.allocateDirect(caras.length * 2);
    ibb.order(ByteOrder.nativeOrder());
    indexBuffer = ibb.asShortBuffer();
    indexBuffer.put(caras);
    indexBuffer.position(0);

    ByteBuffer cbb = ByteBuffer.allocateDirect(colors.length * 4);
    cbb.order(ByteOrder.nativeOrder());
    colorBuffer = cbb.asFloatBuffer();
    colorBuffer.put(colors);
    colorBuffer.position(0);               


public void draw(GL10 gl) 

    gl.glFrontFace(GL10.GL_CCW);

    gl.glEnable(GL10.GL_CULL_FACE);

    gl.glCullFace(GL10.GL_BACK);

    gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);

    gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer);

    gl.glEnableClientState(GL10.GL_COLOR_ARRAY);

    gl.glColorPointer(4, GL10.GL_FLOAT, 0, colorBuffer);

    gl.glDrawElements(GL10.GL_TRIANGLES, caras.length, GL10.GL_UNSIGNED_SHORT, indexBuffer);

    gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);

    gl.glDisable(GL10.GL_CULL_FACE);

    gl.glDisableClientState(GL10.GL_COLOR_ARRAY);          


实际结果的外图:http://i60.tinypic.com/v3zuvr.png

【问题讨论】:

【参考方案1】:

两个问题:

OpenGL 索引基于 0,而此代码使用基于 1 的索引。 颜色数组需要包含每个顶点的颜色。由于有 8 个顶点,因此需要 8 种颜色,即 8 * 4 = 32 个浮点数。

【讨论】:

以上是关于在 android 中使用 opengl 在 glsurfaceview 中显示 3D 模型的问题的主要内容,如果未能解决你的问题,请参考以下文章

在 OpenCL 内核 (android) 中读取 GL_UNSIGNED_BYTE OpenGL texture2D

Android Opengl OES 纹理渲染到 GL_TEXTURE_2D

Android Opengl OES 纹理渲染到 GL_TEXTURE_2D

如何在Android上使用OpenGL ES 2.0绘制点

使用 drawtexture (OpenGl ES Android) 旋转精灵的问题

Android 上的 Opengl ES:如何使用 gluUnProject?