Android NDK中的OpenGL ES 2.0:没有被绘制

时间:2014-10-28 01:36:30

标签: android c++ opengl-es android-ndk opengl-es-2.0

我有一个2D游戏项目,我正在移植到使用OpenGL ES 2.0的Android。我无法在屏幕上绘制任何内容(除了清除屏幕的纯色)。在我的Windows环境中运行时,所有内容都可以正常运行,但当然不同版本的OpenGL环境设置也不同。

我按照原生活动样本并从其他几个OpenGL ES 2.0资源中获取建议,以构建我目前拥有的内容。

我已经检查了我知道的所有内容,没有出现任何异常结果。如上所述,glClear有效,并显示glClearColor设置的颜色。我也知道每个帧都在渲染,因为逐帧更改glClearColor会显示不同的颜色。当然,应用程序正确编译。我的纹理是从应用程序缓存中的正确位置加载的。 glGetError在流程的每一步都返回GL_NO_ERROR,因此我正在做的事情似乎被OpenGL接受。我的着色器加载没有错误。我还在一些仿真器和我的物理android设备上测试了这个,所以它没有被本地化到特定的设备配置。

我推测在初始化和设置OpenGL时必定会出现一些错误。我希望有更多精通OpenGL ES的人能够帮助解决我的问题。我正在粘贴下面代码的不同相关部分。 engine是我目前因懒惰而使用的全局结构。

初始化显示

static int AND_InitDisplay() {

    // Desired display attributes
    const EGLint attribs[] = {
            EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
            EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
            EGL_BLUE_SIZE, 8,
            EGL_GREEN_SIZE, 8,
            EGL_RED_SIZE, 8,
            EGL_ALPHA_SIZE, 8,
            EGL_DEPTH_SIZE, 16,
            EGL_NONE
    };
    EGLint w, h, dummy, format;
    EGLint numConfigs;
    EGLConfig config;
    EGLSurface surface;
    EGLContext context;

    EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
    eglInitialize(display, 0, 0);
    eglChooseConfig(display, attribs, &config, 1, &numConfigs);
    eglGetConfigAttrib(display, config, EGL_NATIVE_VISUAL_ID, &format);

    ANativeWindow_setBuffersGeometry(engine->app->window, 0, 0, format);

    surface = eglCreateWindowSurface(display, config, engine->app->window, NULL);

    EGLint const attrib_list[3] = {EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE};
    context = eglCreateContext(display, config, NULL, attrib_list);

    if (eglMakeCurrent(display, surface, surface, context) == EGL_FALSE) {
        LOGW("Unable to eglMakeCurrent");
        return -1;
    }

    eglQuerySurface(display, surface, EGL_WIDTH, &w);
    eglQuerySurface(display, surface, EGL_HEIGHT, &h);

    engine->display = display;
    engine->context = context;
    engine->surface = surface;
    engine->width = w;
    engine->height = h;

    // Initialize GL state.
    glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);

    return 0;
}

绘制框架

static void AND_drawFrame() {
    if (engine->display == NULL) {
        LOGW("DB E: DISPLAY IS NULL");
        // No display.
        return;
    }

    // Clearing with red color. This displays properly.
    glClearColor(1.f, 0.f, 0.f, 1.f);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    // eglSwapBuffers results in no visible change
    eglSwapBuffers(engine->display, engine->surface);
}

准备VBO数据的示例

我知道很多人不喜欢将多个VBO用于相同的几何体。我很想知道这段代码是不正统的还是不正确的,但除非它是我问题的根源,否则我不会专注于此。

GLfloat charPosVerts[] = {

    p0.x, p0.y, 0.f,
    p1.x, p0.y, 0.f,
    p1.x, p1.y, 0.f,

    p0.x, p0.y, 0.f,
    p1.x, p1.y, 0.f,
    p0.x, p1.y, 0.f
};

GLfloat charTexVerts[] = {
    0.0, 0.0,
    textures[texid].w, 0.0,
    textures[texid].w, textures[texid].h,

    0.0, 0.0,
    textures[texid].w, textures[texid].h,
    0.0, textures[texid].h
};

GLfloat charColorVerts[] = {
    e->color.r, e->color.g, e->color.b, e->color.a,
    e->color.r, e->color.g, e->color.b, e->color.a,
    e->color.r, e->color.g, e->color.b, e->color.a,

    e->color.r, e->color.g, e->color.b, e->color.a,
    e->color.r, e->color.g, e->color.b, e->color.a,
    e->color.r, e->color.g, e->color.b, e->color.a
};

glGenBuffers(1, &(e->vboPos));
glGenBuffers(1, &(e->vboTex));
glGenBuffers(1, &(e->vboColor));

glBindBuffer(GL_ARRAY_BUFFER, e->vboPos);
glBufferData(GL_ARRAY_BUFFER, sizeof(charPosVerts), charPosVerts, GL_DYNAMIC_DRAW);
glVertexAttribPointer(shaderIDs.attribPosition, 3, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(shaderIDs.attribPosition);

glBindBuffer(GL_ARRAY_BUFFER, e->vboTex);
glBufferData(GL_ARRAY_BUFFER, sizeof(charTexVerts), charTexVerts, GL_DYNAMIC_DRAW);
glVertexAttribPointer(shaderIDs.attribTexCoord, 2, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(shaderIDs.attribTexCoord);

glBindBuffer(GL_ARRAY_BUFFER, e->vboColor);
glBufferData(GL_ARRAY_BUFFER, sizeof(charColorVerts), charColorVerts, GL_DYNAMIC_DRAW);
glVertexAttribPointer(shaderIDs.attribColors, 4, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(shaderIDs.attribColors);

绘制VBO的示例

glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, CORE_GetBmpOpenGLTex(texix));
glUniform1i(shaderIDs.uniTexture, 0);

// Draw the sprite
glBindBuffer(GL_ARRAY_BUFFER, e->vboPos);
glVertexAttribPointer(shaderIDs.attribPosition, 3, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(shaderIDs.attribPosition);

glBindBuffer(GL_ARRAY_BUFFER, e->vboTex);
glVertexAttribPointer(shaderIDs.attribTexCoord, 2, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(shaderIDs.attribTexCoord);

glBindBuffer(GL_ARRAY_BUFFER, e->vboColor);
glVertexAttribPointer(shaderIDs.attribColors, 4, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(shaderIDs.attribColors);

glDrawArrays(GL_TRIANGLES, 0, 18);

顶点着色器

着色器非常简单。

attribute vec3 position;
attribute vec2 texCoord;
attribute vec4 colors;

varying vec2 texCoordVar;
varying vec4 colorsVar;

void main() {
    gl_Position = vec4(position, 1.0);
    texCoordVar = texCoord;
    colorsVar = colors;
}

片段着色器

uniform sampler2D texture;

varying vec2 texCoordVar;
varying vec4 colorsVar;

void main()
{
    gl_FragColor = texture2D(texture, texCoordVar) * colorsVar;
}

感谢您查看这篇长篇文章。非常感谢帮助。

1 个答案:

答案 0 :(得分:3)

发布的代码没有绘制任何内容。来自AND_drawFrame()函数:

// Clearing with red color. This displays properly.
glClearColor(1.f, 0.f, 0.f, 1.f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

// eglSwapBuffers results in no visible change
eglSwapBuffers(engine->display, engine->surface);

基于此,绘图代码要么永远不会被调用,要么在绘图后清除窗口,这会消除之前绘制的所有内容。