掌機 - Pandora(Rebirth) - SuperZaxxon - OpenGL ES 2.0 - Draw 2 Textures



參考資訊:
https://pandorawiki.org/GLES

main.c

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include <dlfcn.h>
#include <unistd.h>
#include <EGL/egl.h>
#include <GLES2/gl2.h>
  
#define LCD_W   800
#define LCD_H   480
  
const char *vShaderSrc =
    "attribute vec4 a_position;    \n"
    "attribute vec2 a_texCoord;    \n"
    "varying vec2 v_texCoord;      \n"
    "void main()                   \n"
    "{                             \n"
    "    gl_Position = a_position; \n"
    "    v_texCoord = a_texCoord;  \n"
    "}                             \n";
    
const char *fShaderSrc =
    "precision mediump float;                                  \n"
    "varying vec2 v_texCoord;                                  \n"
    "uniform sampler2D s_texture;                              \n"
    "void main()                                               \n"
    "{                                                         \n"
    "    vec3 tex = texture2D(s_texture, v_texCoord).rgb;      \n"
    "    gl_FragColor = vec4(tex, 1.0);                        \n"
    "}                                                         \n";
  
int main(int argc, char** argv)
{
    EGLint egl_major = 0;
    EGLint egl_minor = 0;
    EGLint num_configs = 0;
    EGLConfig configs = {0};
    EGLDisplay display = EGL_NO_DISPLAY;
    EGLSurface surface = EGL_NO_SURFACE;
    EGLContext context = EGL_NO_CONTEXT;
    EGLint config_attribs[] = {
        EGL_SURFACE_TYPE,    EGL_WINDOW_BIT,
        EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
        EGL_RED_SIZE,   5,
        EGL_GREEN_SIZE, 6,
        EGL_BLUE_SIZE,  5,
        EGL_ALPHA_SIZE, 0,
        EGL_NONE
    };
    EGLint window_attributes[] = { 
        EGL_RENDER_BUFFER, EGL_BACK_BUFFER,
        EGL_NONE
    };
    EGLint const context_attributes[] = {
        EGL_CONTEXT_CLIENT_VERSION, 2,
        EGL_NONE,
    };
    GLuint vShader = 0;
    GLuint fShader = 0;
    GLuint pObject = 0;
    GLint compiled = 0;
  
    int x = 0;
    int y = 0;
    uint32_t *p = NULL;
    GLuint texID[2] = {0};
    GLubyte *buf = NULL;
  
    GLfloat vVertices[] = {
       -1.0f,  1.0f, 0.0f,      0.0f,  0.0f,
       -1.0f, -1.0f, 0.0f,      0.0f,  1.0f,
        1.0f, -1.0f, 0.0f,      1.0f,  1.0f,
        1.0f,  1.0f, 0.0f,      1.0f,  0.0f
    };
    GLushort indices[] = {0, 1, 2, 0, 2, 3};
  
    display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
    eglInitialize(display, &egl_major, &egl_minor);
    eglChooseConfig(display, config_attribs, &configs, 1, &num_configs);
    surface = eglCreateWindowSurface(display, configs, 0, window_attributes);
    context = eglCreateContext(display, configs, EGL_NO_CONTEXT, context_attributes);
    eglMakeCurrent(display, surface, surface, context);
  
    vShader = glCreateShader(GL_VERTEX_SHADER);
    glShaderSource(vShader, 1, &vShaderSrc, NULL);
    glCompileShader(vShader);
    glGetShaderiv(vShader, GL_COMPILE_STATUS, &compiled);
  
    fShader = glCreateShader(GL_FRAGMENT_SHADER);
    glShaderSource(fShader, 1, &fShaderSrc, NULL);
    glCompileShader(fShader);
    glGetShaderiv(fShader, GL_COMPILE_STATUS, &compiled);
   
    pObject = glCreateProgram();
    glAttachShader(pObject, vShader);
    glAttachShader(pObject, fShader);
    glLinkProgram(pObject);
    glUseProgram(pObject);
  
    GLint posLoc = glGetAttribLocation(pObject, "a_position");
    GLint texLoc = glGetAttribLocation(pObject, "a_texCoord");
    GLint samLoc = glGetUniformLocation(pObject, "s_texture");
  
    glGenTextures(2, texID);
    glViewport(0, 0, LCD_W, LCD_H);
    glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT);
  
    buf = malloc(LCD_W * LCD_H * 4);
    p = (uint32_t *)buf;
    for (y = 0; y < LCD_H; y++) {
        for (x = 0; x < LCD_W; x++) {
            *p++ = 0xff0000ff;
        }
    }
    glBindTexture(GL_TEXTURE_2D, texID[0]);
    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, LCD_W, LCD_H, 0, GL_RGBA, GL_UNSIGNED_BYTE, buf);
  
    p = (uint32_t *)buf;
    for (y = 0; y < LCD_H; y++) {
        for (x = 0; x < LCD_W; x++) {
            *p++ = 0xff00ff00;
        }
    }
    glBindTexture(GL_TEXTURE_2D, texID[1]);
    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, LCD_W, LCD_H, 0, GL_RGBA, GL_UNSIGNED_BYTE, buf);
  
    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D, texID[0]);
    vVertices[0] = -1.0;
    vVertices[1] = 1.0;
    vVertices[2] = 0.0;
    vVertices[5] = -1.0;
    vVertices[6] = 0.0;
    vVertices[7] = 0.0;
    vVertices[10] = 0.0;
    vVertices[11] = 0.0;
    vVertices[12] = 0.0;
    vVertices[15] = 0.0;
    vVertices[16] = 1.0;
    vVertices[17] = 0.0;
    glVertexAttribPointer(posLoc, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), vVertices);
    glVertexAttribPointer(texLoc, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), &vVertices[3]);
    glEnableVertexAttribArray(posLoc);
    glEnableVertexAttribArray(texLoc);
    glUniform1i(samLoc, 0);
    glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices);
  
    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D, texID[1]);
    vVertices[0] = 1.0;
    vVertices[1] = -1.0;
    vVertices[2] = 0.0;
    vVertices[5] = 1.0;
    vVertices[6] = 0.0;
    vVertices[7] = 0.0;
    vVertices[10] = 0.0;
    vVertices[11] = 0.0;
    vVertices[12] = 0.0;
    vVertices[15] = 0.0;
    vVertices[16] = -1.0;
    vVertices[17] = 0.0;
    glVertexAttribPointer(posLoc, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), vVertices);
    glVertexAttribPointer(texLoc, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), &vVertices[3]);
    glEnableVertexAttribArray(posLoc);
    glEnableVertexAttribArray(texLoc);
    glUniform1i(samLoc, 0);
    glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices);
  
    eglSwapBuffers(display, surface);
    system("fbgrab main.png");
    sleep(3);
  
    free(buf);
    glDeleteTextures(2, texID);
    eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
    eglDestroyContext(display, context);
    eglDestroySurface(display, surface);
    eglTerminate(display);
    return 0;
}

編譯、執行

$ gcc main.c -o main -lGLESv2 -lEGL
$ op_runfbapp ./main

完成