Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 3 months ago.
Improve this question
I use opengl in qt. I have several pictures with a size of 30000 * 20000, including single channel, three channel and four channel pictures. The function I want to achieve is to switch and display different pictures through the keyboard, and support moving and zooming. I have implemented this function now, but I encountered some problems.
I want to bind them to different texture units and switch them when painting. But it seems to have no effect.
void MyOpenGLWidget::initializeGL()
{
initializeOpenGLFunctions();
glGenVertexArrays(2, VAO);
glGenVertexArrays(2, VBO);
glEnable(GL_DEPTH_TEST);
{
if (!bindShaderProgram(m_shaderProgram, vertexSourceBG, fragmentSourceBG))
return;
glBindVertexArray(VAO[0]);
glBindBuffer(GL_ARRAY_BUFFER, VBO[0]);
glPixelStorei(GL_PACK_ALIGNMENT, 1);
glBufferData(GL_ARRAY_BUFFER, m_vBGVertices.size() * sizeof(GLfloat), m_vBGVertices.data(), GL_STREAM_DRAW);
readImage();
glGenTextures(IMAGE_NUM, texture);
for (int i = 0; i < IMAGE_NUM; i++) {
glActiveTexture(GL_TEXTURE0+i);
glBindTexture(GL_TEXTURE_2D, texture[i]);
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_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
int channel = m_vImage[m_imageIdx].channels();
int internalFormat = GL_RGB, format = GL_RGB;
getImageFormat(channel, internalFormat, format);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, m_imageWidth, m_imageHeight, 0, format, GL_UNSIGNED_BYTE, m_vImage[m_imageIdx].data);
glBindTexture(GL_TEXTURE_2D, texture[i]);
}
m_shaderProgram.setAttributeBuffer("aPos", GL_FLOAT, 0, 3, sizeof(GLfloat) * 5);//8
m_shaderProgram.enableAttributeArray("aPos");
m_shaderProgram.setAttributeBuffer("aTexCoord", GL_FLOAT, sizeof(GLfloat) * 3, 2, sizeof(GLfloat) * 5);
m_shaderProgram.enableAttributeArray("aTexCoord");
m_shaderProgram.release();
glBindBuffer(GL_ARRAY_BUFFER, VBO[0]);
glBindVertexArray(VAO[0]);
}
}
void MyOpenGLWidget::paintGL()
{
glClearColor(0.1f, 0.5f, 0.7f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
{
glBindVertexArray(VAO[0]);
m_shaderProgram.bind();
createCameraTransformMatrix();
m_shaderProgram.setUniformValue("model", m_mModel);
m_shaderProgram.setUniformValue("view", m_mView);
m_shaderProgram.setUniformValue("projection", m_mProjection);
glActiveTexture(GL_TEXTURE0+m_imageIdx);
glBindTexture(GL_TEXTURE_2D, texture[m_imageIdx]);
m_shaderProgram.setUniformValue("ourTexture", GL_TEXTURE0+m_imageIdx);
m_shaderProgram.setUniformValue("imgWidth", m_imageWidth);
m_shaderProgram.setUniformValue("imgHeight", m_imageHeight);
glDrawArrays(GL_POLYGON, 0, 4);
m_shaderProgram.release();
glBindTexture(GL_TEXTURE_2D, texture[m_imageIdx]);
glBindVertexArray(VAO[0]);
}
}
Switch the currently displayed texture by switching m_imageIdx. But no response.
I bound them to the same texture unit, and then loaded them when refreshing. Now they can be loaded, but the speed is too slow to accept.
void MyOpenGLWidget::paintGL()
{
glClearColor(0.1f, 0.5f, 0.7f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
{
glBindVertexArray(VAO[0]);
m_shaderProgram.bind();
createCameraTransformMatrix();
m_shaderProgram.setUniformValue("model", m_mModel);
m_shaderProgram.setUniformValue("view", m_mView);
m_shaderProgram.setUniformValue("projection", m_mProjection);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture[m_imageIdx]);
updateImage();
if (!m_vImage[m_imageIdx].empty()) {
int channel = m_vImage[m_imageIdx].channels();
int internalFormat = GL_RGB, format = GL_RGB;
getImageFormat(channel, internalFormat, format);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, m_imageWidth, m_imageHeight, 0, format, GL_UNSIGNED_BYTE, m_vImage[m_imageIdx].data);
}
m_shaderProgram.setUniformValue("imgWidth", m_imageWidth);
m_shaderProgram.setUniformValue("imgHeight", m_imageHeight);
glDrawArrays(GL_POLYGON, 0, 4);
m_shaderProgram.release();
glBindTexture(GL_TEXTURE_2D, texture[m_imageIdx]);
glBindVertexArray(VAO[0]);
}
I referred to some similar problems and tried glTexSubImage2D, but I needed to refresh the whole picture, so the efficiency was not improved.
I can't reduce the texture precision because the texture display needs high precision.
I hope someone can give me some advice.
Available code snippets.
//init
for (int i = 0; i < IMAGE_NUM; i++) {
glActiveTexture(GL_TEXTURE0 + i);
glBindTexture(GL_TEXTURE_2D, texture[i]);
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_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
int channel = m_vImage[m_imageIdx].channels();
int internalFormat = GL_RGB, format = GL_RGB;
getImageFormat(channel, internalFormat, format);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, m_imageWidth, m_imageHeight, 0, format, GL_UNSIGNED_BYTE, m_vImage[i].data);
glBindTexture(GL_TEXTURE_2D, texture[i]);
}
//paintGL
glBindTexture(GL_TEXTURE_2D, texture[m_imageIdx]);
m_shaderProgram.setUniformValue("ourTexture", m_imageIdx);
m_shaderProgram.setUniformValue("imgWidth", m_imageWidth);
m_shaderProgram.setUniformValue("imgHeight", m_imageHeight);
glDrawArrays(GL_POLYGON, 0, 4);
m_shaderProgram.release();
glBindTexture(GL_TEXTURE_2D, texture[m_imageIdx]);
You definitely do not need to upload them every frame. What you did forget was to set the correct value for sampler2D uniform variable in the fragment shader (which you did not post).
m_shaderProgram.setUniformValue("ourTexture", m_imageIdx); must be called in the draw loop
with correctly bound shader
Do not use GL_TEXTURE0 here, as pointed by #HolyBlackCat .
By default, it uses data from GL_TEXTURE0. You can imagine GL_TEXTURE as an array of pointers to the actual textures. glActiveTexture sets which pointer is used for the subsequent GL calls and glBindTexture assigns to this active pointer.
The uniform sampler acts exactly the same, the index you assign to it is the array element it will work with.
This also means that you need to just bind all textures to separate units only once, e.g. how you do (needlessly) during initialization and then vary only the uniform sampler, no binds, not activates needing.
Related
I have a series of rectangles of different colours and I'm trying to add a texture to one of them. However when I apply the texture to the given rectangle, it just turns black. Below is the function I use to load the texture.
GLuint GLWidget:: LoadTexture(const char * pic, int width, int height){
GLuint Texture;
BYTE * data;
FILE * picfile;
picfile = fopen(pic, "rb");
if (picfile == NULL)
return 0;
data = (BYTE *)malloc(width * height * 3);
fread(data, width * height, 3, picfile);
fclose(picfile);
glGenTextures(1, &Texture);
glBindTexture(GL_TEXTURE_2D, Texture);
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_MIN_FILTER, GL_LINEAR);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, width, height, 0, GL_RGB8, GL_UNSIGNED_BYTE, data);
return Texture;
}
In another function where the GL_QUADS are drawn, I then have...
GLuint myTex = LoadTexture("texture.bmp", 500, 500);
glEnable(GL_TEXTURE_2D);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glBindTexture(GL_TEXTURE_2D, myTex);
glBegin(GL_QUADS);
glTexCoord2f(1, 1); glVertex3f(42, 10, 42);
glTexCoord2f(1, 0); glVertex3f(42, 10, -42);
glTexCoord2f(0, 0); glVertex3f(-42,10,-42);
glTexCoord2f(0, 1); glVertex3f(-42,10, 42);
glEnd();
If anyone could let me know where I am going wrong that would be great, thanks!
This call
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, width, height, 0, GL_RGB8, GL_UNSIGNED_BYTE, data);
is invalid. GL_RGB8 is a valid internalFormat, but it is not a valid enum for format. Use GL_RGB, GL_UNSIGNED_BYTE as format and type if your client-side data is 3 channels with 8 but unsigned int data per channel.
Another thing is
LoadTexture("texture.bmp", 500, 500);
This suggests that you are dealing with BMP files, but your loader only deals with completely raw image data.
I'm trying to render to texture.Using opengl-es 2.0.I wanna make Black and white postprocessing.But all I see, is black texture.On scene I have lightsources, and two spheres.But when I'm trying to render my texture that attached to framebuffer, I see black square.
this->frameBuffersCount = 3;
this->frameBuffers = new int[frameBuffersCount];
glGenFramebuffers(frameBuffersCount, (GLuint*)this->frameBuffers);
this->texturesCount = this->frameBuffersCount * 2;
this->bufferTextures = new int[this->texturesCount];
glGenTextures(this->texturesCount, (GLuint*)this->bufferTextures);
for(int i = 0; i < this->texturesCount / 2; ++i)
{
glBindTexture(GL_TEXTURE_2D, this->bufferTextures[2*i]);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, screenWidth, screenHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, 0);
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_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glBindTexture(GL_TEXTURE_2D,0);
glBindTexture(GL_TEXTURE_2D, this->bufferTextures[2*i + 1]);
glTexImage2D(GL_TEXTURE_2D, 0,GL_DEPTH_COMPONENT, screenWidth, screenHeight, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, 0);
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_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glBindTexture(GL_TEXTURE_2D,0);
}
for(int i = 0; i < this->frameBuffersCount; ++i)
{
glBindFramebuffer(GL_FRAMEBUFFER, this->frameBuffers[i]);
glFramebufferTexture2D(GL_FRAMEBUFFER,
GL_COLOR_ATTACHMENT0,
GL_TEXTURE_2D,
this->bufferTextures[2*i],
0);
glFramebufferTexture2D(GL_FRAMEBUFFER,
GL_DEPTH_ATTACHMENT,
GL_TEXTURE_2D,
this->bufferTextures[2*i + 1],
0);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
}
this->ordinaryQuad = new ModelVertex[4];
this->ordinaryQuad[0].UV = Vector2(0.0,0.0);
this->ordinaryQuad[0].position = Vector3(-1, -1, 0.0);
this->ordinaryQuad[1].UV = Vector2(0.0,1.0);
this->ordinaryQuad[1].position = Vector3(-1.0, 1.0, 0.0);
this->ordinaryQuad[2].UV = Vector2(1.0,1.0);
this->ordinaryQuad[2].position = Vector3(1.0, 1.0, 0.0);
this->ordinaryQuad[3].UV = Vector2(1.0,0.0);
this->ordinaryQuad[3].position = Vector3(1.0, -1.0, 0.0);
This is rendering code.
void EffectManager::applyBnW()
{
glBindFramebuffer(GL_FRAMEBUFFER, this->frameBuffers[0]);
auto res = glCheckFramebufferStatus(GL_FRAMEBUFFER);
if(res == GL_FRAMEBUFFER_COMPLETE)
{
SceneManager::GetInstance().DrawScene();
glDisable(GL_DEPTH_TEST);
unsigned short indices[6] = {0,2,1,2,0,3};
Shaders shaders;
shaders.Init("../Resources/Shaders/BlackAndWhiteVS.vs", "../Resources/Shaders/BlackAndWhiteFS.fs", 0);
glUseProgram(shaders.program);
unsigned int hVBuff,hInBuff;
glGenBuffers(1, &hVBuff);
glGenBuffers(1, &hInBuff);
glBindBuffer(GL_ARRAY_BUFFER, hVBuff);
glBufferData(GL_ARRAY_BUFFER, 4 * sizeof(SEngine::ModelVertex), this->ordinaryQuad, GL_STATIC_DRAW);
//glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, hInBuff);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, 6 * sizeof(unsigned short), indices, GL_STATIC_DRAW);
//glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, this->bufferTextures[0]);
glGenerateMipmap(GL_TEXTURE_2D);
if(shaders.positionAttribute != -1)
{
glEnableVertexAttribArray(shaders.positionAttribute);
glVertexAttribPointer(shaders.positionAttribute, 3, GL_FLOAT, GL_FALSE, sizeof(SEngine::ModelVertex), 0);
}
if(shaders.UVAttribute != -1)
{
glEnableVertexAttribArray(shaders.UVAttribute);
glVertexAttribPointer(shaders.UVAttribute, 2, GL_FLOAT, GL_FALSE, sizeof(SEngine::ModelVertex), (void*)(sizeof(Vector3)));
}
if(shaders.samplerUniform != -1)
{
glUniform1i(shaders.samplerUniform, 0);
}
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, (void*)0);
//glDrawArrays(GL_TRIANGLES,0,4);
}
What is wrong?
Not a clear answer can be given since there is not enough information/code provided in your question.
Did you clear the depth buffer ?
When you generated the color in the fragment shader for the rendered objects, did you correctly calculate the White color?
One way I do in these situations to help me debug the issue is to remove potential error areas.
Clear the framebuffer to Red color and Alpha channel = 1.0
Clear depth buffer
Hard code gl_FragColor to vec4(1,1,1,1)
By doing this you can see if the output is all red? Then the issue is with the object rendering, such as transformation, clipping, depth rejection or other reason.
If you can see the objects with White color? Then you know it's the issue with your fragment shader
I would also recommend you to remove the line
glGenerateMipmap(GL_TEXTURE_2D);
As from what I can see in your code, it does not add any extra. If not this is the root-cause to your error.
Generating mipmaps on the texture that still being used and attached to a framebuffer object is not very effecient, especially if the driver internally would have to reallocate the memory for being able to store the new mipmap levels.
Solved.It was problems with index buffer and I forget to disable depth_test.
I am trying to write a GPGPU program, by just copying contents of a texture to an output texture attached to FBO. However, I see that the input texture data is not being loaded or binded properly. I cannot understand what is wrong.
Here is my code:
void render()
{
int i;
float * result, *in;
//allocating and filling data in the input texture
result = (float * ) malloc(4*32*32*sizeof(float));
in = (float *) malloc(4*32*32*sizeof(float));
for(i=0;i<32*32*4; i++)
{
in[i]=1.0f;
}
makeBuffers(); //makes the vertex and element buffers
makeTexture(in); //makes the input textures
makeShaders(); //makes the vertex n pixel shaders
makeProgram(); //makes the program
glClearColor(1.0f, 1.0f, 1.0f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT);
glBindBuffer(GL_ARRAY_BUFFER, res.vertexBuffer);
glVertexAttribPointer(res.position, 2, GL_FLOAT, GL_FALSE, sizeof(GLfloat)*2, (void*)0);
glEnableVertexAttribArray(res.position);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, res.elementBuffer);
res.texture= glGetUniformLocation(res.shaderProgram, "intexture");
/* bind texture */
makefbo(); // making the offscreen frame buffer object
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, res.texture);
glUniform1i(res.texture, 0);
glDrawElements(GL_TRIANGLE_STRIP,4, GL_UNSIGNED_SHORT, (void*)0);
// glFlush(); // i think drawing would be enough now.
glReadBuffer(GL_COLOR_ATTACHMENT0_EXT); //reading back data from the framebuffer
glReadPixels(0, 0, 32, 32,GL_RGBA,GL_FLOAT,result);
printf(" float values \n");
for(i=0; i< 32*4 ; i++)
printf(" %f ", result[i]);
printf(" \n");
}
and here is my maketexture() function
glGenTextures (1, &res.texture);
glBindTexture(GL_TEXTURE_2D,res.texture);
// set texture parameters
glTexParameteri(GL_TEXTURE_2D,
GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D,
GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D,
GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D,
GL_TEXTURE_WRAP_T, GL_CLAMP);
// define texture with floating point format
glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA32F,
texSize,texSize,0,GL_RGBA,GL_FLOAT,0);
// transfer data to texture
glTexSubImage2D(GL_TEXTURE_2D,0,0,0,texSize,texSize,
GL_RGBA,GL_FLOAT,data);
And here is my framebuffer object preparation and output texture binding:
glGenFramebuffers(1, &res.fbo);
glBindFramebuffer(GL_FRAMEBUFFER, res.fbo);
glViewport(0, 0, 32, 32);
glGenTextures(1, &res.tex);
glBindTexture(GL_TEXTURE_2D, res.fbo);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F,
32, 32, 0, GL_RGBA, GL_FLOAT, 0);
glFramebufferTexture2DEXT(GL_FRAMEBUFFER,
GL_COLOR_ATTACHMENT0,
GL_TEXTURE_2D, res.tex, 0);
The data does not seem to be read properly. I tried to attach the input texture to a framebuffer object, and tried to read back the texture data immediately, and the data gets displayed fine then. However, when I try to render to an offscreen texture, it does not give the correct output. It gives just a bunch of zeros at the end of pixel shader execution.
The pixel shader takes the input texture and copies the data into the output texture: outColor = texture2D (intexture, texcoord);
Does anyone see any problem with this?
Your code lacks a lot of context, but I have the impression that you bind everything exactly one time and then just leave it that way. That's not how it's meant to be used and will likely not work.
The essential gist is, that if a texture is used as a FBO render target it must not serve as a sampling source. So you have to either unbind textures / FBOs as needed, so that things don't tread on each other's toes, or you're loading shaders which simply make forbidden texture accesses. IMHO unbinding is the simpler option (however with OpenGL-4.4 a bindless texture extension was released, which may become core in 4.5).
I have created the shadow map. However it has two problems :
1. The shadow comes into picture only when I change the model matrix. i.e initially there is no shadows, but when i press a key to move the figure, that is there is a change in the model matrix, the shadow appears.
2. There is a trail of old renders on the texture on the framebuffer that results in a long trail.
Can anyone shed any light on this?
THis is the screenshot of the problem
Edit Code here :
void generateShadowTex()
{
//Calculate final ligting properties
glm::vec4 a_f=light_ambient*mat_ambient;
glm::vec4 d_f=light_diffuse*mat_diffuse;
glm::vec4 s_f=light_specular*mat_specular;
int counter=0;
glClear(GL_DEPTH_BUFFER_BIT);
glEnable(GL_DEPTH_TEST); // need depth test to correctly draw 3D objects
glClearColor(0,0,0,1);
//glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
if(wframe)
glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);
else
glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
glActiveTexture(GL_TEXTURE3);
glBindTexture(GL_TEXTURE_2D,depthTex);
// MAths here for mvp manupulation
//Draw Elements
if(a<17 || a==18)
glDrawElements(GL_QUADS, masterNumberIndices[a], GL_UNSIGNED_INT, (char*) NULL+0);
else
glDrawElements(GL_TRIANGLES, masterNumberIndices[a], GL_UNSIGNED_INT, (char*) NULL+0);
glBindVertexArrayAPPLE(0);
}
glUseProgram(0);
}
void Init_FBO()
{
GLfloat border[] = {1.0f, 0.0f, 0.0f, 0.0f};
//glActiveTexture(GL_TEXTURE3);
glGenTextures(1, &depthTex);
glBindTexture(GL_TEXTURE_2D, depthTex);
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24,900,900, 0, GL_DEPTH_COMPONENT, 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_BORDER);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, border);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LESS);
glBindTexture(GL_TEXTURE_2D,0);
glGenFramebuffers(1, &shadowFBO);
glBindFramebuffer(GL_FRAMEBUFFER, shadowFBO);
glDrawBuffer(GL_NONE);
glReadBuffer(GL_NONE);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depthTex, 0);
glBindFramebuffer(GL_FRAMEBUFFER, 0); // go back to the default framebuffer
// check FBO status
GLenum FBOstatus = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER);
if(FBOstatus != GL_FRAMEBUFFER_COMPLETE)
{
printf("GL_FRAMEBUFFER_COMPLETE failed, CANNOT use FBO\n");
}
else
{
printf("Frame Buffer Done Succesfully\n");
}
}
void display()
{
glBindFramebuffer(GL_FRAMEBUFFER, shadowFBO);
generateShadowTex();
glBindFramebuffer(GL_FRAMEBUFFER, 0);
generateScene();
}
You need to enable the depth buffer before you clear it. From the OpenGL specification:
If a buffer is not present, then a glClear directed at that buffer has no effect. 1
And:
GL_DEPTH_TEST
If enabled, do depth comparisons and update the depth buffer. Note that even if the depth buffer exists and the depth mask is non-zero, the depth buffer is not updated if the depth test is disabled. 2
As to the first part of your question, I can only guess what the problem might be, but you're probably not initializing the model matrix correctly.
I have some code in OpenGL to render a YUV image onto an OpenGL viewport. The program works without a problem when running on nvidia cards, but it generates an error when running over the Intel HD 3000, which sadly is the target machine. The point where the error is generated is marked in the code.
The shader programs are
// Vertex Shader
#version 120
void main() {
gl_TexCoord[0] = gl_MultiTexCoord0;
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
}
// fragment shader
#version 120
uniform sampler2D texY;
uniform sampler2D texU;
uniform sampler2D texV;
void main() {
vec4 color;
float y = texture2D(texY, gl_TexCoord[0].st).r;
float u = texture2D(texU, gl_TexCoord[0].st).r;
float v = texture2D(texV, gl_TexCoord[0].st).r;
color.r = (1.164 * (y - 0.0625)) + (1.596 * (v - 0.5));
color.g = (1.164 * (y - 0.0625)) - (0.391 * (u - 0.5)) - (0.813 * (v - 0.5));
color.b = (1.164 * (y - 0.0625)) + (2.018 * (u - 0.5));
color.a = 1.0;
gl_FragColor = color;
};
Then I run the program like this:
GLuint textures[3];
glGenTextures(3, textures);
glBindTexture(GL_TEXTURE_2D, textures[YTEX]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glBindTexture(GL_TEXTURE_2D, textures[UTEX]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glBindTexture(GL_TEXTURE_2D, textures[VTEX]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glBindTexture(GL_TEXTURE_2D, 0);
GLsizei size = width * height;
GLvoid *y = yuv_buffer;
GLvoid *u = (GLubyte *)y + size;
GLvoid *v = (GLubyte *)u + (size >> 2);
glUseProgram(program_id);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, textures[0]);
glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, width, height, 0, GL_LUMINANCE,
GL_UNSIGNED_BYTE, y);
glUniform1i(glGetUniformLocation(program_id, "texY"), 0);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, textures[1]);
glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, width >> 1, height >> 1, 0,
GL_LUMINANCE, GL_UNSIGNED_BYTE, u);
glUniform1i(glGetUniformLocation(program_id, "texU"), 1);
glActiveTexture(GL_TEXTURE2);
glBindTexture(GL_TEXTURE_2D, textures[2]);
glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, width >> 1, height >> 1, 0,
GL_LUMINANCE, GL_UNSIGNED_BYTE, u);
glUniform1i(glGetUniformLocation(program_id, "texV"), 2);
glBegin(GL_QUADS);
glTexCoord2f(texLeft, texTop);
glVertex2i(left, top);
glTexCoord2f(texLeft, texBottom);
glVertex2i(left, bottom);
glTexCoord2f(texRight, texBottom);
glVertex2i(right, bottom);
glTexCoord2f(texRight, texTop);
glVertex2i(right, top);
glEnd();
// glError() returns 0x506 here
glBindTexture(GL_TEXTURE_2D, 0);
glActiveTexture(GL_TEXTURE0);
glUseProgram(0);
update since the error happens with frame buffers, I discover they are used like this:
when the program is instantiated, a frame buffer is created like this:
glViewport(0, 0, (GLint)width, (GLint)height);
glGenFramebuffers(1, &fbo_id);
glGenTextures(1, &fbo_texture);
glGenRenderbuffers(1, &rbo_id);
glBindTexture(GL_TEXTURE_2D, fbo_texture);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_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);
glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0,
GL_RGBA, GL_UNSIGNED_BYTE, 0);
glBindTexture(GL_TEXTURE_2D, 0);
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, rbo_id);
glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT, width, height);
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo_id);
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
GL_TEXTURE_2D, fbo_texture, 0);
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT,
GL_RENDERBUFFER_EXT, rbo_id);
GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
glBindFramebuffer(GL_FRAMEBUFFER_EXT, 0);
glPushAttrib(GL_TEXTURE_BIT);
glBindTexture(GL_TEXTURE_2D, m_frameTexture->texture());
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glPopAttrib();
The YUV image comes spliced in tiles, which are assembled by rendering in this fbo. Whenever a frame starts, this is performed:
glBindFramebuffer(GL_FRAMEBUFFER_EXT, 0);
glDrawBuffer(GL_BACK);
glViewport(0, 0, (GLint)width, (GLint)height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0.0, (double)width, 0.0, (double)height, -1.0, 1.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glBindFramebuffer(GL_FRAMEBUFFER_EXT, fbo_id);
Then the code above is executed, and after all the tiles had been assembled together
glBindFramebuffer(GL_FRAMEBUFFER_EXT, 0);
glPushAttrib(GL_VIEWPORT_BIT | GL_TEXTURE_BIT | GL_ENABLE_BIT);
glViewport(0, 0, width, height);
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT);
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
glOrtho(0.0, (double)width, 0.0, (double)height, -1.0, 1.0);
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadIdentity();
glEnable(GL_TEXTURE_2D);
glDisable(GL_DEPTH_TEST);
glBindTexture(GL_TEXTURE_2D, fbo_texture);
glBegin(GL_QUADS);
glTexCoord2i(0, 0);
glVertex2f(renderLeft, renderTop);
glTexCoord2i(0, 1);
glVertex2f(renderLeft, renderTop + renderHeight);
glTexCoord2i(1, 1);
glVertex2f(renderLeft + renderWidth, renderTop + renderHeight);
glTexCoord2i(1, 0);
glVertex2f(renderLeft + renderWidth, renderTop);
glEnd();
glPopMatrix();
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glPopAttrib();
What's the value of status after:
GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
If the value is anything other than GL_FRAMEBUFFER_COMPLETE, OpenGL will probably choke when it tries to read from the FBO.
The glCheckFramebufferStatus docs describes other (error) values it can return, and what causes them.
Of particular interest might be:
If the currently bound framebuffer is not framebuffer complete, then
it is an error to attempt to use the framebuffer for writing or
reading. This means that rendering commands (glDrawArrays and
glDrawElements) as well as commands that read the framebuffer
(glReadPixels, glCopyTexImage2D, and glCopyTexSubImage2D) will
generate the error GL_INVALID_FRAMEBUFFER_OPERATION if called while
the framebuffer is not framebuffer complete.
(emphasis mine)
edit based on your comments:
To paraphrase the docs wrt GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
Not all framebuffer attachment points are framebuffer attachment complete.
This means that one of the following is happening:
At least one attachment point with a renderbuffer or texture attached has its attached object no longer in existence or has an attached image with a width or height of zero,
The color attachment point has a non-color-renderable image attached. Color-renderable formats include GL_RGBA4, GL_RGB5_A1, and GL_RGB565.
The depth attachment point has a non-depth-renderable image attached. GL_DEPTH_COMPONENT16 is the only depth-renderable format.
The stencil attachment point has a non-stencil-renderable image attached. GL_STENCIL_INDEX8 is the only stencil-renderable format.
We can rule out the last 2 bullets, because it doesn't appear that you're using depth or stencil attachements. That leaves two calls to examine:
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, fbo_texture, 0);
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, rbo_id);
From the opengl.org wiki on FBOs:
You get GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT when any of the attachments are 'incomplete'. Criteria for completeness are:
The source object for the image still exists and has the same type it was attached with.
The image has a non-zero width and height.
The layer for 3D or array textures attachments is less than the depth of the texture.
The image's format must match the attachment point's requirements, as defined above. Color-renderable formats for color attachments, etc.
The wiki says of GL_COLOR_ATTACHMENTi​:
These attachment points can only have images bound to them with
color-renderable formats. All compressed image formats are not
color-renderable, and thus cannot be attached to an FBO.
Double check that the fbo_texture and rbo_id are still valid, and that their height/width aren't 0. Finally, it could be fbo_texture's format. You've got it set to GL_RGBA8, but the docs say valid options include GL_RGBA4, GL_RGB5_A1, and GL_RGB565. I'm not sure whether or not that excludes all other formats (like your GL_RGBA8). The wiki seems to suggest that any non-compressed format should work. Try switching it to GL_RGBA4, and see if that works out.
glGetError error codes "stick" and are not automatically cleared. If something at the beginning your program generates OpenGL error AND you check for error code 1000 opengl calls later, error will be still here.
So if you want to understand what's REALLY going on, check for errors after every OpenGL call, or call glGetError in a loop, until all error codes are returned (as OpenGL documentation suggests).
I solved the problem. It was an extensions problem which made the render buffer object disappear. I basically changed this
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, rbo_id);
glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT, width, height);
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo_id);
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
GL_TEXTURE_2D, fbo_texture, 0);
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT,
GL_RENDERBUFFER_EXT, rbo_id);
GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
for this
glBindRenderbuffer(GL_RENDERBUFFER, rbo_id);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, width, height);
glBindRenderbuffer(GL_RENDERBUFFER, 0);
glBindFramebuffer(GL_FRAMEBUFFER, fbo_id);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
GL_TURE_2D, fbo_texture, 0);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
GL_RENDERBUFFER, rbo_id);
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
and then it worked. I still wonder exactly what the problem was, but so far I am happy with the result. Special thanks to #luke who's answer helped to locate the exact point of the problem.
Exactly, what command raises error? Try to replace GL_QUADS with GL_TRIANGLE_FAN.