You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

在Android Studio中开发GLES 3.0三角形绘制应用遇阻求助

解决Android Studio中GLES 3.0 VAO+VBO绘制三角形的问题

我完全懂你的挫败感!作为熟悉桌面现代OpenGL的开发者,转去GLES 3.0尤其是在Android环境下,确实会因为VAO的支持和教程的滞后性踩很多坑。下面我会给你一个完整的、使用VAO+VBO的GLES3.0三角形绘制示例,同时点明你可能踩中的关键问题。


一、先确认基础配置

确保你的Android项目满足以下前提:

  • AndroidManifest.xml中声明GLES3.0依赖:
    <uses-feature android:glEsVersion="0x00030000" android:required="true" />
    
  • 给GLSurfaceView设置GLES3.0上下文:
    glSurfaceView.setEGLContextClientVersion(3);
    

二、完整Native层C++核心代码

因为你熟悉C++,这里直接给出Native层的渲染逻辑,包含VAO、VBO的创建与使用:

1. 着色器代码(硬编码在C++中)

// 顶点着色器(GLES3.0必须用300 es版本)
const char* vertexShaderSource = R"(
    #version 300 es
    layout(location = 0) in vec3 aPos;
    void main() {
        gl_Position = vec4(aPos, 1.0);
    }
)";

// 片段着色器(必须声明精度)
const char* fragmentShaderSource = R"(
    #version 300 es
    precision mediump float;
    out vec4 FragColor;
    void main() {
        FragColor = vec4(1.0, 0.5, 0.2, 1.0);
    }
)";

2. 渲染核心逻辑

#include <GLES3/gl3.h>

// 全局变量(实际项目建议封装为类成员)
GLuint shaderProgram;
GLuint VAO, VBO;

// 初始化:Surface创建时调用
void initGL() {
    // 1. 编译链接着色器程序
    GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
    glShaderSource(vertexShader, 1, &vertexShaderSource, nullptr);
    glCompileShader(vertexShader);

    GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
    glShaderSource(fragmentShader, 1, &fragmentShaderSource, nullptr);
    glCompileShader(fragmentShader);

    shaderProgram = glCreateProgram();
    glAttachShader(shaderProgram, vertexShader);
    glAttachShader(shaderProgram, fragmentShader);
    glLinkProgram(shaderProgram);

    // 清理临时着色器对象
    glDeleteShader(vertexShader);
    glDeleteShader(fragmentShader);

    // 2. 创建VAO、VBO并配置
    float vertices[] = {
        -0.5f, -0.5f, 0.0f,
         0.5f, -0.5f, 0.0f,
         0.0f,  0.5f, 0.0f
    };

    glGenVertexArrays(1, &VAO);
    glGenBuffers(1, &VBO);

    // 绑定VAO(关键:GLES3.0中绑定VAO后,后续的VBO配置会被记录到VAO)
    glBindVertexArray(VAO);

    glBindBuffer(GL_ARRAY_BUFFER, VBO);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

    // 配置顶点属性指针
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
    glEnableVertexAttribArray(0);

    // 解绑(顺序不影响,VAO已记录配置)
    glBindBuffer(GL_ARRAY_BUFFER, 0);
    glBindVertexArray(0);
}

// 渲染:每帧调用
void drawFrame() {
    glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT);

    glUseProgram(shaderProgram);
    // 绑定VAO后直接绘制,无需重复配置顶点属性
    glBindVertexArray(VAO);
    glDrawArrays(GL_TRIANGLES, 0, 3);
}

// 清理:Surface销毁时调用
void cleanupGL() {
    glDeleteVertexArrays(1, &VAO);
    glDeleteBuffers(1, &VBO);
    glDeleteProgram(shaderProgram);
}

三、你可能踩中的关键坑

  1. 上下文版本错误:如果GLSurfaceView用的是GLES2.0上下文,glGenVertexArrays会直接失败(GLES2.0不支持VAO),一定要确认setEGLContextClientVersion(3)
  2. 着色器版本与语法错误:GLES3.0着色器必须用#version 300 es,片段着色器必须声明精度,否则会编译失败。
  3. VAO绑定时机错误:必须在配置VBO和顶点属性指针之前绑定VAO,否则配置不会被VAO记录;绘制时只需绑定VAO即可。
  4. 线程问题:Android的GLES操作必须在GLSurfaceView的渲染线程执行,主线程调用GL函数会导致崩溃或无渲染结果。

四、Java层简单适配

如果用JNI调用Native代码,GLSurfaceView.Renderer可以这么写:

public class MyGLRenderer implements GLSurfaceView.Renderer {
    static {
        System.loadLibrary("native-lib");
    }

    public native void initGL();
    public native void drawFrame();
    public native void cleanupGL();

    @Override
    public void onSurfaceCreated(GL10 gl, EGLConfig config) {
        initGL();
    }

    @Override
    public void onSurfaceChanged(GL10 gl, int width, int height) {
        gl.glViewport(0, 0, width, height);
    }

    @Override
    public void onDrawFrame(GL10 gl) {
        drawFrame();
    }
}

把这个Renderer设置给你的GLSurfaceView即可。

如果还是有问题,建议用glGetShaderivglGetProgramiv获取着色器编译/链接的日志,这是排查GLES问题的核心手段。

内容的提问来源于stack exchange,提问作者user7986617

火山引擎 最新活动