Android OpenGL ES 示例教程 – wiki基地

Android OpenGL ES 示例教程:打造你的第一个 3D 应用

本教程将引导你一步步创建一个简单的 Android OpenGL ES 应用,绘制一个旋转的彩色三角形。我们将涵盖 OpenGL ES 的基础知识,包括着色器、缓冲区、变换等概念,并结合代码示例进行详细讲解。

一、设置开发环境

确保你的 Android Studio 已安装并配置了必要的 SDK 和 NDK。创建一个新的 Android 项目,选择 “Empty Activity” 模板。

二、添加 OpenGL ES 依赖

app/build.gradle 文件中添加以下依赖:

gradle
dependencies {
implementation 'androidx.appcompat:appcompat:1.5.1'
implementation 'com.google.android.material:material:1.7.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
}

三、创建 GLSurfaceView

GLSurfaceView 是用于渲染 OpenGL ES 图形的视图。在你的布局文件中添加一个 GLSurfaceView

xml
<android.opengl.GLSurfaceView
android:id="@+id/glSurfaceView"
android:layout_width="match_parent"
android:layout_height="match_parent" />

四、创建 Renderer

Renderer 接口负责绘制 OpenGL ES 图形。创建一个名为 TriangleRenderer 的类,实现 GLSurfaceView.Renderer 接口:

“`java
import android.opengl.GLES20;
import android.opengl.GLSurfaceView;
import android.opengl.Matrix;

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

public class TriangleRenderer implements GLSurfaceView.Renderer {

private Triangle mTriangle;
private final float[] mMVPMatrix = new float[16];
private final float[] mProjectionMatrix = new float[16];
private final float[] mViewMatrix = new float[16];
private final float[] mRotationMatrix = new float[16];
private float mAngle;

@Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
    GLES20.glClearColor(0.0f, 0.0f, 0.0f, 1.0f); // 设置背景颜色
    mTriangle = new Triangle();
}

@Override
public void onSurfaceChanged(GL10 gl, int width, int height) {
    GLES20.glViewport(0, 0, width, height); // 设置视口

    float ratio = (float) width / height;
    Matrix.frustumM(mProjectionMatrix, 0, -ratio, ratio, -1, 1, 3, 7);
}

@Override
public void onDrawFrame(GL10 gl) {
    GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT); // 清除屏幕

    // 设置相机位置
    Matrix.setLookAtM(mViewMatrix, 0, 0, 0, -3, 0f, 0f, 0f, 0f, 1.0f, 0.0f);

    // 计算变换矩阵
    Matrix.multiplyMM(mMVPMatrix, 0, mProjectionMatrix, 0, mViewMatrix, 0);

    // 创建旋转变换
    float[] scratch = new float[16];
    Matrix.setRotateM(mRotationMatrix, 0, mAngle, 0, 0, -1.0f);
    Matrix.multiplyMM(scratch, 0, mMVPMatrix, 0, mRotationMatrix, 0);

    // 绘制三角形
    mTriangle.draw(scratch);

    mAngle += 0.5f; // 旋转角度递增
}

}

“`

五、创建 Triangle 类

Triangle 类负责存储三角形的顶点数据和绘制逻辑。

“`java
import android.opengl.GLES20;

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

public class Triangle {

private final String vertexShaderCode =
        "uniform mat4 uMVPMatrix;" +
                "attribute vec4 vPosition;" +
                "void main() {" +
                "  gl_Position = uMVPMatrix * vPosition;" +
                "}";

private final String fragmentShaderCode =
        "precision mediump float;" +
                "uniform vec4 vColor;" +
                "void main() {" +
                "  gl_FragColor = vColor;" +
                "}";

private final int mProgram;
private int mPositionHandle;
private int mColorHandle;
private int mMVPMatrixHandle;

private FloatBuffer vertexBuffer;
private final int COORDS_PER_VERTEX = 3;
private final int vertexStride = COORDS_PER_VERTEX * 4; // 4 bytes per vertex

static float triangleCoords[] = {   // in counterclockwise order:
        0.0f,  0.622008459f, 0.0f, // top
        -0.5f, -0.311004243f, 0.0f, // bottom left
        0.5f, -0.311004243f, 0.0f  // bottom right
};

float color[] = { 0.63671875f, 0.76953125f, 0.22265625f, 1.0f };


public Triangle() {
    ByteBuffer bb = ByteBuffer.allocateDirect(triangleCoords.length * 4);
    bb.order(ByteOrder.nativeOrder());
    vertexBuffer = bb.asFloatBuffer();
    vertexBuffer.put(triangleCoords);
    vertexBuffer.position(0);

    int vertexShader = loadShader(GLES20.GL_VERTEX_SHADER, vertexShaderCode);
    int fragmentShader = loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentShaderCode);

    mProgram = GLES20.glCreateProgram();
    GLES20.glAttachShader(mProgram, vertexShader);
    GLES20.glAttachShader(mProgram, fragmentShader);
    GLES20.glLinkProgram(mProgram);
}

public void draw(float[] mvpMatrix) {
    GLES20.glUseProgram(mProgram);

    mPositionHandle = GLES20.glGetAttribLocation(mProgram, "vPosition");
    GLES20.glEnableVertexAttribArray(mPositionHandle);
    GLES20.glVertexAttribPointer(mPositionHandle, COORDS_PER_VERTEX,
            GLES20.GL_FLOAT, false,
            vertexStride, vertexBuffer);

    mColorHandle = GLES20.glGetUniformLocation(mProgram, "vColor");
    GLES20.glUniform4fv(mColorHandle, 1, color, 0);

    mMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix");
    GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, mvpMatrix, 0);

    GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, triangleCoords.length / COORDS_PER_VERTEX);

    GLES20.glDisableVertexAttribArray(mPositionHandle);
}

public static int loadShader(int type, String shaderCode){
    int shader = GLES20.glCreateShader(type);
    GLES20.glShaderSource(shader, shaderCode);
    GLES20.glCompileShader(shader);
    return shader;
}

}
“`

六、在 Activity 中初始化

在你的 Activity 中,获取 GLSurfaceView 并设置渲染器:

“`java
import android.opengl.GLSurfaceView;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;

public class MainActivity extends AppCompatActivity {

private GLSurfaceView glSurfaceView;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    glSurfaceView = new GLSurfaceView(this);

    //设置OpenGL ES版本
    glSurfaceView.setEGLContextClientVersion(2);


    glSurfaceView.setRenderer(new TriangleRenderer());


    setContentView(glSurfaceView);


}

@Override
protected void onPause(){
    super.onPause();
    glSurfaceView.onPause();
}

@Override
protected void onResume(){
    super.onResume();
    glSurfaceView.onResume();
}

}
“`

七、运行应用

现在你可以运行你的应用,应该会看到一个绕 Z 轴旋转的彩色三角形。

八、进阶学习

  • 纹理映射:学习如何将图像应用于 3D 对象。
  • 光照:学习如何模拟光照效果,使 3D 场景更加逼真。
  • 模型加载:学习如何加载复杂的 3D 模型。
  • 更复杂的着色器:学习如何编写更高级的着色器,实现更丰富的视觉效果.

本教程提供了一个简单的 OpenGL ES 入门示例,希望能帮助你开启 Android 3D 图形编程之旅。 通过不断学习和实践,你可以创建更复杂、更精美的 3D 应用。 记住,理解 OpenGL ES 的核心概念是关键,这将帮助你更好地掌握 3D 图形编程技巧。 不断探索和尝试,你将能够创造出令人惊叹的视觉效果。

发表评论

您的邮箱地址不会被公开。 必填项已用 * 标注

滚动至顶部