【问题标题】:How to display the image texture in GLES2?如何在 GLES2 中显示图像纹理?
【发布时间】:2020-06-14 14:37:34
【问题描述】:

如何在 GLES2 中显示图像纹理。

在下面初始化 GLES2 显示的源代码中,表面 .., 创建离线帧缓冲区, 将 RGBA 图像加载到纹理中,

用蓝色清除屏幕, 尝试显示加载的图像纹理(.. 找不到 GLES2 的正确 API) 读取 FBO 并写入文件。

GLES2 不支持显示 glEnableClientState&glVertexPointer API 如何在 GLES2 中显示加载的图像纹理。 在下面的源代码中,缓冲区中只有蓝色来自 glReadPixels

unsigned char *video_raw = loadFile("./video.raw");//RGBA raw image
    int iConfigs;
    EGLConfig eglConfig;
    EGLint ai32ContextAttribs[] = { EGL_CONTEXT_CLIENT_VERSION, 2,EGL_NONE };
    EGLDisplay eglDisplay = eglGetDisplay((EGLNativeDisplayType)0);
    eglInitialize(eglDisplay, 0, 0);
    eglBindAPI(EGL_OPENGL_ES_API);
    EGLint pi32ConfigAttribs[5];
    pi32ConfigAttribs[0] = EGL_SURFACE_TYPE;
    pi32ConfigAttribs[1] = EGL_WINDOW_BIT;
    pi32ConfigAttribs[2] = EGL_RENDERABLE_TYPE;
    pi32ConfigAttribs[3] = EGL_OPENGL_ES2_BIT;
    pi32ConfigAttribs[4] = EGL_NONE;
    eglChooseConfig(eglDisplay, pi32ConfigAttribs, &eglConfig, 1, &iConfigs);
    EGLSurface  eglSurface = eglCreatePbufferSurface(eglDisplay, eglConfig, NULL);
    EGLContext  eglContext = eglCreateContext(eglDisplay, eglConfig, NULL, ai32ContextAttribs);
    eglMakeCurrent(eglDisplay, eglSurface, eglSurface, eglContext);

    GLuint fboId = 0;
    GLuint renderBufferWidth = 960;
    GLuint renderBufferHeight = 540;

    glGenFramebuffers(1, &fboId);
    glBindFramebuffer(GL_FRAMEBUFFER, fboId);

    GLuint renderBuffer;
    glGenRenderbuffers(1, &renderBuffer);
    glBindRenderbuffer(GL_RENDERBUFFER, renderBuffer);

    glRenderbufferStorage(GL_RENDERBUFFER, GL_RGB565, renderBufferWidth, renderBufferHeight);
    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, renderBuffer);

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

    glEnable(GL_TEXTURE_2D);

    GLuint texture_object_id;
    glGenTextures(1, &texture_object_id);
    glBindTexture(GL_TEXTURE_2D, texture_object_id);

    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, renderBufferWidth, renderBufferHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, video_raw);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);


    GLfloat vtx1[] = { -1, -1, 0, -1, 1, 0, 1, 1, 0, 1, -1, 0 };
    GLfloat tex1[] = { 0, 0, 0, 1, 1, 1, 1, 0 };

    /*glEnableClientState(GL_VERTEX_ARRAY);
    glEnableClientState(GL_TEXTURE_COORD_ARRAY);

    glVertexPointer(3, GL_FLOAT, 0, vtx1);
    glTexCoordPointer(2, GL_FLOAT, 0, tex1);
    glDrawArrays(GL_TRIANGLE_FAN, 0, 4);

    glDisableClientState(GL_VERTEX_ARRAY);
    glDisableClientState(GL_TEXTURE_COORD_ARRAY);*/

    eglSwapBuffers( eglDisplay, eglSurface);

    //read & write to a file
    int size = 4 * renderBufferHeight * renderBufferWidth;
    unsigned char *data2 = new unsigned char[size];
    glReadPixels(0, 0, renderBufferWidth, renderBufferHeight, GL_RGBA, GL_UNSIGNED_BYTE, data2);

    dumptoFile("./read1.raw", size, data2);

编辑 1:

@Rabbid76 , 谢谢回复。当我在 vec3 inPos;\n 中使用您的顶点着色器时,着色器编译失败。我将“in”替换为“uniform”。

从以下来源获取黑屏并添加您的输入。

static const GLuint WIDTH = 960;
static const GLuint HEIGHT = 540;

static const GLchar* vertex_shader_source =
        "#version 100\n"
        "precision mediump float;\n"
        "uniform vec3 inPos;\n"
        "uniform vec2 inUV;\n"
        "varying vec2 vUV;\n"
        "void main(){\n"
        "    vUV = inUV;\n"
        "    gl_Position = vec4(inPos, 1.0);\n"
        "}\n";

static const GLchar* fragment_shader_source =
        "#version 100\n"
        "precision mediump float;\n"
        "varying vec2 vUV;\n"
        "uniform sampler2D u_texture;\n"
        "void main(){\n"
        "    gl_FragColor = texture2D(u_texture, vUV);\n"
        "}\n";

int main(int argc, char **argv)
{
    unsigned char *video_raw = loadFile("./video.raw");

    int iConfigs;
    EGLConfig eglConfig;
    EGLint ai32ContextAttribs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };
    EGLDisplay eglDisplay = eglGetDisplay((EGLNativeDisplayType) 0);
    eglInitialize(eglDisplay, 0, 0);
    eglBindAPI(EGL_OPENGL_ES_API);
    EGLint pi32ConfigAttribs[5];
    pi32ConfigAttribs[0] = EGL_SURFACE_TYPE;
    pi32ConfigAttribs[1] = EGL_WINDOW_BIT;
    pi32ConfigAttribs[2] = EGL_RENDERABLE_TYPE;
    pi32ConfigAttribs[3] = EGL_OPENGL_ES2_BIT;
    pi32ConfigAttribs[4] = EGL_NONE;
    eglChooseConfig(eglDisplay, pi32ConfigAttribs, &eglConfig, 1, &iConfigs);
    EGLSurface eglSurface = eglCreatePbufferSurface(eglDisplay, eglConfig, NULL);
    EGLContext eglContext = eglCreateContext(eglDisplay, eglConfig, NULL, ai32ContextAttribs);
    eglMakeCurrent(eglDisplay, eglSurface, eglSurface, eglContext);

    GLuint shader_program, framebuffer, renderBuffer;

    glGenRenderbuffers(1, &renderBuffer);
    glBindRenderbuffer(GL_RENDERBUFFER, renderBuffer);
    glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA, WIDTH, HEIGHT);

    glGenFramebuffers(1, &framebuffer);
    glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, renderBuffer);

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

    glViewport(0, 0, WIDTH, HEIGHT);
    glEnable(GL_TEXTURE_2D);

    shader_program = common_get_shader_program(vertex_shader_source, fragment_shader_source);

    GLint vert_inx = glGetAttribLocation(shader_program, "inPos");
    GLint uv_inx = glGetAttribLocation(shader_program, "inUV");
    GLint tex_loc = glGetUniformLocation(shader_program, "u_texture");

    GLuint texture_object_id;
    glGenTextures(1, &texture_object_id);
    glBindTexture(GL_TEXTURE_2D, texture_object_id);

    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, WIDTH, HEIGHT, 0, GL_RGBA, GL_UNSIGNED_BYTE, video_raw);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);

    GLfloat vtx1[] = { -1, -1, 0, -1, 1, 0, 1, 1, 0, 1, -1, 0 };
    GLfloat tex1[] = { 0, 0, 0, 1, 1, 1, 1, 0 };

    glVertexAttribPointer(vert_inx, 3, GL_FLOAT, GL_FALSE, 0, vtx1);
    glEnableVertexAttribArray(vert_inx);
    glVertexAttribPointer(uv_inx, 2, GL_FLOAT, GL_FALSE, 0, tex1);
    glEnableVertexAttribArray(uv_inx);

    glViewport(0,0,renderBufferWidth,renderBufferHeight);

    glUseProgram(shader_program);
    glUniform1i(tex_loc, 0);
    glDrawArrays( GL_TRIANGLE_FAN, 0, 4);

    glFlush();

    int size = 4 * WIDTH * HEIGHT;
    unsigned char *data2 = new unsigned char[size];
    glReadPixels(0, 0, WIDTH, HEIGHT, GL_RGBA, GL_UNSIGNED_BYTE, data2);
    dumptoFile("./read1.raw", size, data2);

    return EXIT_SUCCESS;
}

【问题讨论】:

    标签: opengl-es glsl shader opengl-es-2.0


    【解决方案1】:

    您必须使用着色器程序,并定义通用顶点属性数据的数组。另见Vertex Specification

    创建、编译和链接一个非常简单的着色器程序,如下所示:

    const char *sh_vert =
    "#version 100\n"\
    "precision mediump float;\n"\
    "attribute vec3 inPos;\n"\
    "attribute vec2 inUV;\n"\
    "varying vec2 vUV;\n"\
    "void main()\n"\
    "{\n"\
    "    vUV = inUV;\n"\
    "    gl_Position = vec4(inPos, 1.0);\n"\
    "}";
    

    const char *sh_frag =
    "#version 100\n"\
    "precision mediump float;\n"\
    "varying vec2 vUV;\n"\
    "uniform sampler2D u_texture;\n"\
    "void main()\n"\
    "{\n"\
    "    gl_FragColor = texture2D(u_texture, vUV);\n"\
    "}";
    

    GLuint v_sh = glCreateShader( GL_VERTEX_SHADER );
    glShaderSource( v_sh, 1, &sh_vert, nullptr );
    glCompileShader( v_sh );
    GLint status = GL_TRUE;
    glGetShaderiv( v_sh, GL_COMPILE_STATUS, &status );
    if ( status == GL_FALSE )
    {
        // compile error
    }
    
    GLuint f_sh = glCreateShader( GL_FRAGMENT_SHADER );
    glShaderSource( f_sh, 1, &sh_frag, nullptr );
    glCompileShader( f_sh );
    status = GL_TRUE;
    glGetShaderiv( f_sh, GL_COMPILE_STATUS, &status );
    if ( status == GL_FALSE )
    {
        // compile error
    }
    
    GLuint prog = glCreateProgram();
    glAttachShader( prog, v_sh );
    glAttachShader( prog, f_sh );
    glLinkProgram( prog );
    status = GL_TRUE;
    glGetProgramiv( prog, GL_LINK_STATUS, &status );
    if ( status == GL_FALSE )
    {
        // link error
    }
    

    获取纹理采样器制服的属性索引和位置:

    GLint vert_inx = glGetAttribLocation( prog, "inPos" );
    GLint uv_inx   = glGetAttribLocation( prog, "inUV" );
    GLint tex_loc  = glGetUniformLocation( prog, "u_texture" );
    

    然后通过 (glVertexAttribPointer) 定义通用顶点属性数据数组并通过glEnableVertexAttribArray 启用它们:

    GLfloat vtx1[] = { -1, -1, 0, -1, 1, 0, 1, 1, 0, 1, -1, 0 };
    GLfloat tex1[] = { 0, 0, 0, 1, 1, 1, 1, 0 };
    
    glVertexAttribPointer( vert_inx, 3, GL_FLOAT, GL_FALSE, 0, vtx1);
    glEnableVertexAttribArray( vert_inx );
    glVertexAttribPointer( uv_inx, 2, GL_FLOAT, GL_FALSE, 0, tex1);
    glEnableVertexAttribArray( uv_inx );
    

    设置渲染缓冲区和帧缓冲区并调整视口:

    glGenFramebuffers(1, &fboId);
    glBindFramebuffer(GL_FRAMEBUFFER, fboId);
    
    GLuint renderBuffer;
    glGenRenderbuffers(1, &renderBuffer);
    glBindRenderbuffer(GL_RENDERBUFFER, renderBuffer);
    
    glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA, renderBufferWidth, renderBufferHeight);
    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, renderBuffer);
    
    glViewport(0,0,renderBufferWidth,renderBufferHeight);
    glClearColor(0.0f, 0.0f, 1.0f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT);
    

    使用程序,统一设置纹理采样器并绘制几何体:

    // use the program
    glUseProgram( prog );
    glUniform1i( tex_loc, 0 ); // 0 == texture unit 0
    
    // draw the geometry
    glDrawArrays( GL_TRIANGLE_FAN, 0, 4 );
    
    glUseProgram( 0 );
    

    终于可以读取图片了:

    int size = 4 * renderBufferHeight * renderBufferWidth;
    unsigned char *data2 = new unsigned char[size];
    glReadPixels(0, 0, renderBufferWidth, renderBufferHeight, GL_RGBA, GL_UNSIGNED_BYTE, data2);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-05-23
      • 1970-01-01
      • 2021-04-08
      • 2017-07-18
      • 1970-01-01
      相关资源
      最近更新 更多