How to use Vertex Array Object? - c++

I am trying to simulate a cube bouncing between walls. For this purpose, I have constructed 2 vertex array objects, one of them representing the cube and the other representing walls. Firstly, I created walls. I am drawing walls with glDrawElements call since I have used index (element) buffers to create it. I have also created a cube model, but I am not using index buffer for it, so I will use glDrawArrays call to draw it as far as I know. My walls are showing up nicely, but I cannot figure out how to draw the cube (at this step, I am not even trying to animate the cube, I just want to draw it) This is what my code looks like:
#include "Cube.h"
#include <cstring>
GLuint vao[2];
void init()
{
cube();
GLuint program = InitShader( "vshader.glsl", "fshader.glsl" );
glUseProgram( program );
GLuint vPosition = glGetAttribLocation(program, "vPosition");
glGenVertexArrays(2, vao);
glBindVertexArray(vao[0]);
GLuint cube_buffer;
glGenBuffers(1, &cube_buffer);
glBindBuffer(GL_ARRAY_BUFFER, cube_buffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(cubePoints), cubePoints, GL_STATIC_DRAW);
glEnableVertexAttribArray(vPosition);
glVertexAttribPointer(vPosition, 4, GL_FLOAT, GL_FALSE, 0, (void*)0);
const float mid_value = 0.0f;
const float far_value = 0.35f;
const float near_value = 1.0f;
const float positions[60] = {
/// positions /// colors
mid_value, -near_value, 1.0, 0.0, 0.0, /// 0
near_value, -near_value, 1.0, 0.0, 0.0, /// 1
near_value, mid_value, 0.0, 1.0, 0.0, /// 2
near_value, near_value, 0.0, 1.0, 0.0, /// 3
mid_value, near_value, 1.0, 1.0, 0.0, /// 4
-near_value, near_value, 1.0, 1.0, 0.0, /// 5
-near_value, mid_value, 0.0, 0.0, 1.0, /// 6
-near_value, -near_value, 0.0, 0.0, 1.0, /// 7
far_value, -far_value, 1.0, 0.0, 0.0, /// 8
far_value, far_value, 0.0, 1.0, 0.0, /// 9
-far_value, far_value, 1.0, 1.0, 0.0, /// 10
-far_value, -far_value, 0.0, 0.0, 1.0 /// 11
};
unsigned int indices[36] = {
7,11,0,
0,8,1,
1,8,2,
2,9,3,
3,9,4,
4,10,5,
5,10,6,
6,11,7,
11,0,8,
8,2,9,
9,4,10,
10,6,11,
};
glBindVertexArray(vao[1]);
GLuint room_buffer;
glGenBuffers(1, &room_buffer);
glBindBuffer(GL_ARRAY_BUFFER, room_buffer);
glBufferData(GL_ARRAY_BUFFER, 60 * sizeof(float), positions, GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 5, (void*)0); /// positions
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 5, (void*)(2* sizeof(float))); /// colors
GLuint index_buffer;
glGenBuffers(1, &index_buffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index_buffer);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, 36 * sizeof(unsigned int), indices, GL_STATIC_DRAW);
glClearColor(1.0, 1.0, 1.0, 1.0);
}
void display()
{
glClear(GL_COLOR_BUFFER_BIT);
glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_INT, nullptr);
// glDrawArrays(...); --> how to use this, or should I really use this here?
glutSwapBuffers();
}
void idle() {
glutPostRedisplay();
}
void reshape(int width, int height) {
glViewport(0, 0, width, height);
}
int main( int argc, char **argv )
{
glutInit( &argc, argv );
glutInitDisplayMode( GLUT_RGBA | GLUT_DOUBLE);
glutInitWindowSize( 600, 600 );
glutCreateWindow( "Bouncing Cube" );
glewExperimental = GL_TRUE;
glewInit();
init();
glutDisplayFunc(display);
glutIdleFunc(idle);
glutReshapeFunc(reshape);
glutMainLoop();
}
In this code, cubePoints is filled by cube() method in another translation unit. I am not exactly sure how to draw cube on the screen, and how to use glDrawArrays here? Should I bind or unbind anything to draw it? I feel like I am not using vertex array objects properly. Below is what my walls look like:
I simply want cube to appear on the far side, where the white rectangle is located at. Is it possible to call glDrawArrays with glDrawElements?

You must bind the Vertex Array Object before the "draw" call. The drawing instruction uses the data stored in the currently bound Vertex Array Object:
void display()
{
glClear(GL_COLOR_BUFFER_BIT);
glBindVertexArray(vao[0]);
glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_INT, nullptr);
glBindVertexArray(vao[1]);
glDrawArrays(...);
glutSwapBuffers();
}

Related

OpenGL mix fix pipeline and shader program (Qt)

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.

How to draw multiple shapes

I'm trying to make a program with OpenGL that creates two rectangles, but my problem is that when I create my two model_views, the first one gets overwritten by the second one so only one rectangle is displaying and I'm not sure how to display both. I posted the entire code. How do I get both triangles to render?
using namespace std;
#include "vgl.h"
#include "LoadShaders.h"
#include "glm\glm.hpp"
#include "glm\gtc\matrix_transform.hpp"
enum VAO_IDs { Triangles, NumVAOs };
enum Buffer_IDs { ArrayBuffer, NumBuffers };
enum Attrib_IDs { vPosition = 0 };
GLuint VAOs[NumVAOs];
GLuint Buffers[NumBuffers];
GLuint location;
const GLuint NumVertices = 4;
//---------------------------------------------------------------------
// Setting up our pipeline and preparing to draw
void init(void)
{
//Defining the name of our shader files
ShaderInfo shaders[] = {
{ GL_VERTEX_SHADER, "triangles.vert" },
{ GL_FRAGMENT_SHADER, "triangles.frag" },
{ GL_NONE, NULL }
};
//Loading and attaching shaders to our pipeline
GLuint program = LoadShaders(shaders);
glUseProgram(program); //My Pipeline is set up
// Coordinates of vertices (Square)
GLfloat vertices[NumVertices][2] = {
{ -0.3, -0.45 },
{ 0.3, -0.45 },
{ 0.3, 0.45 },
{ -0.3, 0.45 }
};
// Colors for vertices in {R, G, B} mode
GLfloat colorData[NumVertices][3] = {
{ 1,0,0 }, //Red
{ 0,1,0 }, //Green
{ 0,0,1 }, //Blue
{ 1,1,1 } //White
};
glGenBuffers(2, Buffers);
glBindBuffer(GL_ARRAY_BUFFER, Buffers[0]);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glBindAttribLocation(program, 0, "vPosition");
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(0));
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, Buffers[1]);
glBufferData(GL_ARRAY_BUFFER, sizeof(colorData), colorData, GL_STATIC_DRAW);
glBindAttribLocation(program, 1, "vertexColor");
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(0));
glEnableVertexAttribArray(1);
location = glGetUniformLocation(program, "model_matrix");
}
//---------------------------------------------------------------------
//This is done by using glutDisplayFunc function. Look at the main method
void drawScene(void)
{
//Clear the screen and preparing to draw
glClear(GL_COLOR_BUFFER_BIT);
/////////THIS IS WERE I CREATE RECTANGLES
//Sun
glm::mat4 model_view = glm::translate(glm::mat4(1.0), glm::vec3(0.0, 0.0, 0.0));
model_view = glm::scale(model_view, glm::vec3(0.5, 0.5, 0)); //shrink it
glUniformMatrix4fv(location, 1, GL_FALSE, &model_view[0][0]);
glm::mat4 model_view2 = glm::translate(glm::mat4(1.0), glm::vec3(0.5, 0.0, 0.0));
model_view2 = glm::scale(model_view2, glm::vec3(0.5, 0.5, 0)); //shrink it
glUniformMatrix4fv(location, 1, GL_FALSE, &model_view2[0][0]);
//The following function passes the generated rotation function into the vertex-shader
//Starting the pipeline
glDrawArrays(GL_QUADS, 0, NumVertices);
glDrawArrays(GL_QUADS, 0, NumVertices);
//Flush the image onto the window (screen)
glFlush();
}
//The registration happens in the main() function using
glutIdleFunc(runEveryFrame) function.
void runEveryFrame()
{
//Increasing our rotation angle
rotate_value += 0.001;
glutPostRedisplay();
}
int main(int argc, char** argv)
{
//Initializing to draw
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGBA);
glutInitWindowSize(512, 512);
glutCreateWindow("Hello World");
glewInit();
//init function is defined above
init();
//Registering the display function
glutDisplayFunc(drawScene);
//Registering the idle function
glutIdleFunc(runEveryFrame);
//glutMainLoop enters the event processing loop
glutMainLoop();
}
You call glDrawArrays with the same arguments, without changing any uniform between the two calls. My bet would that the two shapes are drawed, one over the other.
You'd have to call glUniformXXX before each glDrawArrays calls, if the uniform data (the model/view matrices) have changed :
void drawScene(void) {
glClear(GL_COLOR_BUFFER_BIT);
//first draw call with model/view transformation 1
glm::mat4 model_view = glm::translate(glm::mat4(1.0), glm::vec3(0.0, 0.0, 0.0));
model_view = glm::scale(model_view, glm::vec3(0.5, 0.5, 0)); //shrink it
glUniformMatrix4fv(location, 1, GL_FALSE, &model_view[0][0]);
glDrawArrays(GL_QUADS, 0, NumVertices);
//second draw call with model/view transformation 2
glm::mat4 model_view2 = glm::translate(glm::mat4(1.0), glm::vec3(0.5, 0.0, 0.0));
model_view2 = glm::scale(model_view2, glm::vec3(0.5, 0.5, 0));
glUniformMatrix4fv(location, 1, GL_FALSE, &model_view2[0][0]);
glDrawArrays(GL_QUADS, 0, NumVertices);
//Flush the image onto the window (screen)
glFlush();
}

VBO - Drawing multiple elements with different colors

I am trying to draw two quads using vertex buffer objects in OpenGL. They should be draw with different colors. Like you see, the first quad has a red, green, blue and yellow vertices. The second quad has different colors, but the problem is that they second quad gets drawn completely yellow. This is my code:
GLfloat vertices[24] = {10.0, 10.0, 0.0, 10.0, -10.0, 0.0, -10.0, -10.0, 0.0, -10.0, 10.0, 0.0,
20.0, 20.0, 0.0, 20.0, 10.0, 0.0, 10.0, 10.0, 0.0, 10.0, 20.0, 0.0 };
glBindBuffer(GL_ARRAY_BUFFER, buffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 24, vertices, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
GLfloat colors[24] = {1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 0.0,
0.5, 0.5, 0.5, 0.7, 0.2, 1.0, 0.2, 1.0, 0.7, 0.8, 0.0, 0.45 };
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, colorBuffer);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLfloat) * 24, colors, GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glEnableClientState(GL_VERTEX_ARRAY);
glBindBuffer(GL_ARRAY_BUFFER, buffer);
glVertexPointer(3, GL_FLOAT, 0, 0);
glEnableClientState(GL_COLOR_ARRAY);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, colorBuffer);
glColorPointer(3, GL_FLOAT, 0, 0);
glDrawArrays(GL_QUADS, 0, 8);
This is how the quads are drawn:
The second quad is the one on top right. It should be multicolored, but it's drawn using the 4th element of the color buffer. What should I do to fix it?
See OpenGL 2.1 Reference Pages; glColorPointer:
glColorPointer specifies the location and data format of an array of color components to use when rendering. ...
If a non-zero named buffer object is bound to the GL_ARRAY_BUFFER target while a color array is specified, pointer is treated as a byte offset into the buffer object's data store.
In your code buffer is bound to the target GL_ARRAY_BUFFER;
glBindBuffer(GL_ARRAY_BUFFER, colorBuffer);
Then colorBuffer is bound to the target GL_ELEMENT_ARRAY_BUFFER and the color array is defined:
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, colorBuffer);
glColorPointer(3, GL_FLOAT, 0, 0);
Since buffer is still bound to the target GL_ARRAY_BUFFER at this point, glColorPointer uses buffer. This causes that the vertex coordinates are treated as colors and that`s what you can see in the rendering.
To solve the issue you have to bint colorBuffer to the target GL_ARRAY_BUFFER:
glBindBuffer(GL_ARRAY_BUFFER, colorBuffer);

openGL draw circle triangle and square in different display mode

I am using Xcode to write openGL. What I am doing is to draw a circle, a triangle, and a square.
However, I found that my circle only can display on
glutInitDisplayMode(GLUT_RGBA | GLUT_SINGLE);
the triangle and square can only display on glutInitDisplayMode(GLUT_3_2_CORE_PROFILE|GLUT_RGBA | GLUT_SINGLE);
How can i make them display together?
Here is part of my entire code:
#include "Angel.h" //includes gl.h, glut.h and other stuff...
void m_glewInitAndVersion(void); //pre-implementation declaration (could do in header file)
void close(void);
//Mesh 0
GLuint buffer[3];
GLuint VAO[3];
GLuint color_loc;
GLuint program;
const int NumVertices = 4;
// Vertices of a unit cube centered at origin, sides aligned with axes
vec2 points[4] = {
vec2( 0.25, 0.25),
vec2( 0.75, 0.25),
vec2( 0.75, 0.75),
vec2( 0.25, 0.75)
};
vec2 points2[3]={
vec2(-1,-1),
vec2(0,-1),
vec2(0,-0.7)};
// RGBA colors
vec4 blue_opaque = vec4( 0.0, 0.0, 1.0, 1.0 );
vec4 red_opaque = vec4(1.0, 0.0, 0.0, 1.0);
//----------------------------------------------------------------------------
// OpenGL initialization
void
init()
{
glClearColor( 1.0, 1.0, 1.0, 1.0 );
// glColor3f(1.0, 0.0, 0.0);
// glMatrixMode(GL_PROJECTION);
// glLoadIdentity();
// gluOrtho2D(-3.5, 3.5, -3.5, 3.5);
// Create and initialize a buffer object
glGenBuffers( 2, buffer );
glBindBuffer( GL_ARRAY_BUFFER, buffer[0] );
glBufferData( GL_ARRAY_BUFFER, sizeof(points), points, GL_STATIC_DRAW );
// Load shaders and use the resulting shader program
program = InitShader( "vshader00_v150.glsl", "fshader00_v150.glsl" );
glUseProgram( program );
// set up vertex arrays
GLuint vPosition = glGetAttribLocation( program, "vPosition" );
//Set up VAO
glGenVertexArrays(2,VAO);
glBindVertexArray(VAO[0]);
glBindBuffer(GL_ARRAY_BUFFER,buffer[0]);
glEnableVertexAttribArray( vPosition );
glVertexAttribPointer( vPosition, 2, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(0) );
color_loc = glGetUniformLocation(program, "color");
//triangle
// glBindVertexArray(VAO[1]);
// glBindBuffer(GL_ARRAY_BUFFER, buffer[1]);
// glBufferData(GL_ARRAY_BUFFER, sizeof(points2), points2, GL_STATIC_DRAW);
// glUseProgram(program);
// glEnableVertexAttribArray(vPosition);
// glVertexAttribPointer(vPosition, 2, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(0) );
}
//----------------------------------------------------------------------------
void
display( void )
{
glClear( GL_COLOR_BUFFER_BIT );
// const float PI=3.14159;
// glBegin(GL_TRIANGLE_FAN);
// All triangles fan out starting with this point
// glVertex2f (0.0,0.0);
// for (int i = 0; i <=361; i++)
// {
// glColor3f(float(rand())/float(RAND_MAX),
// float(rand())/float(RAND_MAX),
// float(rand())/float(RAND_MAX));
// glVertex2f(2.0*cos(i*PI/180), 2.0*sin(i*PI/180));
// }
// glEnd();
glBindVertexArray(VAO[0]);
glDrawArrays( GL_TRIANGLE_FAN, 0, NumVertices );
glUseProgram(program);
glUniform4fv(color_loc, 1, blue_opaque);
// glBindVertexArray(VAO[1]);
// glDrawArrays( GL_TRIANGLE_FAN, 0, 3);
// glUseProgram(program);
// glUniform4fv(color_loc, 1, red_opaque);
glFlush();
}
int main( int argc, char **argv )
{
glutInit( &argc, argv );
#ifdef __APPLE__
glutInitDisplayMode(GLUT_3_2_CORE_PROFILE|GLUT_RGBA | GLUT_SINGLE);
#else
glutInitDisplayMode( GLUT_RGBA | GLUT_SINGLE);
#endif
glutInitWindowSize( 500, 500 );
glutCreateWindow( "CS 432 Hello World" );
m_glewInitAndVersion();
init();
glutDisplayFunc( display );
glutKeyboardFunc( keyboard );
glutWMCloseFunc(close);
glutMainLoop();
return 0;
}
Your circle code doesn't work with GLUT_3_2_CORE_PROFILE because glBegin, glColor3f, glVertex2f and glEnd were removed in OpenGL 3, so OpenGL 3.2 (or later) doesn't have them.
I'm not sure exactly why your triangle and square code doesn't work without GLUT_3_2_CORE_PROFILE, but consider that VAOs were added in OpenGL 3, and when you don't specify GLUT_3_2_CORE_PROFILE, you get a version before 3.
Pick a version and stick with it.

Rendering quad with tiling image?

I am learning how to texture a quad in OpenGL. The idea is to have the image repeated across the whole quad, nevertheless I am getting the image stretched and the two triangles forming the quad are visible.
What am I missing? The code looks like follows
void GLViewer::initializeGL()
{
float vertices[] =
{
-0.5, 0.0, 0.0,
0.5, 0.0, 0.0,
0.5, 0.5, 0.0
};
// Setup viewport
glViewport(0, 0,this->width(), this->height());
// OpenGL configuration
glClearColor(0.0f,0.0f,0.0f,1.0f);
// Setup shaders
m_triangleShader.addShaderFromSourceFile(QGLShader::Vertex, ":/vshader.glsl");
m_triangleShader.addShaderFromSourceFile(QGLShader::Fragment, ":/fshader.glsl");
m_triangleShader.link();
glGenVertexArrays(1, &m_VAO);
glBindVertexArray(m_VAO);
glPointSize(10);
glGenBuffers(1, &m_VBO);
glBindBuffer(GL_ARRAY_BUFFER, m_VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
float quad[] =
{
-1.0, -1.0,
1.0, -1.0,
-1.0, 1.0,
1.0, 1.0
};
float uv[] =
{
0.0, 0.0,
1.0, 0.0,
1.0, 1.0,
0.0, 1.0
};
m_backgroundShader.addShaderFromSourceFile(QGLShader::Vertex, ":/vbackground.glsl");
m_backgroundShader.addShaderFromSourceFile(QGLShader::Fragment, ":/fbackground.glsl");
m_backgroundShader.link();
glGenVertexArrays(1, &m_backgroundVAO);
glBindVertexArray(m_backgroundVAO);
glGenBuffers(1, &m_quadVBO);
glBindBuffer(GL_ARRAY_BUFFER, m_quadVBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(quad), quad, GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);
glGenBuffers(1, &m_uvVBO);
glBindBuffer(GL_ARRAY_BUFFER, m_uvVBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(uv), uv, GL_STATIC_DRAW);
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, 0);
glGenTextures(1, &m_textureID);
glBindTexture(GL_TEXTURE_2D, m_textureID);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
QImage image(":/background.png");
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, image.width(), image.height(),
0, GL_RGBA, GL_UNSIGNED_BYTE, image.bits());
glBindTexture(GL_TEXTURE_2D, 0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
}
void GLViewer::paintGL()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glDepthMask(GL_TRUE);
glEnable(GL_DEPTH_TEST);
m_backgroundShader.bind();
glBindVertexArray(m_backgroundVAO);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, m_textureID);
glUniform1i(glGetUniformLocation(m_backgroundShader.programId(),"tex"),0);
glDrawArrays(GL_TRIANGLE_STRIP,0,4);
m_triangleShader.bind();
glBindVertexArray(m_VAO);
glDrawArrays(GL_TRIANGLES, 0, 3);
update();
}
Why do you expect your texture to be repeated (and how many times) by the code you are using?
However, the code as-is is consistent with your observation. You are using the texcoords in the range [0,1], so if you are not tweaking the texcoords before sampling the texture, you should only see the image strechted to the quads. You might do that via the shaders you have not pasted so far. If you want the texture to appear n-times tiled along the u dimension and m times along v, you need to use [0,n] for the u range and [0,m] for the v range, respectively.
The second issue is that your texcoords do not match your geometry. This is probably causing what you describe as "the two triangles forming the quad are visible". Your two trianges do not build up the quad in texture space you'd expect, you should swap the last two lines:
float uv[] =
{
0.0, 0.0,
1.0, 0.0,
1.0, 1.0, /* should be 0.0, 1.0 */
0.0, 1.0 /* should be 1.0, 1.0 */
};