I am trying to display a sphere and a torus on the same screen, but it seems like the "glutInitDisplayMode" is what is causing me to display only one.
When I keep it as glutInitDisplayMode(GLUT_SINGLE | GLUT_RGBA |GLUT_DEPTH) the torus displays.
When I keep it as glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH) the sphere displays. What can I do to display both?
The render code is below:
static void render(void) {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
// clear the drawing buffer.
glClear(GL_COLOR_BUFFER_BIT);
// clear the identity matrix.
glLoadIdentity();
glTranslatef(0.0, 0.0, -5.0);
glColor3f(0.0, 0.0, 0.0);
glRotatef(zRotated, 0.0, 0.0, 1.0);
// scaling transfomation
glScalef(1.0, 1.0, 1.0);
// built-in (glut library) function , draw you a sphere.
glutSolidTorus(innerRadius, outerRadius, sides, rings);
// Flush buffers to screen
glFlush();
// glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// activate our shader program
glUseProgram(programId);
// turn on depth buffering
glEnable(GL_DEPTH_TEST);
float aspectRatio = (float)width / (float)height;
glm::mat4 projection = glm::perspective(glm::radians(45.0f), aspectRatio, 0.1f, 1000.0f);
// view matrix - orient everything around our preferred view
glm::mat4 view = glm::lookAt(
glm::vec3(40,30,30), // eye/camera location
glm::vec3(0,0,0), // where to look
glm::vec3(0,1,0) // up
);
// model matrix: translate, scale, and rotate the model
glm::vec3 rotationAxis(0,1,0);
glm::mat4 model = glm::mat4(1.0f);
model = glm::rotate(model, glm::radians(angle), glm::vec3(0, 1, 0)); // rotate about the y-axis
model = glm::scale(model, glm::vec3(25.0f, 25.0f, 25.0f));
// model-view-projection matrix
glm::mat4 mvp = projection * view * model;
GLuint mvpMatrixId = glGetUniformLocation(programId, "MVP");
glUniformMatrix4fv(mvpMatrixId, 1, GL_FALSE, &mvp[0][0]);
// texture sampler - a reference to the texture we've previously created
// send the texture id to the texture sampler
GLuint textureUniformId = glGetUniformLocation(programId, "textureSampler");
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, textureId);
glUniform1i(textureUniformId, 0);
// find the names (ids) of each vertex attribute
GLint positionAttribId = glGetAttribLocation(programId, "position");
GLint colourAttribId = glGetAttribLocation(programId, "colour");
GLint textureCoordsAttribId = glGetAttribLocation(programId, "textureCoords");
GLint normalAttribId = glGetAttribLocation(programId, "normal");
// provide the vertex positions to the shaders
glBindBuffer(GL_ARRAY_BUFFER, positions_vbo);
glEnableVertexAttribArray(positionAttribId);
glVertexAttribPointer(positionAttribId, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
// provide the vertex texture coordinates to the shaders
glBindBuffer(GL_ARRAY_BUFFER, textureCoords_vbo);
glEnableVertexAttribArray(textureCoordsAttribId);
glVertexAttribPointer(textureCoordsAttribId, 2, GL_FLOAT, GL_FALSE, 0, nullptr);
// provide the vertex normals to the shaders
glBindBuffer(GL_ARRAY_BUFFER, normals_vbo);
glEnableVertexAttribArray(normalAttribId);
glVertexAttribPointer(normalAttribId, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
// draw the triangles
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
glDrawElements(GL_TRIANGLES, numVertices, GL_UNSIGNED_INT, (void*)0);
// disable the attribute arrays
glDisableVertexAttribArray(positionAttribId);
glDisableVertexAttribArray(textureCoordsAttribId);
glDisableVertexAttribArray(normalAttribId);
glDisableVertexAttribArray(colourAttribId);
// make the draw buffer to display buffer (i.e. display what we have drawn)
glutSwapBuffers();
}
glutSolidTorus draws a torus, by the use of the fixed function attributes. For this a compatibility profile OpenGL Context indispensable.
glutSolidTorus is not compatible with you shader program. Invalidate the currently installed program, before glutSolidTorus:
glUseProgram(0);
glutSolidTorus(innerRadius, outerRadius, sides, rings);
Note, OpenGL is a state engine. If a program is installed, it is kept, until another program is installed or it is invalidated, even beyond frames. In you case is is not an issue in the first frame, but it would be still installed at the begin of the 2nd frame, when glutSolidTorus is called.
If you are use a double buffered window (GLUT_DOUBLE) you have to call glutSwapBuffers. glutSwapBuffers swaps the buffers. The buffer in which was drawn, is shown in the window. The buffer which was show int eh window is prepared for drawing in the next frame.
In a single buffered window you can do glFlush. This forces OpenGL to finish drawing. Since the buffer which is draw to is the same, which is shown on the window, this causes that all what is drawing to the buffer is immediately shown in the window.
Move the singe glFlush call form the middle of the render function to its end, right before glutSwapBuffers:
void render()
{
// ...
glUseProgram(0);
glutSolidTorus(innerRadius, outerRadius, sides, rings);
// glFlush(); <---- delete
// ...
glUseProgram(programId);
// ...
glDrawElements(GL_TRIANGLES, numVertices, GL_UNSIGNED_INT, (void*)0);
// ...
glFlush();
glutSwapBuffers();
}
Related
I'm working on a old code that used fixed function pipeline, the scene is a bit complex but works fine. For the sake of simplicity, I replaced it with one blue triangle :
void RenduOpenGL::paintGL()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
glViewport(0, 0, this->width(), this->height());
glBegin(GL_TRIANGLES);
glColor3d(0,0,1);
glVertex3d(0.7, 0.7, 0.0);
glVertex3d(-0.5, 0.7, 0.0);
glVertex3d(0.1, -0.7, 0.0);
glEnd();
}
Now I want to add shaders for new elements in the scene but keep the old elements of the scene like this blue triangle.
I've read here that I can mix the two to produce a scene containing the first then the second.
Therefore I want to add this code after the blue triangle :
float vertices[] = {
0.6, 0.6, 0.0,
-0.6, 0.6, 0.0,
0.0, -0.6, 0.0,
};
vbo.create(); // glGenBuffers(...);
vbo.bind(); // glBindBuffer(GL_ARRAY_BUFFER, vbo);
vbo.allocate(vertices, sizeof(vertices)); // glBufferData(GL_ARRAY_BUFFER, 9 * sizeof(float), vertices, GL_STATIC_DRAW);
vbo.release(); // glBindBuffer(GL_ARRAY_BUFFER, 0);
prog.addShaderFromSourceFile(QOpenGLShader::Vertex, "shaders/base.vert");
prog.addShaderFromSourceFile(QOpenGLShader::Fragment, "shaders/base.frag");
vao.create(); // glGenVertexArrays(...)
vao.bind(); // glBindVertexArray(vao);
prog.enableAttributeArray("position"); // glEnableVertexAttribArray(VAO_position);
prog.setAttributeBuffer("position", GL_FLOAT, 0, 3); // (offset, size, stride=0); // glVertexAttribPointer(VAO_position, 4, GL_FLOAT, False, 0, reinterpret_cast<const void *>(offset)(0)); (False,
vao.release(); // glBindVertexArray(0);
// draw the triangle
prog.bind(); // glUseProgram(shader_program);
vao.bind(); // glBindVertexArray(vertex_array_object);
glDrawArrays(GL_TRIANGLES, 0, 3);
vao.release(); // glBindVertexArray(0);
prog.release(); // glUseProgram(0);
I use Qt to call the openGL functions, the corresponding opengl functions are in comments.
My shaders are very basic :
// base.vert
#version 330
// vertex shader
in vec3 position;
void main() {
gl_Position = vec4(position.xyz, 1);
}
// base.frag
#version 330
// fragment shader
out vec4 pixel;
void main() {
pixel = vec4(1, 0.5, 0, 1);
}
That is supposed to draw an orange triangle, but when I put the code after the blue triangle code, I don't see the orange triangle created from shaders.
Short (with code) answer:
The VBO and the prog.enableAttributeArray and prog.setAttributeBuffer should be in the VAO.
Something along the lines:
float vertices[] = {
0.6, 0.6, 0.0,
-0.6, 0.6, 0.0,
0.0, -0.6, 0.0,
};
prog.bind(); // glUseProgram(shader_program);
vao.create(); // glGenVertexArrays(...)
vao.bind(); // glBindVertexArray(vao);
vbo.create(); // glGenBuffers(...);
vbo.bind(); // glBindBuffer(GL_ARRAY_BUFFER, vbo);
vbo.allocate(vertices, sizeof(vertices)); // glBufferData(GL_ARRAY_BUFFER, 9 * sizeof(float), vertices, GL_STATIC_DRAW);
//vbo.release(); // glBindBuffer(GL_ARRAY_BUFFER, 0);
prog.addShaderFromSourceFile(QOpenGLShader::Vertex, "shaders/base.vert");
prog.addShaderFromSourceFile(QOpenGLShader::Fragment, "shaders/base.frag");
prog.enableAttributeArray("position"); // glEnableVertexAttribArray(VAO_position);
prog.setAttributeBuffer("position", GL_FLOAT, 0, 3); // (offset, size, stride=0); // glVertexAttribPointer(VAO_position, 4, GL_FLOAT, False, 0, reinterpret_cast<const void *>(offset)(0)); (False,
vao.release(); // glBindVertexArray(0);
// draw the triangle
prog.bind(); // glUseProgram(shader_program);
vao.bind(); // glBindVertexArray(vertex_array_object);
glDrawArrays(GL_TRIANGLES, 0, 3);
vao.release(); // glBindVertexArray(0);
prog.release(); // glUseProgram(0);
Not so long but textual answer: OpenGL is a state machine, you need to link together: the VBO and how to read its data, inside the VAO. However, IMHO, Qt people have sadly chosen their abstractions poorly: enableAttributeArray and setAttributeBuffer would be clearer as members of the VAO class instead of the prog class.
I am writing a 3D graphics renderer in C++ using OpenGL-ES for a handheld system and I am utilizing a decal (texture) shader, as well as a color-fill shader. I have two render passes where I use the respective program and use Array/Element buffers to draw data using glDrawElements.
Although I enable GL_DEPTH_TEST in my application, my decal polygons always render in front of my color-filled polygons.
I have tried reworking how my projection/modelView matrices are built and passed to the shaders, I have tried different glDepthFunc parameters but I am not able to get them to render properly.
This is my draw code - I start each frame with
glClearColor(0.25f, 0.25f, 0.25f, 1.f);
glClearDepthf(1.f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
Then I calculate world-space polygon coordinates and arrange it into GLfloat vectors. I draw the decal data first:
GLuint programId = decalProgramId;
glUseProgram(programId);
// All of my uniform params are setup here - omitting to save space
// Set proj/mv matrices
glUniformMatrix4fv(glGetUniformLocation(programId, "uProjection"), 1, GL_TRUE, static_cast<f32*>(gameEngine.proj));
glUniformMatrix4fv(glGetUniformLocation(programId, "uModelView"), 1, GL_TRUE, static_cast<f32*>(gameEngine.modelView));
// Then I prepare the buffer data
glBindBuffer(GL_ARRAY_BUFFER, decalBufferId);
glBufferData(GL_ARRAY_BUFFER, coordSize + texCoordSize, 0, GL_STATIC_DRAW);
glBufferSubData(GL_ARRAY_BUFFER, 0, coordSize, &coords[0]);
glBufferSubData(GL_ARRAY_BUFFER, coordSize, texCoordSize, &texCoords[0]);
// And element array buffer data
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, decalElementBufferId);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indexSize, &indices[0], GL_STATIC_DRAW);
// Enable our vertex attributes
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, (GLvoid*)(coordSize));
// Bind my test texture
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, textureId);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
// Draw the elements
glDrawElements(GL_TRIANGLES, indexCount, GL_UNSIGNED_SHORT, 0);
The process is then repeated with my color polygons. Followed by SwapBuffer and WaitVSync commands.
Here is my code for creating one of the triangles and the front face of the cube:
// Add polygon directly to the scene object
scene.AddPolygon(polygonBuilder
.AddVertex(Vector3(0.5f, 0.5f, 0.f), Vector4(0.f, 0.f, 1.f, 1.f))
.AddVertex(Vector3(0.25f, 0.f, 0.f), Vector4(0.f, 1.f, 0.f, 1.f))
.AddVertex(Vector3(0.75f, 0.f, 0.f), Vector4(1.f, 0.f, 0.f, 1.f))
.AddIndex(0).AddIndex(1).AddIndex(2)
.Build()
);
// Create a polygon within the crate object
crateObject.AddPolygon(polygonBuilder
.AddVertex(Vector3(-0.25f, 0.25f, 0.f), Vector2(0.f, 0.f))
.AddVertex(Vector3(-0.25f, -0.25f, 0.f), Vector2(0.f, 1.f))
.AddVertex(Vector3(0.25f, -0.25f, 0.f), Vector2(1.f, 1.f))
.AddVertex(Vector3(0.25f, 0.25f, 0.f), Vector2(1.f, 0.f))
.SetTexture("crate")
.AddIndex(0).AddIndex(1).AddIndex(3)
.AddIndex(3).AddIndex(1).AddIndex(2)
.Build()
);
// Add the crate object as a child within the scene
scene.AddChild(crate);
This screenshot is the current output when I create two colored triangles and one textured cube:
The blue arrow indicates a triangle that should have rendered in the front. Any ideas?
I feel really silly now. My color shader was not properly applying the model-view matrix. It was always rendering at a fixed depth.
I modified my color shader code to apply the matrix the same way as the decal and now it works perfectly.
I've been looking into how to make the bubble texture transparent but haven't found anything that would fit in my code. I have tried with glColor4f() but I might be putting it in the wrong place. I'm a total beginner in openGL and I've been given a basic code to which I need to add other objects in order to make a 2D scene. I also don't exactly know what every single line does.
These are the relevant pieces of code:
// Globals
GLuint locT; // location of "T" uniform variable in myShaderProgram
GLuint locT2;
// Textures
GLuint myBubblesTexture = 0;
// Shader program object for applying textures to our shapes
GLuint myShaderProgram;
// Vertex Buffer Object IDs for the ground texture object
GLuint bubblesPosVBO, bubblesColourVBO, bubblesTexCoordVBO, bubblesIndicesVBO;
// 1) Position Array - Store vertices as (x,y) pairs
static GLfloat bubblesVertices[] = {
-0.2f, -0.2f,
-0.2f, 0.2f,
0.2f, -0.2f,
0.2f, 0.2f
};
// 2) Colour Array - Store RGB values as unsigned bytes
static GLubyte bubblesColors[] = {
255, 0, 0, 255,
255, 255, 0, 255,
0, 255, 0, 255,
0, 255, 255, 255
};
// 3) Texture coordinate array (store uv coordinates as floating point values)
static float bubblesTextureCoords[] = {
0.0f, 1.0f,
0.0f, 0.0f,
1.0f, 1.0f,
1.0f, 0.0f
};
// 4) Index Array - Store indices to quad vertices - this determines the order the vertices are to be processed
static GLubyte bubblesVertexIndices[] = { 0, 1, 2, 3 };
void init(int argc, char* argv[]);
void setupBubblesTextureVBO(void);
void display(void);
void drawTexturedBubblesVBO(void);
int _tmain(int argc, char* argv[])
{
init(argc, argv);
glutMainLoop();
// Shut down COM
shutdownCOM();
return 0;
}
void init(int argc, char* argv[]) {
// Initialise COM so we can use Windows Imaging Component
initCOM();
// Initialise FreeGLUT
glutInit(&argc, argv);
glutInitContextVersion(3, 3);
glutInitContextProfile(GLUT_COMPATIBILITY_PROFILE);
glutInitDisplayMode(GLUT_RGBA | GLUT_DEPTH | GLUT_DOUBLE);
glutInitWindowSize(1200, 800);
glutInitWindowPosition(64, 64);
glutCreateWindow("Funky Fish");
// Register callback functions
glutDisplayFunc(display);
// Initialise GLEW library
GLenum err = glewInit();
// Setup colour to clear the window
glClearColor(0.2f, 0.2f, 0.8f, 0.0f);
glLineWidth(9.0f);
//Load textures
myBubblesTexture = fiLoadTextureA("bubbles.png");
//Shader setup
myShaderProgram = setupShaders(string("Shaders\\basic_vertex_shader.txt"), string("Shaders\\basic_fragment_shader.txt"));
// Get uniform location of "T" variable in shader program (we'll use this in the play function to give the uniform variable "T" a value)
locT = glGetUniformLocation(myShaderProgram, "T");
//Setup the bubbles using VBO
setupBubblesTextureVBO();
}
// our bubbles
void setupBubblesTextureVBO(void) {
// setup VBO for the quad object position data
glGenBuffers(1, &bubblesPosVBO);
glBindBuffer(GL_ARRAY_BUFFER, bubblesPosVBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(bubblesVertices), bubblesVertices, GL_STATIC_DRAW);
// setup VBO for the quad object colour data
glGenBuffers(1, &bubblesColourVBO);
glBindBuffer(GL_ARRAY_BUFFER, bubblesColourVBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(bubblesColors), bubblesColors, GL_STATIC_DRAW);
// setup VBO for the quad object texture coord data
glGenBuffers(1, &bubblesTexCoordVBO);
glBindBuffer(GL_ARRAY_BUFFER, bubblesTexCoordVBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(bubblesTextureCoords), bubblesTextureCoords, GL_STATIC_DRAW);
// setup quad vertex index array
glGenBuffers(1, &bubblesIndicesVBO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, bubblesIndicesVBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(bubblesVertexIndices), bubblesVertexIndices, GL_STATIC_DRAW);
}
void display(void) {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// draw our bubble
drawTexturedBubblesVBO();
glutSwapBuffers();
}
void drawTexturedBubblesVBO(void) {
glUseProgram(myShaderProgram);
glEnable(GL_TEXTURE_2D);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_BLEND);
// Move our bubble to the centre of the screen
GUMatrix4 T = GUMatrix4::translationMatrix(0.0f, 0.0f, 0.0f);
glUniformMatrix4fv(locT, 1, GL_FALSE, (GLfloat*)&T);
// Bind each vertex buffer and enable
// The data is still stored in the GPU but we need to set it up (which also includes validation of the VBOs behind-the-scenes)
// Bind texture
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, myBubblesTexture);
glUniform1i(glGetUniformLocation(myShaderProgram, "texture"), 0);
glEnable(GL_TEXTURE_2D);
glBindBuffer(GL_ARRAY_BUFFER, bubblesPosVBO);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, (const GLvoid*)0);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, bubblesColourVBO);
glVertexAttribPointer(1, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, (const GLvoid*)0);
glEnableVertexAttribArray(1);
glBindBuffer(GL_ARRAY_BUFFER, bubblesTexCoordVBO);
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 0, (const GLvoid*)0);
glEnableVertexAttribArray(2);
// Bind the index buffer
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, bubblesIndicesVBO);
// Draw the object - same function call as used for vertex arrays but the last parameter is interpreted as an offset into the currently bound index buffer (set to 0 so we start drawing from the beginning of the buffer).
glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_BYTE, (GLvoid*)0);
// glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glDisable(GL_TEXTURE_2D);
// use to force disable our shaderprogram
// glUseProgram(0);
}
The code looks OK so:
Does your Texture have an alpha channel?
Does your OpenGL context pixel format has Alpha channel buffer?
What kind of transparency you want (whole texture have the same transparency, or the transparency should be modulated)?
The glColor4f(1.0,1.0,1.0,alpha) will work only if your textures are configured to be modulated by glColor and have nonzero alpha channel set so you need to add:
glTexEnvi(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_MODULATE);
call after binding the texture to make it work.
In case you do not have alpha channel (in texture or in pixelformat) you can use:
glBlendFunc(GL_SRC_COLOR, GL_ONE_MINUS_SRC_COLOR);
Also take a look at:
OpenGL - How to create Order Independent transparency?
Normally this code renders the image of the texture to screen. But if I now add the command glBindFramebuffer(GL_FRAMEBUFFER,0) to the code, it will not render anything. It renders the screens just in the color of glClearColor. I am working with QT so using QOpenGLWidget.
glViewport(0, 0, _width, _height);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glClearColor(0.0,0.0,0.0,1.0);
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
glDisable(GL_DEPTH_TEST);
_program.bind();
glBindVertexArray(_vao);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, textureID);
glUniform1i(glGetUniformLocation(_program.programId(), "u_texture"), 1);
glDrawArrays(GL_TRIANGLES, 0, 6);
glBindVertexArray(0);
Want can go possibly wrong?
EDIT:
/* final.fsh */
# version 330 core
uniform sampler2D u_texture;
in vec4 qt_TexCoord0;
out vec4 fragColor;
void main(void)
{
fragColor = texture(u_texture, qt_TexCoord0.xy);
}
/* final.vsh */
# version 330 core
layout (location = 0) in vec3 a_position;
out vec4 qt_TexCoord0;
void main(void)
{
gl_Position = vec4(a_position, 1.0);
const mat4 B = mat4(0.5, 0.0, 0.0, 0.0,
0.0, 0.5, 0.0, 0.0,
0.0, 0.0, 0.5, 0.0,
0.5, 0.5, 0.5, 1.0);
qt_TexCoord0 = B * vec4(a_position, 1.0);
}
/* Loads VAO to GPU */
GLfloat max_ = 1.0;
GLfloat min_ = -1.0;
GLfloat vert[] = {
max_, max_, 0,
max_, min_, 0,
min_, max_, 0,
max_, min_, 0,
min_, min_, 0,
min_, max_, 0,
};
glGenVertexArrays(1, &_vao);
glBindVertexArray(_vao);
GLuint vbo;
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(vert), vert, GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(GLfloat)*3, (GLvoid*)0);
glBindVertexArray(0);
As stated by G.M., and according to the docs, glBindFramebuffer(GL_FRAMEBUFFER, 0) "breaks the existing binding of a framebuffer object to the target". You need this call after having used your framebuffers to do some offscreen rendering. When you want to finally render to the screen, you have to render the the back buffer, by calling glDrawBuffer(GL_BACK).
So your render loop might look like
// Do some rendering stuff in n offscreen textures
glBindFramebuffer(GL_FRAMEBUFFER, the_buffer);
glDrawBuffers(n, buffers);
// Rendering calls
// Finally use the results for the final rendering
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glDrawBuffer(GL_BACK);
// Rendering calls
EDIT:
It appears you are using QOpenGLWidget as your OpenGL provider / windowing system. The Qt guys are using framebuffers to render their UI, and the content of the result of your QOpenGLWidget is drawn inside an FBO.
So, what it means (at least in my experience, there might be a better way to tackle this problem), is that you cannot render in the backbuffer anymore, you have to render in Qts framebuffer.
One way to do this (again, it might not be the best way at all, but it has worked for me), is to save the bound framebuffer at the begining of your rendering, and do your final rendering in this buffer. Which leads to
// First of all, save the already bound framebuffer
GLint qt_buffer;
glGetIntegerv(GL_FRAMEBUFFER_BINDING, &qt_buffer);
// Do some rendering stuff in n offscreen textures
glBindFramebuffer(GL_FRAMEBUFFER, your_buffer);
glDrawBuffers(n, buffers);
// Rendering calls
// Finally use the results for the final rendering
if (glIsFramebuffer(qt_buffer))
{
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glDrawBuffer(GL_BACK);
}
else
{
glBindFramebuffer(GL_FRAMEBUFFER, qt_buffer);
glDrawBuffers(1, buffers);
}
// Rendering calls
I have the same issue and finally I find the cause is glBindFramebuffer(GL_FRAMEBUFFER, 0);
QOpenGLWidget's default framebuffer may not be 0, so you need to get it by calling QOpenGLContext::defaultFramebufferObject()
so change like this:
glViewport(0, 0, _width, _height);
glBindFramebuffer(GL_FRAMEBUFFER, defaultFramebufferObject()); //<-- change here
glClearColor(0.0,0.0,0.0,1.0);
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
glDisable(GL_DEPTH_TEST);
_program.bind();
glBindVertexArray(_vao);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, textureID);
glUniform1i(glGetUniformLocation(_program.programId(), "u_texture"), 1);
glDrawArrays(GL_TRIANGLES, 0, 6);
glBindVertexArray(0);
I've been trying to render a cube in a QGLWidget, but it comes out wrong. No matter how I rotate it, it looks like a flat square. It's like it didn't notice the Z coordinates of its vertices. Just before I added clearing of the GL_DEPTH_BUFFER_BIT, the square looked like all of the cube's sides crammed into one. Now it seems to discard vertices which don't belong in the front side, but it still isn't a cube.!
Screenshots [link]
My initializeGL() and paintGL():
typedef struct
{
float XYZW[4];
float RGBA[4];
} Vertex;
Vertex Vertices[8] =
{
//vertices
};
const GLubyte Indices[36] =
{
//indices
};
void ModelView::initializeGL()
{
m_program = new QGLShaderProgram(this);
m_program->addShaderFromSourceCode(QGLShader::Vertex, vertexShaderSource);
m_program->addShaderFromSourceCode(QGLShader::Fragment, fragmentShaderSource);
m_program->link();
}
void ModelView::paintGL()
{
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);
glClearColor(.5f, .5f, .5f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glViewport(0, 0, width(), height());
m_program->bind();
QMatrix4x4 matrix;
matrix.perspective(60, 4.0/3.0, 0.1, 100.0);
matrix.translate(0, 0, -2);
matrix.rotate(50.0, 1, 1, 1);
m_program->setUniformValue(m_matrixUniform, matrix);
m_posAttr = m_program->attributeLocation("posAttr");
m_colAttr = m_program->attributeLocation("colAttr");
m_matrixUniform = m_program->uniformLocation("matrix");
glGenBuffers(1, &BufferId);
glGenBuffers(1, &IndexBufferId);
glBindBuffer(GL_ARRAY_BUFFER, BufferId);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IndexBufferId);
glBufferData(GL_ARRAY_BUFFER, BufferSize, Vertices, GL_STATIC_DRAW);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(Indices), Indices, GL_STATIC_DRAW);
glVertexAttribPointer(m_posAttr, 2, GL_FLOAT, GL_FALSE, VertexSize, 0);
glVertexAttribPointer(m_colAttr, 3, GL_FLOAT, GL_FALSE, VertexSize, (GLvoid *)RgbOffset);
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_BYTE, NULL);
glDisableVertexAttribArray(1);
glDisableVertexAttribArray(0);
m_program->release();
}
Vertices and Indices should be defined correctly, they're taken from a tutorial, as is most of the code. Rendering of 2D object seems to be just fine, though.
Also, why does the tutorial call matrix.translate with the -2 argument? If I change it to anything else greater than 1 or remove it, the rendered object disappears.
Qt5, Windows Vista 32-bit.
Also, why does the tutorial call matrix.translate with the -2
argument? If I change it to anything else greater than 1 or remove it,
the rendered object disappears.
This is due to clipping. When you render objects, things that are "too close" or "too far" are discarded, via the near and far clipping planes (respectively).
By moving the cube closer (changing -2 to 1 or 0), you are bringing the cube forward, past the near clipping plane, and it consequently disappears.
glVertexAttribPointer() has a size parameter, which specifies the number of components per vertex. In the code it is 2, therefore everything is 2D. Changing to 3 solves the issue.