openGL draw circle triangle and square in different display mode - c++

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.

Related

How to use Vertex Array Object?

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();
}

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();
}

Drawing an inverted triangle on top of a rectangle with OpenGL

This is the goal:
I can get the inverted triangle with:
GLfloat vertices[][4] = {
{-0.75, 0.5, 0.0, 1.0},
{0.75, 0.5, 0.0, 1.0},
{0.0, -0.75, 0.0, 1.0}};
and some of the rectangle with:
GLfloat vertices[][4] = {
{-0.9, 0.0, 0.0, 1.0},
{0.9, 0.0, 0.0, 1.0},
{-0.9, -0.9, 0.0, 1.0}};
When I try to add the fourth vertex ({0.0, -0.9, 0.0, 1.0}), it loses its form and creates a skinny rectangle in the top left like this:
When I try to draw them both at the same time, I get a black screen.
How can I draw that goal image?
full code:
#include <stdlib.h>
#include <GL/glew.h>
#include <GL/freeglut.h>
#define BUFFER_OFFSET(offset) ((GLvoid *) offset)
GLuint buffer = 0;
GLuint vPos;
GLuint program;
void init()
{
// Three vertexes that define a triangle.
GLfloat vertices[][ 4 ] =
{
{-0.75, -0.5, 0.0, 1.0},
{0.75, -0.5, 0.0, 1.0},
{0.0, 0.75, 0.0, 1.0}
};
glGenBuffers( 1, &buffer );
glBindBuffer( GL_ARRAY_BUFFER, buffer );
glBufferData( GL_ARRAY_BUFFER, sizeof( vertices ), vertices, GL_STATIC_DRAW );
// OpenGL vertex shader source code
const char* vSource =
{
"#version 330\n"
"in vec4 vPos;"
"void main() {"
" gl_Position = vPos * vec4(1.0f, 1.0f, 1.0f, 1.0f);"
"}"
};
// OpenGL fragment shader source code
const char* fSource =
{
"#version 330\n"
"out vec4 fragColor;"
"void main() {"
" fragColor = vec4(0.8, 0.8, 0, 1);"
"}"
};
// Declare shader IDs
GLuint vShader, fShader;
// Create empty shader objects
vShader = glCreateShader( GL_VERTEX_SHADER );
fShader = glCreateShader( GL_FRAGMENT_SHADER );
glShaderSource( vShader, 1, &vSource, NULL );
glShaderSource( fShader, 1, &fSource, NULL );
glCompileShader( vShader );
glCompileShader( fShader );
// Create an empty shader program object
program = glCreateProgram();
// Attach vertex and fragment shaders to the shader program
glAttachShader( program, vShader );
glAttachShader( program, fShader );
// Link the shader program
glLinkProgram( program );
vPos = glGetAttribLocation( program, "vPos" );
// Specify the background color
glClearColor( 0, 0, 0, 1 );
}
void reshape( int width, int height )
{
// Specify the width and height of the picture within the window
glViewport( 0, 0, width, height );
}
void display()
{
// Clear the window with the background color
glClear( GL_COLOR_BUFFER_BIT );
// Activate the shader program
glUseProgram( program );
glBindBuffer( GL_ARRAY_BUFFER, buffer );
glVertexAttribPointer( vPos, 4, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET( 0 ) );
glEnableVertexAttribArray( vPos );
// Start the shader program
glDrawArrays( GL_TRIANGLES, 0, 3 );
// Refresh the window
glutSwapBuffers();
}
void main( int argc, char *argv[] )
{
glutInit( &argc, argv );
glutInitDisplayMode( GLUT_RGBA | GLUT_DOUBLE );
glutCreateWindow( argv[ 0 ] );
glewInit();
init();
glutDisplayFunc( display );
glutReshapeFunc( reshape );
glutMainLoop();
}

OpenGL - C++ VS 2013 nothing displayed, only black window

This is exercises for my course in computer graphics, but I'm not asking for solutions, just for a way to be able to actually work on the exercises since right now I can't because all the output is producing is black window - I know what it's supposed to produce since I worked on it on school computers and am trying to work on it from home now.
The code works fine on school computers, and I've asked the TAs for help, but they've been unsuccesful so far in locating my problem.
The school computers run on VS 2010 windows 7, while I only have VS 2013 windows 8.1 available. When I opened the project the first time it asked me to convert it to VS2013 etc. and I did so.
I am able to run some other exercises just fine, but I have a problem with all exercises above 2.1.
The code below is from exercise 2.2
// 02561-02-02
#include <iostream>
#include <string>
#include <GL/glew.h>
#include <GL/freeglut.h>
#include "Angel.h"
using namespace std;
using namespace Angel;
int WINDOW_WIDTH = 500;
int WINDOW_HEIGHT = 500;
GLuint shaderProgram;
GLuint projectionUniform,
modelViewUniform,
colorUniform;
GLuint positionAttribute;
GLuint unitCubeVertexArrayObject,
axisVertexArrayObject,
vertexBuffer;
const int axisSize = 6;
struct Vertex {
vec4 position;
};
void loadShader();
void display();
GLuint loadBufferData(Vertex* vertices, int vertexCount);
void buildUnitCube() {
const int cubeSize = 8;
Vertex cubeData[cubeSize] = {
{ vec4( 1.0, 1.0, 1.0, 1.0 ) },
{ vec4( 1.0, 0.0, 1.0, 1.0 ) },
{ vec4( 1.0, 1.0, 0.0, 1.0 ) },
{ vec4( 1.0, 0.0, 0.0, 1.0 ) },
{ vec4(-0.0, 1.0, 0.0, 1.0 ) },
{ vec4(-0.0, 0.0, 0.0, 1.0 ) },
{ vec4(-0.0, 1.0, 1.0, 1.0 ) },
{ vec4(-0.0, 0.0, 1.0, 1.0 ) }
};
unitCubeVertexArrayObject = loadBufferData(cubeData, cubeSize);
}
void buildAxis() {
Vertex axisData[axisSize] = {
{vec4(0., 0., 0., 1.0)}, // v0
{vec4(4., 0., 0., 1.0)}, // vx
{vec4(0., 4., 0., 1.0)}, // vy
{vec4(0., 0., 4., 1.0)}, // vz
{vec4(1., 0., 0., 1.0)}, // v0x1
{vec4(1., 3., 0., 1.0)} // vyx1
};
axisVertexArrayObject = loadBufferData(axisData, axisSize);
}
GLuint loadBufferData(Vertex* vertices, int vertexCount) {
GLuint vertexArrayObject;
glGenVertexArrays(1, &vertexArrayObject);
glBindVertexArray(vertexArrayObject);
GLuint vertexBuffer;
glGenBuffers(1, &vertexBuffer);
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
glBufferData(GL_ARRAY_BUFFER, vertexCount * sizeof(Vertex), vertices, GL_STATIC_DRAW);
glEnableVertexAttribArray(positionAttribute);
glVertexAttribPointer(positionAttribute, 4, GL_FLOAT, GL_FALSE, sizeof(Vertex), (const GLvoid *)0);
return vertexArrayObject;
}
void loadShader(){
shaderProgram = InitShader("const-shader.vert", "const-shader.frag", "fragColor");
projectionUniform = glGetUniformLocation(shaderProgram, "projection");
if (projectionUniform == GL_INVALID_INDEX) {
cerr << "Shader did not contain the 'projection' uniform."<<endl;
}
modelViewUniform = glGetUniformLocation(shaderProgram, "modelView");
if (modelViewUniform == GL_INVALID_INDEX) {
cerr << "Shader did not contain the 'modelView' uniform."<<endl;
}
colorUniform = glGetUniformLocation(shaderProgram, "color");
if (colorUniform == GL_INVALID_INDEX) {
cerr << "Shader did not contain the 'color' uniform."<<endl;
}
positionAttribute = glGetAttribLocation(shaderProgram, "position");
if (positionAttribute == GL_INVALID_INDEX) {
cerr << "Shader did not contain the 'position' attribute." << endl;
}
}
void drawWireUnitCube() {
GLuint indices[24] = {
0,1,
1,3,
3,2,
2,0,
4,5,
5,7,
7,6,
6,4,
7,1,
6,0,
4,2,
5,3
};
glBindVertexArray(unitCubeVertexArrayObject);
glDrawElements(GL_LINES, 24, GL_UNSIGNED_INT, indices);
}
void drawAxis() {
GLuint indices[8] = {
0,1,
0,2,
0,3,
4,5
};
glBindVertexArray(axisVertexArrayObject);
glDrawElements(GL_LINES, 8, GL_UNSIGNED_INT, indices);
}
void display() {
glClearColor(0.0, 0.0, 0.0, 1.0);
glClear(GL_COLOR_BUFFER_BIT);
glUseProgram(shaderProgram);
mat4 projection = Ortho(-6., 6., -6., 6., -6., 10.);
glUniformMatrix4fv(projectionUniform, 1, GL_TRUE, projection);
mat4 modelView(1.0f);
vec4 red(1.0, 0.0, 0.0, 1.0);
glUniform4fv(colorUniform, 1, red);
glUniformMatrix4fv(modelViewUniform, 1, GL_TRUE, modelView);
drawAxis();
// todo multiply model transformations
vec4 white(1.0, 1.0, 1.0, 1.0);
glUniform4fv(colorUniform, 1, white);
glUniformMatrix4fv(modelViewUniform, 1, GL_TRUE, modelView);
drawWireUnitCube();
glutSwapBuffers();
Angel::CheckError();
}
void reshape(int W, int H) {
WINDOW_WIDTH = W;
WINDOW_HEIGHT = H;
glViewport(0, 0, WINDOW_WIDTH, WINDOW_HEIGHT);
}
int main(int argc, char* argv[]) {
glutInit(&argc, argv);
glutInitContextVersion(3, 2);
glutInitContextFlags(GLUT_FORWARD_COMPATIBLE);
glutInitContextProfile(GLUT_CORE_PROFILE);
glutSetOption(
GLUT_ACTION_ON_WINDOW_CLOSE,
GLUT_ACTION_GLUTMAINLOOP_RETURNS
);
glutInitDisplayMode(GLUT_RGBA|GLUT_DOUBLE|GLUT_3_2_CORE_PROFILE);
glutCreateWindow("02561-02-02");
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutReshapeWindow(WINDOW_WIDTH, WINDOW_HEIGHT);
Angel::InitOpenGL();
loadShader();
buildUnitCube();
buildAxis();
Angel::CheckError();
glutMainLoop();
}
Your code requests a Core Profile context:
glutInitContextFlags(GLUT_FORWARD_COMPATIBLE);
glutInitContextProfile(GLUT_CORE_PROFILE);
but it's not completely compatible with the Core Profile. In the Core Profile, all vertex data needs to be sourced from buffers. Passing client side arrays for vertex data is not supported anymore. This includes index data. So the following is not allowed:
GLuint indices[8] = {
0,1,
0,2,
0,3,
4,5
};
glBindVertexArray(axisVertexArrayObject);
glDrawElements(GL_LINES, 8, GL_UNSIGNED_INT, indices);
You need to store the indices in a GL_ELEMENT_ARRAY_BUFFER. Extend the signature of loadBufferData() function to also take index data, and add code to also create an index buffer:
GLuint loadBufferData(Vertex* vertices, int vertexCount
GLuint* indices, int indexCount) {
...
GLuint indexBuffer;
glGenBuffers(1, &indexBuffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indexCount * sizeof(GLuint), indices, GL_STATIC_DRAW);
return vertexArrayObject;
}
Then the draw functions look like this:
glBindVertexArray(axisVertexArrayObject);
glDrawElements(GL_LINES, 8, GL_UNSIGNED_INT, 0);

Segmentation fault at glGenVertexArrays( 1, &vao );

My gdb backtrace gives:
(gdb) backtrace
#0 0x00000000 in ?? ()
#1 0x0804a211 in init () at example1.cpp:147
#2 0x0804a6bc in main (argc=1, argv=0xbffff3d4) at example1.cpp:283
Not very informative. Eclipse debugger at least lets me see that it stops on line 3 below:
// Create a vertex array object
GLuint vao;
glGenVertexArrays( 1, &vao );
glBindVertexArray( vao );
This is a very common block to see in gl programming, and I'm even running other code with the same block with no problem. So I'm baffled.
Build output from running make:
g++ -g -DFREEGLUT_STATIC -DGLEW_STATIC -I../../include example1.cpp ../../Commo/InitShader.o -L/usr/lib/mesa -lGLEW -lglut -lGL -lX11 -lm -o example1
Program containing the problem:
// rotating cube with two texture objects
// change textures with 1 and 2 keys
#include "Angel.h"
const int NumTriangles = 12; // (6 faces)(2 triangles/face)
const int NumVertices = 3 * NumTriangles;
const int TextureSize = 64;
typedef Angel::vec4 point4;
typedef Angel::vec4 color4;
// Texture objects and storage for texture image
GLuint textures[2];
GLubyte image[TextureSize][TextureSize][3];
GLubyte image2[TextureSize][TextureSize][3];
// Vertex data arrays
point4 points[NumVertices];
color4 quad_colors[NumVertices];
vec2 tex_coords[NumVertices];
// Array of rotation angles (in degrees) for each coordinate axis
enum { Xaxis = 0, Yaxis = 1, Zaxis = 2, NumAxes = 3 };
int Axis = Xaxis;
GLfloat Theta[NumAxes] = { 0.0, 0.0, 0.0 };
GLuint theta;
//----------------------------------------------------------------------------
int Index = 0;
void quad( int a, int b, int c, int d )
{
point4 vertices[8] = {
point4( -0.5, -0.5, 0.5, 1.0 ),
point4( -0.5, 0.5, 0.5, 1.0 ),
point4( 0.5, 0.5, 0.5, 1.0 ),
point4( 0.5, -0.5, 0.5, 1.0 ),
point4( -0.5, -0.5, -0.5, 1.0 ),
point4( -0.5, 0.5, -0.5, 1.0 ),
point4( 0.5, 0.5, -0.5, 1.0 ),
point4( 0.5, -0.5, -0.5, 1.0 )
};
color4 colors[8] = {
color4( 0.0, 0.0, 0.0, 1.0 ), // black
color4( 1.0, 0.0, 0.0, 1.0 ), // red
color4( 1.0, 1.0, 0.0, 1.0 ), // yellow
color4( 0.0, 1.0, 0.0, 1.0 ), // green
color4( 0.0, 0.0, 1.0, 1.0 ), // blue
color4( 1.0, 0.0, 1.0, 1.0 ), // magenta
color4( 0.0, 1.0, 1.0, 1.0 ), // white
color4( 1.0, 1.0, 1.0, 1.0 ) // cyan
};
quad_colors[Index] = colors[a];
points[Index] = vertices[a];
tex_coords[Index] = vec2( 0.0, 0.0 );
Index++;
quad_colors[Index] = colors[a];
points[Index] = vertices[b];
tex_coords[Index] = vec2( 0.0, 1.0 );
Index++;
quad_colors[Index] = colors[a];
points[Index] = vertices[c];
tex_coords[Index] = vec2( 1.0, 1.0 );
Index++;
quad_colors[Index] = colors[a];
points[Index] = vertices[a];
tex_coords[Index] = vec2( 0.0, 0.0 );
Index++;
quad_colors[Index] = colors[a];
points[Index] = vertices[c];
tex_coords[Index] = vec2( 1.0, 1.0 );
Index++;
quad_colors[Index] = colors[a];
points[Index] = vertices[d];
tex_coords[Index] = vec2( 1.0, 0.0 );
Index++;
}
//----------------------------------------------------------------------------
void colorcube()
{
quad( 1, 0, 3, 2 );
quad( 2, 3, 7, 6 );
quad( 3, 0, 4, 7 );
quad( 6, 5, 1, 2 );
quad( 4, 5, 6, 7 );
quad( 5, 4, 0, 1 );
}
//----------------------------------------------------------------------------
void init()
{
colorcube();
// Create a checkerboard pattern
for ( int i = 0; i < 64; i++ ) {
for ( int j = 0; j < 64; j++ ) {
GLubyte c = (((i & 0x8) == 0) ^ ((j & 0x8) == 0)) * 255;
image[i][j][0] = c;
image[i][j][1] = c;
image[i][j][2] = c;
image2[i][j][0] = c;
image2[i][j][1] = 0;
image2[i][j][2] = c;
}
}
// Initialize texture objects
glGenTextures( 2, textures );
glBindTexture( GL_TEXTURE_2D, textures[0] );
glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, TextureSize, TextureSize, 0,
GL_RGB, GL_UNSIGNED_BYTE, image );
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
glBindTexture( GL_TEXTURE_2D, textures[1] );
glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, TextureSize, TextureSize, 0,
GL_RGB, GL_UNSIGNED_BYTE, image2 );
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
glActiveTexture( GL_TEXTURE0 );
glBindTexture( GL_TEXTURE_2D, textures[0] );
// Create a vertex array object
GLuint vao;
glGenVertexArrays( 1, &vao );
glBindVertexArray( vao );
// Create and initialize a buffer object
GLuint buffer;
glGenBuffers( 1, &buffer );
glBindBuffer( GL_ARRAY_BUFFER, buffer );
glBufferData( GL_ARRAY_BUFFER,
sizeof(points) + sizeof(quad_colors) + sizeof(tex_coords),
NULL, GL_STATIC_DRAW );
// Specify an offset to keep track of where we're placing data in our
// vertex array buffer. We'll use the same technique when we
// associate the offsets with vertex attribute pointers.
GLintptr offset = 0;
glBufferSubData( GL_ARRAY_BUFFER, offset, sizeof(points), points );
offset += sizeof(points);
glBufferSubData( GL_ARRAY_BUFFER, offset,
sizeof(quad_colors), quad_colors );
offset += sizeof(quad_colors);
glBufferSubData( GL_ARRAY_BUFFER, offset, sizeof(tex_coords), tex_coords );
// Load shaders and use the resulting shader program
GLuint program = InitShader( "vshader71.glsl", "fshader71.glsl" );
glUseProgram( program );
// set up vertex arrays
offset = 0;
GLuint vPosition = glGetAttribLocation( program, "vPosition" );
glEnableVertexAttribArray( vPosition );
glVertexAttribPointer( vPosition, 4, GL_FLOAT, GL_FALSE, 0,
BUFFER_OFFSET(offset) );
offset += sizeof(points);
GLuint vColor = glGetAttribLocation( program, "vColor" );
glEnableVertexAttribArray( vColor );
glVertexAttribPointer( vColor, 4, GL_FLOAT, GL_FALSE, 0,
BUFFER_OFFSET(offset) );
offset += sizeof(quad_colors);
GLuint vTexCoord = glGetAttribLocation( program, "vTexCoord" );
glEnableVertexAttribArray( vTexCoord );
glVertexAttribPointer( vTexCoord, 2, GL_FLOAT, GL_FALSE, 0,
BUFFER_OFFSET(offset) );
// Set the value of the fragment shader texture sampler variable
// ("texture") to the the appropriate texture unit. In this case,
// zero, for GL_TEXTURE0 which was previously set by calling
// glActiveTexture().
glUniform1i( glGetUniformLocation(program, "texture"), 0 );
theta = glGetUniformLocation( program, "theta" );
glEnable( GL_DEPTH_TEST );
glClearColor( 1.0, 1.0, 1.0, 1.0 );
}
void display( void )
{
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
glUniform3fv( theta, 1, Theta );
glDrawArrays( GL_TRIANGLES, 0, NumVertices );
glutSwapBuffers();
}
//----------------------------------------------------------------------------
void mouse( int button, int state, int x, int y )
{
if ( state == GLUT_DOWN ) {
switch( button ) {
case GLUT_LEFT_BUTTON: Axis = Xaxis; break;
case GLUT_MIDDLE_BUTTON: Axis = Yaxis; break;
case GLUT_RIGHT_BUTTON: Axis = Zaxis; break;
}
}
}
//----------------------------------------------------------------------------
void idle( void )
{
Theta[Axis] += 0.01;
if ( Theta[Axis] > 360.0 ) {
Theta[Axis] -= 360.0;
}
glutPostRedisplay();
}
//----------------------------------------------------------------------------
void keyboard( unsigned char key, int mousex, int mousey )
{
switch( key ) {
case 033: // Escape Key
case 'q': case 'Q':
exit( EXIT_SUCCESS );
break;
case '1':
glBindTexture( GL_TEXTURE_2D, textures[0] );
break;
case '2':
glBindTexture( GL_TEXTURE_2D, textures[1] );
break;
}
glutPostRedisplay();
}
//----------------------------------------------------------------------------
int main( int argc, char **argv )
{
glutInit( &argc, argv );
glutInitDisplayMode( GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH );
glutInitWindowSize( 512, 512 );
glutInitContextVersion( 3, 2 );
glutInitContextProfile( GLUT_CORE_PROFILE );
glutCreateWindow( "Color Cube" );
glewInit();
init();
glutDisplayFunc( display );
glutKeyboardFunc( keyboard );
glutMouseFunc( mouse );
glutIdleFunc( idle );
glutMainLoop();
return 0;
}
glewExperimental = GL_TRUE;
glewInit();
Should do the magic
Experimental Drivers
GLEW obtains information on the supported extensions from the graphics
driver. Experimental or pre-release drivers, however, might not report
every available extension through the standard mechanism, in which
case GLEW will report it unsupported. To circumvent this situation,
the glewExperimental global switch can be turned on by setting it to
GL_TRUE before calling glewInit(), which ensures that all extensions
with valid entry points will be exposed.
Works fine for me:
GL_VERSION : 4.1.10750 Compatibility Profile Context
GL_VENDOR : ATI Technologies Inc.
GL_RENDERER : AMD Radeon HD 6500 Series
EDIT: I'm using the latest versions of FreeGLUT (2.8.0 RC2) and GLEW (1.7.0), which may make a difference if you're relying on distro-supplied versions.
Have you tried testing on other systems with different graphics cards? If your code meets the OpenGL spec and it mysteriously crashes inside a function that is correctly called with valid parameters, it could well be a driver bug. If it's a driver bug, you're reduced to guesswork, making shotgun changes, and gradually building up a healthy exasperation that a huge corporation with billions of dollars produce absolutely crap excuses for a graphics card driver. Good luck!
Ubuntu 10.04 for example comes with glew 1.50 which glGenVertexArrays doesn't work without the glewExperimental flag.
so it is glew version dependent