2017-04-15 89 views
-1

我在Visual Studio 2017中创建了一个“原生android应用程序”项目。 它编译和运行良好,但是当我添加简单的三角形代码时,三角形没有显示出来。OpenGL ES ANDROID C++错误

我的代码:

/* 
* Copyright (C) 2010 The Android Open Source Project 
* 
* Licensed under the Apache License, Version 2.0 (the "License"); 
* you may not use this file except in compliance with the License. 
* You may obtain a copy of the License at 
* 
* http://www.apache.org/licenses/LICENSE-2.0 
* 
* Unless required by applicable law or agreed to in writing, software 
* distributed under the License is distributed on an "AS IS" BASIS, 
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
* See the License for the specific language governing permissions and 
* limitations under the License. 
* 
*/ 

#define LOGI(...)((void) __android_log_print(ANDROID_LOG_INFO, "AndroidProject1.NativeActivity", __VA_ARGS__))# define LOGW(...)((void) __android_log_print(ANDROID_LOG_WARN, "AndroidProject1.NativeActivity", __VA_ARGS__)) 

#define LOG_TAG "libgl2jni" 
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__) 
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__) 

static void printGLString(const char * name, GLenum s) { 
    const char * v = (const char *) glGetString(s); 
    LOGI("GL %s = %s\n", name, v); 
} 

static void checkGlError(const char * op) { 
    for (GLint error = glGetError(); error; error = glGetError()) { 
     LOGI("after %s() glError (0x%x)\n", op, error); 
    } 
} 

static const char gVertexShader[] = 
    "attribute vec4 vPosition;\n" 
    "void main() {\n" 
    " gl_Position = vPosition;\n" 
    "}\n"; 

static const char gFragmentShader[] = 
    "precision mediump float;\n" 
    "void main() {\n" 
    " gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);\n" 
    "}\n"; 

GLuint loadShader(GLenum shaderType, 
    const char * pSource) { 
    GLuint shader = glCreateShader(shaderType); 
    if (shader) { 
     glShaderSource(shader, 1, & pSource, NULL); 
     glCompileShader(shader); 
     GLint compiled = 0; 
     glGetShaderiv(shader, GL_COMPILE_STATUS, & compiled); 
     if (!compiled) { 
      GLint infoLen = 0; 
      glGetShaderiv(shader, GL_INFO_LOG_LENGTH, & infoLen); 
      if (infoLen) { 
       char * buf = (char *) malloc(infoLen); 
       if (buf) { 
        glGetShaderInfoLog(shader, infoLen, NULL, buf); 
        LOGE("Could not compile shader %d:\n%s\n", 
         shaderType, buf); 
        free(buf); 
       } 
       glDeleteShader(shader); 
       shader = 0; 
      } 
     } 
    } 
    return shader; 
} 

GLuint createProgram(const char * pVertexSource, 
    const char * pFragmentSource) { 
    GLuint vertexShader = loadShader(GL_VERTEX_SHADER, pVertexSource); 
    if (!vertexShader) { 
     return 0; 
    } 

    GLuint pixelShader = loadShader(GL_FRAGMENT_SHADER, pFragmentSource); 
    if (!pixelShader) { 
     return 0; 
    } 

    GLuint program = glCreateProgram(); 
    if (program) { 
     glAttachShader(program, vertexShader); 
     checkGlError("glAttachShader"); 
     glAttachShader(program, pixelShader); 
     checkGlError("glAttachShader"); 
     glLinkProgram(program); 
     GLint linkStatus = GL_FALSE; 
     glGetProgramiv(program, GL_LINK_STATUS, & linkStatus); 
     if (linkStatus != GL_TRUE) { 
      GLint bufLength = 0; 
      glGetProgramiv(program, GL_INFO_LOG_LENGTH, & bufLength); 
      if (bufLength) { 
       char * buf = (char *) malloc(bufLength); 
       if (buf) { 
        glGetProgramInfoLog(program, bufLength, NULL, buf); 
        LOGE("Could not link program:\n%s\n", buf); 
        free(buf); 
       } 
      } 
      glDeleteProgram(program); 
      program = 0; 
     } 
    } 
    return program; 
} 

GLuint gProgram; 
GLuint gvPositionHandle; 

/** 
* Our saved state data. 
*/ 
struct saved_state { 
    float angle; 
    int32_t x; 
    int32_t y; 
}; 

/** 
* Shared state for our app. 
*/ 
struct engine { 
    struct android_app * app; 

    ASensorManager * sensorManager; 
    const ASensor * accelerometerSensor; 
    ASensorEventQueue * sensorEventQueue; 

    int animating; 
    EGLDisplay display; 
    EGLSurface surface; 
    EGLContext context; 
    int32_t width; 
    int32_t height; 
    struct saved_state state; 
}; 

/** 
* Initialize an EGL context for the current display. 
*/ 
static int engine_init_display(struct engine * engine) { 
    // initialize OpenGL ES and EGL 

    /* 
    * Here specify the attributes of the desired configuration. 
    * Below, we select an EGLConfig with at least 8 bits per color 
    * component compatible with on-screen windows 
    */ 
    const EGLint attribs[] = { 
     EGL_SURFACE_TYPE, 
     EGL_WINDOW_BIT, 
     EGL_BLUE_SIZE, 
     8, 
     EGL_GREEN_SIZE, 
     8, 
     EGL_RED_SIZE, 
     8, 
     EGL_NONE 
    }; 
    EGLint w, h, format; 
    EGLint numConfigs; 
    EGLConfig config; 
    EGLSurface surface; 
    EGLContext context; 

    EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY); 

    eglInitialize(display, 0, 0); 

    /* Here, the application chooses the configuration it desires. In this 
    * sample, we have a very simplified selection process, where we pick 
    * the first EGLConfig that matches our criteria */ 
    eglChooseConfig(display, attribs, & config, 1, & numConfigs); 

    /* EGL_NATIVE_VISUAL_ID is an attribute of the EGLConfig that is 
    * guaranteed to be accepted by ANativeWindow_setBuffersGeometry(). 
    * As soon as we picked a EGLConfig, we can safely reconfigure the 
    * ANativeWindow buffers to match, using EGL_NATIVE_VISUAL_ID. */ 
    eglGetConfigAttrib(display, config, EGL_NATIVE_VISUAL_ID, & format); 

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

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

    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; 
    engine->state.angle = 0; 

    // Initialize GL state. 
    //glEnable(GL_CULL_FACE); 
    glDisable(GL_DEPTH_TEST); 

    gProgram = createProgram(gVertexShader, gFragmentShader); 

    gvPositionHandle = glGetAttribLocation(gProgram, "vPosition"); 

    glViewport(0, 0, w, h); 

    return 0; 
} 

const GLfloat gTriangleVertices[] = { 
    0.0 f, 
    0.5 f, 
    -0.5 f, 
    -0.5 f, 
    0.5 f, 
    -0.5 f 
}; 

/** 
* Just the current frame in the display. 
*/ 
static void engine_draw_frame(struct engine * engine) { 
    if (engine->display == NULL) { 
     // No display. 
     return; 
    } 

    glClearColor(0.0 f, 0.0 f, 0.0 f, 1.0 f); 
    glClear(GL_COLOR_BUFFER_BIT); 

    glUseProgram(gProgram); 
    checkGlError("glUseProgram"); 

    glVertexAttribPointer(gvPositionHandle, 2, GL_FLOAT, GL_FALSE, 0, gTriangleVertices); 
    checkGlError("glVertexAttribPointer"); 
    glEnableVertexAttribArray(gvPositionHandle); 
    checkGlError("glEnableVertexAttribArray"); 
    glDrawArrays(GL_TRIANGLES, 0, 3); 
    checkGlError("glDrawArrays"); 

    eglSwapBuffers(engine->display, engine->surface); 
} 

/** 
* Tear down the EGL context currently associated with the display. 
*/ 
static void engine_term_display(struct engine * engine) { 
    if (engine->display != EGL_NO_DISPLAY) { 
     eglMakeCurrent(engine->display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); 
     if (engine-> context != EGL_NO_CONTEXT) { 
      eglDestroyContext(engine->display, engine->context); 
     } 
     if (engine->surface != EGL_NO_SURFACE) { 
      eglDestroySurface(engine->display, engine->surface); 
     } 
     eglTerminate(engine->display); 
    } 
    engine->animating = 0; 
    engine->display = EGL_NO_DISPLAY; 
    engine->context = EGL_NO_CONTEXT; 
    engine->surface = EGL_NO_SURFACE; 
} 

/** 
* Process the next input event. 
*/ 
static int32_t engine_handle_input(struct android_app * app, AInputEvent * event) { 
    struct engine * engine = (struct engine *) app->userData; 
    if (AInputEvent_getType(event) == AINPUT_EVENT_TYPE_MOTION) { 
     engine->state.x = AMotionEvent_getX(event, 0); 
     engine->state.y = AMotionEvent_getY(event, 0); 
     return 1; 
    } 
    return 0; 
} 

/** 
* Process the next main command. 
*/ 
static void engine_handle_cmd(struct android_app * app, int32_t cmd) { 
    struct engine * engine = (struct engine *) app->userData; 
    switch (cmd) { 
    case APP_CMD_SAVE_STATE: 
     // The system has asked us to save our current state. Do so. 
     engine->app-> savedState = malloc(sizeof(struct saved_state)); * ((struct saved_state *) engine->app->savedState) = engine->state; 
     engine->app->savedStateSize = sizeof(struct saved_state); 
     break; 
    case APP_CMD_INIT_WINDOW: 
     // The window is being shown, get it ready. 
     if (engine->app-> window != NULL) { 
      engine_init_display(engine); 
      engine_draw_frame(engine); 
     } 
     break; 
    case APP_CMD_TERM_WINDOW: 
     // The window is being hidden or closed, clean it up. 
     engine_term_display(engine); 
     break; 
    case APP_CMD_GAINED_FOCUS: 
     // When our app gains focus, we start monitoring the accelerometer. 
     if (engine->accelerometerSensor != NULL) { 
      ASensorEventQueue_enableSensor(engine->sensorEventQueue, 
       engine->accelerometerSensor); 
      // We'd like to get 60 events per second (in us). 
      ASensorEventQueue_setEventRate(engine->sensorEventQueue, 
       engine->accelerometerSensor, (1000 L/60) * 1000); 
     } 
     break; 
    case APP_CMD_LOST_FOCUS: 
     // When our app loses focus, we stop monitoring the accelerometer. 
     // This is to avoid consuming battery while not being used. 
     if (engine->accelerometerSensor != NULL) { 
      ASensorEventQueue_disableSensor(engine->sensorEventQueue, 
       engine->accelerometerSensor); 
     } 
     // Also stop animating. 
     engine->animating = 0; 
     engine_draw_frame(engine); 
     break; 
    } 
} 

/** 
* This is the main entry point of a native application that is using 
* android_native_app_glue. It runs in its own thread, with its own 
* event loop for receiving input events and doing other things. 
*/ 
void android_main(struct android_app * state) { 
    struct engine engine; 

    memset(& engine, 0, sizeof(engine)); 
    state->userData = & engine; 
    state->onAppCmd = engine_handle_cmd; 
    state->onInputEvent = engine_handle_input; 
    engine.app = state; 

    // Prepare to monitor accelerometer 
    engine.sensorManager = ASensorManager_getInstance(); 
    engine.accelerometerSensor = ASensorManager_getDefaultSensor(engine.sensorManager, 
     ASENSOR_TYPE_ACCELEROMETER); 
    engine.sensorEventQueue = ASensorManager_createEventQueue(engine.sensorManager, 
     state->looper, LOOPER_ID_USER, NULL, NULL); 

    if (state->savedState != NULL) { 
     // We are starting with a previous saved state; restore from it. 
     engine.state = * (struct saved_state *) state->savedState; 
    } 

    engine.animating = 1; 

    // loop waiting for stuff to do. 

    while (1) { 
     // Read all pending events. 
     int ident; 
     int events; 
     struct android_poll_source * source; 

     // If not animating, we will block forever waiting for events. 
     // If animating, we loop until all events are read, then continue 
     // to draw the next frame of animation. 
     while ((ident = ALooper_pollAll(engine.animating ? 0 : -1, NULL, & events, 
       (void * *) & source)) >= 0) { 

      // Process this event. 
      if (source != NULL) { 
       source->process(state, source); 
      } 

      // Check if we are exiting. 
      if (state->destroyRequested != 0) { 
       engine_term_display(& engine); 
       return; 
      } 
     } 

     if (engine.animating) { 
      // Drawing is throttled to the screen update rate, so there 
      // is no need to do timing here. 
      engine_draw_frame(&engine); 
     } 
    } 
} 

我也更新pch.h导入OpenGL ES 2.0的

+0

请在这里显示你的代码(我对随机链接过敏)。另请参阅如何创建[MCVE]。 –

+0

哇有人编辑它。非常感谢你,genpfault – IAS0601

+0

@RichardCritten:半固定。 OP仍然需要修复格式。 – genpfault

回答

0

我固定它。

如果你们有这个问题,这是你应该做的:

下面的代码添加到静态INT engine_init_display(结构发动机*引擎)功能

const EGLint contextAttribs[] = { 
    EGL_CONTEXT_CLIENT_VERSION, 2, 
    EGL_NONE 
}; 

并更换

context = eglCreateContext(display, config, NULL, NULL); 

context = eglCreateContext(display, config, EGL_NO_CONTEXT, contextAttribs);