Related
I am trying to render an image to a texture in OpenGL ES to implement off-screen Sobel filter. Following this link http://www.songho.ca/opengl/gl_fbo.html, I create a resulting texture named sobelTexture and a render frame buffer named depthBuffer, then respectively attach them to GL_COLOR_ATTACHMENT0 and GL_DEPTH_ATTACHMENT of a newly created frame buffer. The code is shown in bellow.
// Create a texture associated with the frame buffer to render image into
GLuint sobelTexture;
glGenTextures(1, &sobelTexture);
glBindTexture(GL_TEXTURE_2D, sobelTexture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_FLOAT, 0);
glBindTexture(GL_TEXTURE_2D, 0);
GLuint depthBuffer;
glGenRenderbuffers(1, &depthBuffer);
glBindRenderbuffer(GL_RENDERBUFFER, depthBuffer);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, width, height);
glBindRenderbuffer(GL_RENDERBUFFER, 0);
// Create frame buffer
GLuint frameBuffer;
glGenFramebuffers(1, &frameBuffer);
glBindFramebuffer(GL_FRAMEBUFFER, frameBuffer);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, sobelTexture, 0);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthBuffer);
However, when I check the frame buffer status using the bellow code, it returns what is different from GL_FRAMEBUFFER_COMPLETE.
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
{
NSLog(#"! ERROR: frame buffer is not completed\n");
exit(1);
}
Moreover, If I change the data type GL_FLOAT in glTexImage2D() function to GL_UNSIGNED_BYTE, the frame buffer will be marked as complete. But I cannot use it because, in my fragment shader, the output color components are of float type.
How could I fix this problem?
Thanks in advance for any help.
The following is my create texture function:
- (GLuint)setupTexture:(NSString *)fileName {
// 1
CGImageRef spriteImage = [UIImage imageNamed:fileName].CGImage;
if (!spriteImage) {
NSLog(#"Failed to load image %#", fileName);
exit(1);
}
// 2
size_t kWidth = CGImageGetWidth(spriteImage);
size_t kHeight = CGImageGetHeight(spriteImage);
// 3
GLubyte * spriteData = (GLubyte *) calloc(kWidth*kHeight*4, sizeof(GLubyte));
// 4
GLuint texName;
glGenTextures(1, &texName);
glBindTexture(GL_TEXTURE_2D, texName);
glTexImage2D(GL_TEXTURE_2D, 0, GL_BGRA, (int)kWidth, (int)kHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, spriteData);
glGenerateMipmap(GL_TEXTURE_2D);
//glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL_APPLE, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_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);
glBindTexture(GL_TEXTURE_2D, 0);
return texName;
}
I use GPU capture in XCode, and find an error like this:
I'm new to OpenGL, how can I solve this? Thanks very much!
Take a look at texture descriptor number in the screenshot, 391341552. It's very unlikely to have this many textures in a single process.
It seems like the issue stems not in the set-up, but rather in texture binding before drawing.
Usually, after you successfully set up your textures and vertex arrays, you draw them as follows:
glUseProgram(programDescriptor);
glBindVertexArray(vertexArrayDescriptor);
glUniform(...);
glBindTexture(GL_TEXTURE_2D, textureDescriptor);
glDrawArrays(GL_TRIANGLE_STRIP, 0, verticesQuantity);
Perhaps you passed some pointer in glBindTexture?
I am building an iPad app using OpenGL ES 2.0. What I need to do is render to multiple textures and then render all the textures to view. I draw using GL_POINTS based on the user touch location. My code that I have now is:
Generate frame buffer, textures, and render buffer:
glGenFramebuffers(1, &viewFramebuffer);
glGenRenderbuffers(1, &viewRenderbuffer);
glBindFramebuffer(GL_FRAMEBUFFER, viewFramebuffer);
glBindRenderbuffer(GL_RENDERBUFFER, viewRenderbuffer);
glGenTextures(1, layers);
glBindTexture(GL_TEXTURE_2D, layers[0]);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, self.bounds.size.width, self.bounds.size.height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, layers[0], 0);
Draw:
glBindFramebufferOES(GL_FRAMEBUFFER_OES, viewFramebuffer);
....
glDrawArrays(GL_POINTS, 0, (int)vertexCount);
glBindRenderbuffer(GL_RENDERBUFFER, viewRenderbuffer);
[context presentRenderbuffer:GL_RENDERBUFFER];
The above works OK, however when I want to render to a new texture my application stops drawing any new content. I bind a new texture like this:
glGenTextures(1, &layers[1]);
glBindTexture(GL_TEXTURE_2D, layers[1]);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, self.bounds.size.width, self.bounds.size.height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, layers[1], 0);
And then call the drawing method again. My code works when rendering to the first texture but when I try to generate a new texture to render to, the app stops drawing. Can anyone help out?
I got my code to work. I had several problems with my frameBuffers not generating correctly and my textures not binding accurately. Lesson learned - always check state of frameBuffer after generation! Here it is:
Setup frameBuffers:
// Generate textureFrameBuffer for handling drawing to textures
glGenFramebuffers(1, &textureFrameBuffer);
glBindFramebuffer(GL_FRAMEBUFFER, textureFrameBuffer);
// Generate renderBufferer for drawing to screen
glGenRenderbuffers(1, &viewRenderbuffer);
glBindRenderbuffer(GL_RENDERBUFFER, viewRenderbuffer);
[context renderbufferStorage:GL_RENDERBUFFER fromDrawable:(id<EAGLDrawable>)self.layer];
glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_WIDTH, &backingWidth);
glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_HEIGHT, &backingHeight);
//Generate first texture and bind to textureFrameBuffer
glGenTextures(1, &layers[0]);
glBindTexture(GL_TEXTURE_2D, layers[0]);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, backingWidth, backingHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, layers[0], 0);
//check if frameBuffer is OK
if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE){
NSLog(#"failed to make complete framebuffer objects %x", glCheckFramebufferStatus(GL_FRAMEBUFFER));
return NO;
}
//Generate viewFrameBuffer for drawing to view
glGenFramebuffers(1, &viewFramebuffer);
glBindFramebuffer(GL_FRAMEBUFFER, viewFramebuffer);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, viewRenderbuffer);
if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
{
NSLog(#"failed to make complete framebuffer object %x", glCheckFramebufferStatus(GL_FRAMEBUFFER));
}
To draw to first texture:
glBindFramebuffer(GL_FRAMEBUFFER, textureFrameBuffer);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, layers[0], 0);
....
glDrawArrays(GL_POINTS, 0, (int)vertexCount);
To generate and bind second texture:
glGenTextures(1, &layers[1]);
glBindFramebuffer(GL_FRAMEBUFFER, textureFrameBuffer);
glBindTexture(GL_TEXTURE_2D, layers[1]);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, backingWidth, backingHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, layers[1], 0);
Draw to second texture:
glBindFramebuffer(GL_FRAMEBUFFER, textureFrameBuffer);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, layers[1], 0);
....
glDrawArrays(GL_POINTS, 0, (int)vertexCount);
To draw all textures to screen:
// Bind view buffer
glBindFramebuffer(GL_FRAMEBUFFER, viewFramebuffer);
//clear screen every frame
glClear(GL_COLOR_BUFFER_BIT);
//bind layer texture
for (int i=0; i<= layerCount; i++) {
glBindTexture(GL_TEXTURE_2D, layers [i]);
....
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
}
[context presentRenderbuffer:viewFramebuffer];
I am working on video calling in PJSIP and i am facing an issue with rendering the video using openGL.
I am able to see the real time video but in green tint color, I presume that it is an issue with openGL texture.
I dont have any knowledge on openGL so i am pasting some openGL code snippets which I use in my application.
Please tell me where I am going wrong, all I need to do is somehow remove the green tint in the video.
Below is the code to the best of my knowledge
//YUV toRGB Vertex Shader
attribute vec4 position;
attribute vec2 textureCoordinate;
varying vec2 coordinate;
void main()
{
gl_Position = position;
coordinate = textureCoordinate.xy;
}
//YUV to RGB Fragment Shader
uniform sampler2D SamplerY;
uniform sampler2D SamplerUV;
varying highp vec2 coordinate;
void main()
{
mediump vec3 yuv;
lowp vec3 rgb;
yuv.x = texture2D(SamplerY, coordinate).r;
yuv.yz = texture2D(SamplerUV, coordinate).rg - vec2(0.5, 0.5);
rgb = mat3(1, 1, 1,
0, -.21482, 2.12798,
1.28033, -.38059, 0) * yuv;
gl_FragColor = vec4(rgb, 1);
}
static void uninitialize_gl_buffers(struct ios_stream *strm)
{
TRACE_((THIS_FILE, "uninitialize_gl_buffers"));
glDeleteFramebuffers(1, &strm->frameBufferHandle);
glDeleteRenderbuffers(1, &strm->colorBufferHandle);
}
static void initialize_gl_textures(struct ios_stream *strm)
{
TRACE_((THIS_FILE, "initialize_gl_textures"));
glGenTextures(1, &strm->lumaTexture);
glGenTextures(1, &strm->chromaUTexture);
glGenTextures(1, &strm->chromaVTexture);
}
static void uninitialize_gl_textures(struct ios_stream *strm)
{
TRACE_((THIS_FILE, "uninitialize_gl_textures"));
if (strm->lumaTexture) {
glDeleteTextures(1, &strm->lumaTexture);
strm->lumaTexture = 0;
}
if (strm->chromaUTexture) {
glDeleteTextures(1, &strm->chromaUTexture);
strm->chromaUTexture = 0;
}
if (strm->chromaVTexture) {
glDeleteTextures(1, &strm->chromaVTexture);
strm->chromaVTexture = 0;
}
}
static void allocate_gl_textures(struct ios_stream *strm,
int frameWidth, int frameHeight)
{
TRACE_((THIS_FILE, "allocate_gl_textures %dx%d", frameWidth, frameHeight));
// Y planes (init)
glActiveTexture(GL_TEXTURE0);
glGenTextures( 1, &strm->lumaTexture );
glBindTexture(GL_TEXTURE_2D, strm->lumaTexture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
//glEnable(GL_TEXTURE_2D);
glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, frameWidth, frameHeight, 0,
GL_LUMINANCE, GL_UNSIGNED_BYTE, 0);
// U-planes (init)
glActiveTexture(GL_TEXTURE1);
glGenTextures( 1, &strm->chromaUTexture );
glBindTexture(GL_TEXTURE_2D, strm->chromaUTexture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, frameWidth/2, frameHeight/2, 0,
GL_LUMINANCE, GL_UNSIGNED_BYTE, 0);
// V-plane (init)
glActiveTexture(GL_TEXTURE2);
glGenTextures( 1, &strm->chromaVTexture );
glBindTexture(GL_TEXTURE_2D, strm->chromaVTexture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, frameWidth/2, frameHeight/2, 0,
GL_LUMINANCE, GL_UNSIGNED_BYTE, 0);
}
static void update_gl_textures (struct ios_stream *strm)
{
//const pj_uint8_t *buffer = (const pj_uint8_t *)strm->buf;
const pj_uint8_t *buffer = (const pj_uint8_t *)strm->frame->buf;
pj_uint32_t width = strm->size.w;
pj_uint32_t height = strm->size.h;
//TRACE_((THIS_FILE, "update_gl_textures %dx%d (%d)", width, height, buffer));
// Y planes (update)
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, strm->lumaTexture);
glUniform1i(uniformLocations[UNIFORM_Y], 0);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0,
width, // source width
height, // source height
GL_LUMINANCE, GL_UNSIGNED_BYTE,
buffer);
// U-planes (update)
buffer += width*height;
width >>= 1;
height >>=1;
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, strm->chromaUTexture);
glUniform1i(uniformLocations[UNIFORM_U], 1);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0,
width, // source width
height, // source height
GL_LUMINANCE, GL_UNSIGNED_BYTE,
buffer);
// V-planes (update)
buffer += width*height;
glActiveTexture(GL_TEXTURE2);
glBindTexture(GL_TEXTURE_2D, strm->chromaVTexture);
glUniform1i(uniformLocations[UNIFORM_V], 2);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0,
width, // source width
height, // source height
GL_LUMINANCE, GL_UNSIGNED_BYTE,
buffer);
}
I'm trying to offscreen render using this post
http://www.idevgames.com/forums/thread-1785-post-54500.html#pid54500
First I init FBO.
glGenTextures(1, &tex);
glBindTexture(GL_TEXTURE_2D, tex);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 512, 512, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
glBindTexture(GL_TEXTURE_2D, 0);
glGenFramebuffersOES(1, &fbo);
glBindFramebufferOES(GL_FRAMEBUFFER_OES, fbo);
glFramebufferTexture2DOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_TEXTURE_2D, tex, 0);
GLenum status = glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES);
if (status != GL_FRAMEBUFFER_COMPLETE_OES) {
NSLog(#"failed to make complete framebuffer object %x", status);
exit(-1);
}
Then I draw to my texture
GLint oldFBO, oldViewPort[4];
glGetIntegerv(GL_FRAMEBUFFER_BINDING_OES, &oldFBO);
glGetIntegerv(GL_VIEWPORT, oldViewPort);
glBindTexture(GL_TEXTURE_2D, 0);
glBindFramebufferOES(GL_FRAMEBUFFER_OES, listFrameBuffers[i]);
glViewport(0, 0, 512, 512);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// draw code here
glBindFramebufferOES(GL_FRAMEBUFFER_OES, oldFBO);
glViewport(oldViewPort[0], oldViewPort[1], oldViewPort[2], oldViewPort[3]);
And then each frame I draw it.
When I finish my frame calling glSwapBuffers texture attached to framebuffer becomes clear
(but when I draw to frame buffer each time after glSwapBuffers everything is ok).
So, the quest is completed.
I just changed draw code to this
GLint oldFBO, oldViewPort[4];
glGetIntegerv(GL_FRAMEBUFFER_BINDING_OES, &oldFBO);
glGetIntegerv(GL_VIEWPORT, oldViewPort);
glBindTexture(GL_TEXTURE_2D, 0);
glBindFramebufferOES(GL_FRAMEBUFFER_OES, listFrameBuffers[i]);
glViewport(0, 0, 512, 512);
//glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // HERE
glDisable(GL_DEPTH_TEST); // AND HERE
// draw code here
glBindFramebufferOES(GL_FRAMEBUFFER_OES, oldFBO);
glViewport(oldViewPort[0], oldViewPort[1], oldViewPort[2], oldViewPort[3]);
and it works! :)