I'm trying to do a Sierpinski gasket as specified in "INTERACTIVE COMPUTER GRAPHICS A TOP-DOWN APPROACH WITH SHADER-BASED OPENGL®" 6th edition.
I have this code
Sierpinski.cpp
#include <GL/glew.h>
#include <GL/glut.h>
#include <glm/glm.hpp>
#include "Angel.h"
#include <iostream>
#include <vector>
#include <cmath>
#define NUM_PUNTOS 4
#define DIVISIONES 5
namespace Global
{
GLint Ndivisions = DIVISIONES;
GLint Nvertices = (GLint) std::pow(3,Ndivisions + 1);
std::vector<glm::vec2> points;
};
void display(void);
void init();
//void idle(void);
void triangle(glm::vec2,glm::vec2,glm::vec2,std::vector<glm::vec2> &);
void divide_triangle(glm::vec2,glm::vec2,glm::vec2,GLint,std::vector<glm::vec2> &);
inline glm::vec2 dividir(glm::vec2,double);
glm::vec2 dividir(glm::vec2,double);
int main(int argc, char **argv)
{
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_RGBA);
glutInitWindowSize(800,600);
glutInitContextVersion(3,2);
glutInitContextProfile(GLUT_CORE_PROFILE);
//IMPORTANTE: CREAR ANTES QUE LOS CALLBACKS
glutCreateWindow("Sierpinski gasket"); //Init
glewInit();//IMPORTANTÍSIMO
init();
glutDisplayFunc(display);
#ifdef LIBGL_DEBUG
std::cout<<LIBGL_DEBUG<<'\n';
#endif
//Despues de todo es que se crea la ventana
glutMainLoop();
}
void display(void)
{
glClear(GL_COLOR_BUFFER_BIT);
glDrawArrays(GL_POINTS, 0, Global::Nvertices);
glFlush();
}
void init()
{
//Inicializamos array global
divide_triangle(glm::vec2(0.0,0.0),glm::vec2(1.0,0.0),glm::vec2(0.5,1.0),Global::Ndivisions,Global::points);
glm::vec2 *points = &Global::points[0];
GLuint vao,program;
program = Angel::InitShader("shaders/Sierpinski.vertex.glsl",
"shaders/Sierpinski.fragment.glsl");
glUseProgram(program);
for(int x = 0; x<Global::points.size();x++)
std::cout<<"X: "<<points[x].x<<" Y: "<<points[x].y<<"\n";
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
//Buffers
GLuint buffer;
glGenBuffers(1, &buffer);
std::cout<<"Primer test\n";
glBindBuffer(GL_ARRAY_BUFFER, buffer);
glBufferData(GL_ARRAY_BUFFER,sizeof(points),
points,GL_STATIC_DRAW);
//glGenVertexArrays(1, &buffer);
//glBindVertexArray(buffer);
std::cout<<buffer<<'\n';
// Initialize the vertex position attribute from the vertex shader
GLuint loc = glGetAttribLocation( program, "vPosition" );
glEnableVertexAttribArray( loc );
glVertexAttribPointer( loc, 2, GL_FLOAT, GL_FALSE, 0,
BUFFER_OFFSET(0) );
}
void triangle(glm::vec2 a,glm::vec2 b,glm::vec2 c,std::vector<glm::vec2> &points)
{
size_t old_size = points.size();
points.resize(old_size + 3);
points[old_size] = a;
points[old_size + 1] = b;
points[old_size + 2] = c;
//std::cout<<"Finalizado\n";
}
void divide_triangle(glm::vec2 a,glm::vec2 b,glm::vec2 c,GLint k,std::vector<glm::vec2> &points)
{
if(k>0)
{
glm::vec2 ab = dividir(a + b,2.0);
glm::vec2 ac = dividir(a + c,2.0);
glm::vec2 bc = dividir(b + c,2.0);
//Dividimos triángulo
int new_k = k - 1;
divide_triangle(a,ab,ac,new_k,points);
divide_triangle(c,ac,bc,new_k,points);
divide_triangle(b,bc,ab,new_k,points);
}
else
{
triangle(a,b,c,points);
}
}
glm::vec2 dividir(glm::vec2 vectorcito,double escalar)
{
return glm::vec2(vectorcito.x/escalar,vectorcito.y/escalar);
}
//void idle(void){}
Angel.h
//////////////////////////////////////////////////////////////////////////////
//
// --- Angel.h ---
//
// The main header file for all examples from Angel 6th Edition
//
//////////////////////////////////////////////////////////////////////////////
#ifndef __ANGEL_H__
#define __ANGEL_H__
//----------------------------------------------------------------------------
//
// --- Include system headers ---
//
#include <cmath>
#include <iostream>
// Define M_PI in the case it's not defined in the math header file
#ifndef M_PI
# define M_PI 3.14159265358979323846
#endif
//----------------------------------------------------------------------------
//
// --- Include OpenGL header files and helpers ---
//
// The location of these files vary by operating system. We've included
// copies of open-soruce project headers in the "GL" directory local
// this this "include" directory.
//
#ifdef __APPLE__ // include Mac OS X verions of headers
# include <OpenGL/OpenGL.h>
# include <GLUT/glut.h>
#else // non-Mac OS X operating systems
# include <GL/glew.h>
# include <GL/freeglut.h>
# include <GL/freeglut_ext.h>
#endif // __APPLE__
// Define a helpful macro for handling offsets into buffer objects
#define BUFFER_OFFSET( offset ) ((GLvoid*) (offset))
//----------------------------------------------------------------------------
//
// --- Include our class libraries and constants ---
//
namespace Angel {
// Helper function to load vertex and fragment shader files
GLuint InitShader( const char* vertexShaderFile,
const char* fragmentShaderFile );
// Defined constant for when numbers are too small to be used in the
// denominator of a division operation. This is only used if the
// DEBUG macro is defined.
const GLfloat DivideByZeroTolerance = GLfloat(1.0e-07);
// Degrees-to-radians constant
const GLfloat DegreesToRadians = M_PI / 180.0;
} // namespace Angel
/*#include "vec.h"
#include "mat.h"
#include "CheckError.h"*/
#define Print(x) do { std::cerr << #x " = " << (x) << std::endl; } while(0)
// Globally use our namespace in our example programs.
//using namespace Angel;
namespace Angel {
// Create a NULL-terminated string by reading the provided file
static char*
readShaderSource(const char* shaderFile)
{
FILE* fp = fopen(shaderFile, "r");
if ( fp == NULL ) { return NULL; }
fseek(fp, 0L, SEEK_END);
long size = ftell(fp);
fseek(fp, 0L, SEEK_SET);
char* buf = new char[size + 1];
fread(buf, 1, size, fp);
buf[size] = '\0';
fclose(fp);
return buf;
}
// Create a GLSL program object from vertex and fragment shader files
GLuint
InitShader(const char* vShaderFile, const char* fShaderFile)
{
struct Shader {
const char* filename;
GLenum type;
GLchar* source;
} shaders[2] = {
{ vShaderFile, GL_VERTEX_SHADER, NULL },
{ fShaderFile, GL_FRAGMENT_SHADER, NULL }
};
GLuint program = glCreateProgram();
for ( int i = 0; i < 2; ++i ) {
Shader& s = shaders[i];
s.source = readShaderSource( s.filename );
if ( shaders[i].source == NULL ) {
std::cerr << "Failed to read " << s.filename << std::endl;
exit( EXIT_FAILURE );
}
GLuint shader = glCreateShader( s.type );
glShaderSource( shader, 1, (const GLchar**) &s.source, NULL );
glCompileShader( shader );
GLint compiled;
glGetShaderiv( shader, GL_COMPILE_STATUS, &compiled );
if ( !compiled ) {
std::cerr << s.filename << " failed to compile:" << std::endl;
GLint logSize;
glGetShaderiv( shader, GL_INFO_LOG_LENGTH, &logSize );
char* logMsg = new char[logSize];
glGetShaderInfoLog( shader, logSize, NULL, logMsg );
std::cerr << logMsg << std::endl;
delete [] logMsg;
exit( EXIT_FAILURE );
}
delete [] s.source;
glAttachShader( program, shader );
}
/* link and error check */
glLinkProgram(program);
GLint linked;
glGetProgramiv( program, GL_LINK_STATUS, &linked );
if ( !linked ) {
std::cerr << "Shader program failed to link" << std::endl;
GLint logSize;
glGetProgramiv( program, GL_INFO_LOG_LENGTH, &logSize);
char* logMsg = new char[logSize];
glGetProgramInfoLog( program, logSize, NULL, logMsg );
std::cerr << logMsg << std::endl;
delete [] logMsg;
exit( EXIT_FAILURE );
}
/* use program object */
glUseProgram(program);
return program;
}
} // Close namespace Angel block
#endif // __ANGEL_H__
I compile it using the following commands
g++ Sierpinski.cpp -I. -lGL -lglut -lGLU -lGLEW -g -o Sierpinski.out
When I run it, the follows appears:
[asdrubal@localhost tests]$ ./Sierpinski.out
libGL error: failed to load driver: i965
libGL error: Try again with LIBGL_DEBUG=verbose for more details.
libGL error: failed to load driver: swrast
libGL error: Try again with LIBGL_DEBUG=verbose for more details.
X Error of failed request: GLXBadFBConfig
Major opcode of failed request: 154 (GLX)
Minor opcode of failed request: 34 ()
Serial number of failed request: 39
Current serial number in output stream: 38
Any suggestions?
P.S.: I'm using right now
3.6.9-1-ARCH (Arch Linux)
EDIT 1:
Shaders
Sierpinski.fragment.glsl
void main()
{
gl_FragColor = vec4(0.0,1.0,0.0,1.0);
}
Sierpinski.vertex.glsl
#version 120
attribute vec4 vPosition; /*Si se quieren setear variables*/
void main()
{
gl_Position = vPosition;
}
Output with LIBGL_DEBUG=verbose
[asdrubal@localhost tests]$ ./Sierpinski.out
libGL: OpenDriver: trying /usr/lib32/dri/tls/i965_dri.so
libGL: OpenDriver: trying /usr/lib32/dri/i965_dri.so
libGL error: dlopen /usr/lib32/dri/i965_dri.so failed (/usr/lib32/dri/i965_dri.so: cannot open shared object file: No such file or directory)
libGL error: unable to load driver: i965_dri.so
libGL error: driver pointer missing
libGL error: failed to load driver: i965
libGL: OpenDriver: trying /usr/lib32/dri/tls/swrast_dri.so
libGL: OpenDriver: trying /usr/lib32/dri/swrast_dri.so
libGL error: dlopen /usr/lib32/dri/swrast_dri.so failed (/usr/lib32/dri/swrast_dri.so: cannot open shared object file: No such file or directory)
libGL error: unable to load driver: swrast_dri.so
libGL error: failed to load driver: swrast
X Error of failed request: GLXBadFBConfig
Major opcode of failed request: 154 (GLX)
Minor opcode of failed request: 34 ()
Serial number of failed request: 39
Current serial number in output stream: 38
EDIT 2:
Command:
lspci | grep VGA
Returns
00:02.0 VGA compatible controller: Intel Corporation Mobile GM965/GL960 Integrated Graphics Controller (primary) (rev 03)
Intel Corporation Mobile GM965/GL960
You're running fourth-gen Intel silicon so:
glutInitContextVersion(3,2);
is rather...optimistic.
Unless you want software rendering, in which case you'll have to wait a while for Mesa to get up to OpenGL 3.2.
EDIT: Give this a try:
#include <GL/glew.h>
#include <GL/glut.h>
#include <glm/glm.hpp>
#include <iostream>
#include <vector>
#include <cmath>
#include <stdexcept>
using namespace std;
// vertex shader
const GLchar* vert =
"#version 120\n"
"attribute vec2 position;"
"void main()"
"{"
" gl_Position = vec4( position, 0.0, 1.0 );"
"}"
;
// fragment shader
const GLchar* frag =
"#version 120\n"
"void main()"
"{"
" gl_FragColor = vec4( 0.0, 1.0, 0.0, 1.0 );"
"}"
;
const unsigned int NUM_PUNTOS = 4;
const unsigned int DIVISIONES = 5;
namespace Global
{
GLint Ndivisions = DIVISIONES;
GLint Nvertices = (GLint) std::pow(3.0,Ndivisions + 1);
std::vector<glm::vec2> points;
};
void triangle( glm::vec2 a, glm::vec2 b, glm::vec2 c, std::vector<glm::vec2> &points )
{
size_t old_size = points.size();
points.resize(old_size + 3);
points[old_size] = a;
points[old_size + 1] = b;
points[old_size + 2] = c;
}
glm::vec2 dividir( glm::vec2 vectorcito, double escalar )
{
return glm::vec2(vectorcito.x/escalar,vectorcito.y/escalar);
}
void divide_triangle( glm::vec2 a, glm::vec2 b, glm::vec2 c, GLint k, std::vector<glm::vec2> &points )
{
if(k>0)
{
glm::vec2 ab = dividir(a + b,2.0);
glm::vec2 ac = dividir(a + c,2.0);
glm::vec2 bc = dividir(b + c,2.0);
//Dividimos triángulo
int new_k = k - 1;
divide_triangle(a,ab,ac,new_k,points);
divide_triangle(c,ac,bc,new_k,points);
divide_triangle(b,bc,ab,new_k,points);
}
else
{
triangle(a,b,c,points);
}
}
void CheckStatus( const GLenum id )
{
GLint status = GL_FALSE, loglen = 10;
if( glIsShader(id) ) glGetShaderiv( id, GL_COMPILE_STATUS, &status );
if( glIsProgram(id) ) glGetProgramiv( id, GL_LINK_STATUS, &status );
if( GL_TRUE == status ) return;
if( glIsShader(id) ) glGetShaderiv( id, GL_INFO_LOG_LENGTH , &loglen);
if( glIsProgram(id) ) glGetProgramiv( id, GL_INFO_LOG_LENGTH , &loglen);
vector< char > log( loglen, 'E' );
if( glIsShader(id) ) glGetShaderInfoLog( id, loglen, NULL, &log[0] );
if( glIsProgram(id) ) glGetProgramInfoLog( id, loglen, NULL, &log[0] );
throw logic_error( string( log.begin(), log.end() ) );
}
GLuint CreateShader( const GLenum aType, const string& aSource )
{
GLuint shader = glCreateShader( aType );
const GLchar* shaderString = aSource.c_str();
glShaderSource( shader, 1, &shaderString, NULL );
glCompileShader( shader );
CheckStatus( shader );
return shader;
}
GLuint CreateProgram( const string& aVertexShader, const string& aFragmentShader )
{
GLuint vert = CreateShader( GL_VERTEX_SHADER, aVertexShader );
GLuint frag = CreateShader( GL_FRAGMENT_SHADER, aFragmentShader );
GLuint program = glCreateProgram();
glAttachShader( program, vert );
glAttachShader( program, frag );
glLinkProgram( program );
glDeleteShader( vert );
glDeleteShader( frag );
CheckStatus( program );
return program;
}
GLuint prog = 0;
GLuint vbo = 0;
void init()
{
GLenum glewError = glewInit();
if( GLEW_OK != glewError )
throw runtime_error( (char*)glewGetErrorString(glewError) );
cout << "GL_VERSION : " << glGetString(GL_VERSION) << endl;
cout << "GL_VENDOR : " << glGetString(GL_VENDOR) << endl;
cout << "GL_RENDERER : " << glGetString(GL_RENDERER) << endl;
cout << "GLEW_VERSION : " << glewGetString(GLEW_VERSION) << endl;
cout << "GLSL VERSION : " << glGetString(GL_SHADING_LANGUAGE_VERSION) << endl;
if( !GLEW_VERSION_2_1 )
throw runtime_error( "OpenGL 2.1 or better required for GLSL support." );
// load shaders
prog = CreateProgram( vert, frag );
//Inicializamos array global
divide_triangle
(
glm::vec2(0.0,0.0),
glm::vec2(1.0,0.0),
glm::vec2(0.5,1.0),
Global::Ndivisions,
Global::points
);
// create/fill VBO
glGenBuffers( 1, &vbo );
glBindBuffer( GL_ARRAY_BUFFER, vbo );
unsigned int numBytes = sizeof( glm::vec2 ) * Global::points.size();
glBufferData( GL_ARRAY_BUFFER, numBytes, &Global::points[0].x, GL_STATIC_DRAW );
}
void display(void)
{
glClear( GL_COLOR_BUFFER_BIT );
glUseProgram( prog );
GLint position_loc = glGetAttribLocation( prog, "position" );
glBindBuffer( GL_ARRAY_BUFFER, vbo );
glVertexAttribPointer( position_loc, 2, GL_FLOAT, GL_FALSE, sizeof( glm::vec2 ), 0 );
glEnableVertexAttribArray( position_loc );
glDrawArrays( GL_POINTS, 0, Global::points.size() );
glDisableVertexAttribArray( position_loc );
glutSwapBuffers();
}
int main(int argc, char **argv)
{
glutInit( &argc, argv );
glutInitWindowSize( 800,600 );
glutInitDisplayMode( GLUT_RGBA | GLUT_DOUBLE );
glutCreateWindow( "Sierpinski gasket" );
init();
glutDisplayFunc( display );
glutMainLoop();
return 0;
}