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



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

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

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

用于显示 glEnableClientState&glVertexPointer API 在 GLES2 中不受支持 如何在 GLES2 中显示加载的图像纹理。 在下面的来源中,从glReadPixel获得缓冲区中的蓝色

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 , 感谢您的回复。当我使用您的顶点着色器"in vec3 inPos;"时,着色器编译失败。我用"制服"代替"在"。

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

static const GLuint WIDTH = 960;
static const GLuint HEIGHT = 540;
static const GLchar* vertex_shader_source =
"#version 100n"
"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 100n"
"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;
}

您必须使用着色器程序,并定义通用顶点属性数据的数组。另请参阅顶点规范。

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

const char *sh_vert =
"#version 100n"
"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 100n"
"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);

最新更新