I am attempting to get my first shadow map up and running (from here), but I have run into a very strange problem. This is the code that causes the error:
#interface HSOpenGLView() {
GLuint shadowFramebuffer;
GLuint shadowTexture;
}
#end
#implementation HSOpenGLView
- (void) drawRect:(NSRect)dirtyRect {
}
#pragma mark - Init
- (void) prepareOpenGL {
[super prepareOpenGL];
glEnable(GL_TEXTURE_2D);
glGenFramebuffers(1, &shadowFramebuffer);
glBindFramebuffer(GL_FRAMEBUFFER, shadowFramebuffer);
// Depth texture. Slower than a depth buffer, but you can sample it later in your shader
glGenTextures(1, &shadowTexture);
glBindTexture(GL_TEXTURE_2D, shadowTexture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT16, 1024, 1024, 0, GL_DEPTH_COMPONENT, GL_FLOAT, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
//glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, shadowTexture, 0);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, shadowTexture, 0);
//glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, shadowTexture);
glDrawBuffer(GL_NONE); // No color buffer is drawn to.
// Always check that our framebuffer is ok
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
NSLog(#"Failed to create the shadow framebuffer! %u", glGetError());
}
}
This class is a subclass of 'NSOpenGLView'. When it prints the error number it turns out to be '0'. What could possibly be causing it?
Add a call to glReadBuffer(GL_NONE) after your call to glDrawBuffer(GL_NONE). You need to indicate that your FBO doesn't have a color buffer source for read operations too.
Related
I got some problem about OGL in macOS, as the following sample, it works well in my win system but get error at API glPushAttrib, glDrawArrays, and glPopAttrib and get GL_INVALID_OPERATION each. Any idea about this?
I had read some topic about the issue but seems not work on macOS and compare with win system.
My mac is OS X El Capitan 10.11.6 with compiler Xcode version 6.4
//gen a texture
glGenTextures(1, &FilteredTexture);
glBindTexture(GL_TEXTURE_2D, FilteredTexture);
printf("Start glTexImage2D FilteredTexture...");
glTexImage2D(GL_TEXTURE_2D, 0, TexInterFormat, cols, rows, 0, TexFormat, DataType, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
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);
//gen a Renderbuffer
glGenRenderbuffers(1, &GlRenderbuffer);
glBindRenderbuffer(GL_RENDERBUFFER, GlRenderbuffer);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, cols, rows);
glBindRenderbuffer(GL_RENDERBUFFER, 0);
//gen a Framebuffer & attach
glGenFramebuffers(1, &GlFramebuffer);
glBindFramebuffer(GL_FRAMEBUFFER, GlFramebuffer);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, FilteredTexture, 0);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, GlRenderbuffer);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
//gen shaderas program (ignore detail here)
program = loadProgramFromFile("empty.vert", "depth.frag", "quad.geom");
//do the computation
glBindFramebuffer(GL_FRAMEBUFFER, GlFramebuffer);
const static GLuint attachment_bufferss[] = { static_cast<GLuint>(GL_COLOR_ATTACHMENT0) };
glDrawBuffers(1, attachment_bufferss);
glPushAttrib(GL_VIEWPORT_BIT); //get GL_INVALID_OPERATION here
glViewport(0, 0, cols, rows);
glClearColor(0, 0, 0, 0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glUseProgram(1);
glDrawArrays(GL_POINTS, 0, 1); //get GL_INVALID_OPERATION here
glDrawBuffers(1, attachment_bufferss);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glUseProgram(0);
glPopAttrib(); //get GL_INVALID_OPERATION here
glFinish();
full code can be downloaded here: https://1drv.ms/u/s!Au9Donvb28A9hgeor0v94Q5hKc0e
The errors occur because you're trying to use deprecated functions (glPushAttrib, glPopAttrib) in Core profile. To fix this, replace line
glPushAttrib(GL_VIEWPORT_BIT);
with
GLint vp [4];
glGetIntegerv (GL_VIEWPORT, vp);
and
glPopAttrib();
with
glViewport( vp[0], vp[1], vp[2], vp[3] );
The code first copies your current viewport into an array, then restores the viewport from the array.
I've implemented sample code to convert YUV colorspace to RGB using openGL ES 3.0 for android. I've vertex & fragment shaders where i defined converison formula.
I've created textures as below,
glActiveTexture(GL_TEXTURE0);
glGenTextures(1, &ytex);
glBindTexture(GL_TEXTURE_2D,ytex);
GLint textureBinding;
glGetIntegerv(GL_TEXTURE_BINDING_2D, &textureBinding);
if(textureBinding == 0)
{
char* infoLog = (char*) malloc(100);
glGetProgramInfoLog(programObject, textureBinding, NULL, infoLog);
errormsg = infoLog;
free (infoLog);
}
// Setup the texture parameters
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
//Define the texture image
glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, 640, 480, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, yBuffer);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, ytex, 0);
glActiveTexture(GL_TEXTURE1);
glGenTextures(1, &utex);
glBindTexture(GL_TEXTURE_2D,utex);
glGetIntegerv(GL_TEXTURE_BINDING_2D, &textureBinding);
if(textureBinding == 0)
{
char* infoLog = (char*) malloc(100);
glGetProgramInfoLog(programObject, textureBinding, NULL, infoLog);
errormsg = infoLog;
free (infoLog);
}
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);
glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, 320, 240, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, uBuffer);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, utex, 0);
glActiveTexture(GL_TEXTURE2);
glGenTextures(1, &vtex);
glBindTexture(GL_TEXTURE_2D,vtex);
glGetIntegerv(GL_TEXTURE_BINDING_2D, &textureBinding);
if(textureBinding == 0)
{
char* infoLog = (char*) malloc(100);
glGetProgramInfoLog(programObject, textureBinding, NULL, infoLog);
errormsg = infoLog;
free (infoLog);
}
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_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, 320, 240, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, NULL);
I'm not getting any errors when i verify using glGetError().
The output of textures i dont want to display on viewport, instead i want to store it in one buffer in order to use the output later. So i created framebuffer and render buffer as below,
//Framebuffer
glGenFramebuffers(1, &fboId);
glBindFramebuffer(GL_FRAMEBUFFER, fboId);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, vtex, 0);
//Check the framebuffer status
GLint status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
if(status != GL_FRAMEBUFFER_COMPLETE)
{
char* infoLog = (char*) malloc(100);
glGetProgramInfoLog(programObject, status, NULL, infoLog);
errormsg = infoLog;
free (infoLog);}
When i verify the status it is always returning 36054(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT), but the same returning GL_FRAMEBUFFER_COMPLETE when i unbind the buffer before calling glCheckFrameBufferStatus()
glbindFrameBuffer(GL_FRAMEBUFFER, 0);
So later i want to read the output from the framebuffer using glReadpixels(), but that is also failing. Please someone help how to resolve this issue?
36054 means GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT check your view's frame is right ?
There is no implementation of OpenGL / OpenGL ES supports alpha or luminance textures as color-renderable. You can replicate the behavior with GL_R8,GL_RG8. These two formats are very useful when you want to draw into a one or two-channel image format using an FBO (since GL_LUMINANCE, GL_ALPHA and GL_LUMINANCE_ALPHA are not color-renderable formats).
Try replacing internal format with GL_R8 and format with GL_RED.
I have been trying to get shadow maps to work, but I can;t even get past the depth buffer part of it. I've been looking on the internet for hours now, yadayadayada. Here is my code so far -
Making the FBO and the texture for depth:
GLuint framebuffer;
GLuint depth;
GLuint texture;
glGenFramebuffers(1, &framebuffer);
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1280, 800, 0, GL_RGBA, GL_FLOAT, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
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);
glGenTextures(1, &depth);
glBindTexture(GL_TEXTURE_2D, depth);
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, 1280, 800, 0, GL_DEPTH_COMPONENT, GL_FLOAT, NULL);
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);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depth, 0);
//glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
glDrawBuffer(GL_NONE);
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
std::cout << "There was a problem with making the framebuffer\n";
glBindFramebuffer(GL_FRAMEBUFFER, 0);
return framebuffer;
Rendering the 'depth' to a quad for viewing:
glBindFramebuffer(GL_FRAMEBUFFER, FBO);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
for (int i = 0; i < objects.size(); i++)
{
objects[i].renderObjectForDepth();
}
glBindFrameBuffer(GL_TEXTURE_2D,0);
glBindTexture2D(GL_TEXTURE_2D, texture)
drawQuad();
And to me, everything looks fine, but It generates images like the picture attached. I've been ripping out my hair for days now, and any help would be appreciated.
EDIT: It was because I was rendering a blank texture, IE the texture color that never got written to. After drawing the depth texture and writing the color texture, it works fine. But how do I do it without a color texture?
Check that the following two states are set when rendering to your depth-only FBO:
glDrawBuffer(GL_NONE);
glReadBuffer(GL_NONE);
I'm trying to draw to a texture (and then use that texture on an object) with GLKit but I'm receiving GL ERROR: 0x0502 which I think it means invalid value passed to a function. The thing is, the error is fired somewhere inside the effects prepareToDraw method. The vertex arrays seem to be set up correctly since I can draw on the default frame buffer with no problem using the same set up. Is there something I'm missing?
GLint defaultFBO;
glGetIntegerv(GL_FRAMEBUFFER_BINDING, &defaultFBO);
GLenum status;
glBindFramebuffer(GL_FRAMEBUFFER, _boundsTextureFramebuffer);
glBindTexture(GL_TEXTURE_2D, self.backgroundTexture.name);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8_OES, 1024, 1024, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, self.backgroundTexture.name, 0);
status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
if (status != GL_FRAMEBUFFER_COMPLETE)
{
NSLog(#"Failed to initialize the texture framebuffer");
}
effect.constantColor = [self.color vectorValue];
[effect prepareToDraw];
glBindVertexArrayOES(self.vertexArray);
glDrawElements(_data.mode, (GLsizei)self.data.indicesCount, GL_UNSIGNED_INT, (void*)0);
glBindVertexArrayOES(0);
glBindFramebuffer(GL_FRAMEBUFFER, (GLuint)defaultFBO);
You're missing one important thing from the code you've posted: the render buffer. Adding one might solve your problem. Here is an example off the top of my head:
GLint defaultFBO;
glGetIntegerv(GL_FRAMEBUFFER_BINDING, &defaultFBO);
GLint defaultRBO;
glGetIntegerv(GL_RENDERBUFFER_BINDING, &defaultRBO);
glGenFramebuffers(1, &_boundsTextureFramebuffer);
glBindFramebuffer(GL_FRAMEBUFFER, _boundsTextureFramebuffer);
glGenRenderbuffers(1, &_boundsTextureRenderbuffer);
glBindRenderbuffer(GL_RENDERBUFFER, _boundsTextureRenderbuffer);
glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA4, width, height);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, _boundsTextureRenderbuffer);
...
glBindFramebuffer(GL_FRAMEBUFFER, (GLuint)defaultFBO);
glBindRenderbuffer(GL_RENDERBUFFER, (GLuint)defaultRBO);
I get an error GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT after I try to create a framebuffer that renders to a texture. I can't figure out what is wrong, any help is greatly appreciated.
Edit: Fixed it! Working code:
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
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, 768, 1024, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
glBindTexture(GL_TEXTURE_2D, 0);
glGenRenderbuffers(1, &rboID);
glBindRenderbuffer(GL_RENDERBUFFER, rboID);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, 768, 1024);
glBindRenderbuffer(GL_RENDERBUFFER, 0);
glGenFramebuffers(1, &backFramebuffer);
glBindFramebuffer(GL_FRAMEBUFFER, backFramebuffer);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rboID);
[self checkFramebufferStatus];
glBindFramebuffer(GL_FRAMEBUFFER, 0);
Note: If your version doesn't work, make sure you check for errors after each and every call AND that you clear the error before your first call, else you'll be error-checking the code before that.
It is likely that the texture is incomplete. The default MIN_FILTER for a texture specifies mipmapping, but you've provided only for Texture Level 0, so the texture itself is incomplete.
Add calls to glTexParamter to set the MIN_FILTER to one of the non-mipmapped modes.