第一次用OpenGLES,在iOS端开发一个应用,须要实时渲染摄像头数据,写出来以后发现图像宽度不对,旁边出了四个灰度的原图。
代码大致如下:
shader:
const char* box_video_vert="uniform mat4 trans;\n"
"uniform mat4 proj;\n"
"attribute vec4 coord;\n"
"attribute vec2 texcoord;\n"
"varying vec2 vtexcoord;\n"
"\n"
"void main(void)\n"
"{\n"
" vtexcoord = texcoord;\n"
" gl_Position = proj*trans*coord;\n"
"}\n"
"\n"
;
const char* box_video_frag="#ifdef GL_ES\n"
"precision highp float;\n"
"#endif\n"
"varying vec2 vtexcoord;\n"
"uniform sampler2D texture;\n"
"\n"
"void main(void)\n"
"{\n"
" vec4 color = texture2D(texture, vtexcoord);\n"
" gl_FragColor = vec4(color[2],color[1],color[0],color[3]);\n"
"}\n"
"\n"
;
setup opengl 环境
_eaglLayer = (CAEAGLLayer*) self.layer;
_eaglLayer.opaque = YES;
EAGLRenderingAPI api = kEAGLRenderingAPIOpenGLES2;
_context = [[EAGLContext alloc] initWithAPI:api];
if (!_context)
NSLog(@"Failed to initialize OpenGLES 2.0 context");
if (![EAGLContext setCurrentContext:_context])
NSLog(@"Failed to set current OpenGL context");
GLuint frameBuffer;
glGenFramebuffers(1, &frameBuffer);
glBindFramebuffer(GL_FRAMEBUFFER, frameBuffer);
glGenRenderbuffers(1, &_colorRenderBuffer);
glBindRenderbuffer(GL_RENDERBUFFER, _colorRenderBuffer);
[_context renderbufferStorage:GL_RENDERBUFFER fromDrawable:_eaglLayer];
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, _colorRenderBuffer);
int width, height;
glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_WIDTH, &width);
glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_HEIGHT, &height);
GLuint depthRenderBuffer;
glGenRenderbuffers(1, &depthRenderBuffer);
glBindRenderbuffer(GL_RENDERBUFFER, depthRenderBuffer);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, width, height);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthRenderBuffer);
program_box = glCreateProgram();
GLuint vertShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertShader, 1, &box_video_vert, 0);
glCompileShader(vertShader);
GLuint fragShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragShader, 1, &box_video_frag, 0);
glCompileShader(fragShader);
glAttachShader(program_box, vertShader);
glAttachShader(program_box, fragShader);
glLinkProgram(program_box);
glUseProgram(program_box);
pos_coord_box = glGetAttribLocation(program_box, "coord");
pos_tex_box = glGetAttribLocation(program_box, "texcoord");
pos_trans_box = glGetUniformLocation(program_box, "trans");
pos_proj_box = glGetUniformLocation(program_box, "proj");
TextureID = glGetUniformLocation(program_box, "texture");
glGenBuffers(1, &vbo_coord_box);
glBindBuffer(GL_ARRAY_BUFFER, vbo_coord_box);
const GLfloat cube_vertices[4][3] = {{1.0f, 1.0f, 0.f},{1.0f, -1.0f, 0.f},{-1.0f, -1.0f, 0.f}, {-1.0f, 1.0f, 0.f}};
glBufferData(GL_ARRAY_BUFFER, sizeof(cube_vertices), cube_vertices, GL_DYNAMIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glGenBuffers(1, &vbo_tex_box);
glBindBuffer(GL_ARRAY_BUFFER, vbo_tex_box);
const GLubyte cube_vertex_texs[4][2] = {{0, 0},{1, 0},{1, 1},{0, 1}};
glBufferData(GL_ARRAY_BUFFER, sizeof(cube_vertex_texs), cube_vertex_texs, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glGenBuffers(1, &vbo_faces_box);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vbo_faces_box);
const GLushort cube_faces[] = {3, 0, 1, 2};
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(cube_faces), cube_faces, GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glUniform1i(TextureID, 0);
glGenTextures(1, &texture_id);
glBindTexture(GL_TEXTURE_2D, texture_id);
glHint(GL_GENERATE_MIPMAP_HINT, GL_NICEST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
渲染逻辑:
if (!((AppDelegate*)[[UIApplication sharedApplication]delegate]).active)
return;
videoDimensions = videoTexture.videoDimensions;
memcpy(bwImage,videoTexture->bwImage,640*480*4);
int width = self.frame.size.width;
int height = self.frame.size.height;
glClearColor(0.f, 0.f, 0.f, 1.f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glViewport(0, 0, width, height);
glBindTexture(GL_TEXTURE_2D, texture_id);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, videoDimensions.width, videoDimensions.height,0, GL_RGBA, GL_UNSIGNED_BYTE, bwImage);
glBindTexture(GL_TEXTURE_2D, 0);
glm::mat4 cameraview, projectionMatrix;
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_DEPTH_TEST);
glEnableVertexAttribArray(pos_coord_box);
glEnableVertexAttribArray(pos_tex_box);
glUseProgram(program_box);
glBindBuffer(GL_ARRAY_BUFFER, vbo_coord_box);
glVertexAttribPointer(pos_coord_box, 3, GL_FLOAT, GL_FALSE, 0, 0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ARRAY_BUFFER, vbo_tex_box);
glVertexAttribPointer(pos_tex_box, 2, GL_UNSIGNED_BYTE, GL_FALSE, 0, 0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glUniformMatrix4fv(pos_trans_box, 1, 0, glm::value_ptr(cameraview));
glUniformMatrix4fv(pos_proj_box, 1, 0, glm::value_ptr(projectionMatrix));
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vbo_faces_box);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture_id);
glUniform1i(TextureID, 0);
glDrawElements(GL_TRIANGLE_FAN, 4, GL_UNSIGNED_SHORT, 0);
glBindTexture(GL_TEXTURE_2D, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glDisableVertexAttribArray(pos_coord_box);
glDisableVertexAttribArray(pos_tex_box);
(void)displayLink;
glBindRenderbuffer(GL_RENDERBUFFER, _colorRenderBuffer);
[_context presentRenderbuffer:GL_RENDERBUFFER];
自己检查了好多遍,感觉没问题,glview也没错6s下375*667,摄像头数据也拿到了,结果就是不对。我哪里细节出错了吗,只在这些地方用到OpenGLES的东西。身边没有这方面的人询问,跪求渲染大神抢救。