#include #include #include #include #include //Declare vectors for gcc. typedef float v4f __attribute__ ((vector_size (16))); typedef float rgba __attribute__ ((vector_size (16))); typedef float v2f __attribute__ ((vector_size (8))); //Used by the report function defined below. #define REPORT_TIMESTAMP #define DEBUG #define FAIL 1 #define WARN 2 #define INFO 4 #define PASS 8 #define REPORT_SHOW (FAIL|WARN|INFO|PASS) void report(unsigned char level, const char* format, ...){//A "fancy-smancy printf replacer" for debugging purposes. if(REPORT_SHOW & level){ va_list args; va_start (args, format); #ifdef REPORT_TIMESTAMP fprintf(stderr, "\033[1;37m[%7.4f]",glfwGetTime()); #endif if(level & FAIL)//critical failure fputs("\033[1;31m[FAIL]\033[0m", stderr); else if(level & PASS)//something went right fputs("\033[1;32m[PASS]\033[0m", stderr); else if(level &WARN)//Watch out for this. fputs("\033[0;31m[WARN]\033[0m", stderr); else if(level & INFO) //Information. fputs("\033[1;34m[INFO]\033[0m", stderr); vfprintf(stderr, format, args); fputs("\n",stderr); va_end(args); } } GLuint shaderFromFilename(char *File,GLenum shaderType){ GLenum glError; GLuint shader = glCreateShader(shaderType); glError = glGetError(); if(glError != GL_NO_ERROR){ report(FAIL, "Failed to create shader."); return -1; } FILE * fp; unsigned long fileSize; GLchar* source; fp = fopen(File, "r"); if(fp == NULL){ report(FAIL, "Couldn't open shader file!"); return 0; } fseek(fp, 0, SEEK_END); fileSize = ftell(fp); rewind(fp); //be kind, rewind. source = malloc((fileSize+1)*sizeof(char)); if(source == NULL){ report(FAIL, "Couldn't allocate earth for shader!"); return 0; } if(fread(source,1,fileSize,fp) != fileSize){ report(FAIL, "Couldn't read the opend shader file!"); return 0; } source[fileSize] = '\0'; glShaderSource(shader,1,(const GLchar**)&source,NULL); glCompileShader(shader); return shader; } void reportShaderLog(GLuint shader){ GLsizei logLength; glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &logLength); if(logLength != 1){ GLchar *shaderLog = malloc(logLength); glGetShaderInfoLog(shader,logLength,NULL,shaderLog); report(WARN, "Shader log:\n %s",shaderLog); free(shaderLog); } } GLuint createProgramFromFilenames(char *vertexShader, char *fragmentShader){//simple wrapper for vertex+frag shader program creation. GLenum glError; GLuint vs = shaderFromFilename(vertexShader,GL_VERTEX_SHADER); glError = glGetError(); if(glError != GL_NO_ERROR){ report(FAIL, "Failed everything!" ,vertexShader, fragmentShader,glError); return -1; } GLint isCompiled; glGetShaderiv(vs,GL_COMPILE_STATUS,&isCompiled); isCompiled == GL_TRUE? report(PASS,"Compiled %s", vertexShader) : report(FAIL, "Couldn't compile %s",vertexShader); reportShaderLog(vs); GLuint fs = shaderFromFilename(fragmentShader,GL_FRAGMENT_SHADER); glGetShaderiv(fs,GL_COMPILE_STATUS,&isCompiled); isCompiled == GL_TRUE? report(PASS,"Compiled %s", fragmentShader) : report(FAIL, "Couldn't compile %s",fragmentShader); glError = glGetError(); if(glError != GL_NO_ERROR){ report(FAIL, "Failed to compile everything!" ,vertexShader, fragmentShader,glError); return -1; } reportShaderLog(fs); glError = glGetError(); if(glError != GL_NO_ERROR){ report(FAIL, "what!" ,vertexShader, fragmentShader,glError); return -1; } GLuint shaderProgram = glCreateProgram(); glError = glGetError(); if(glError != GL_NO_ERROR){ report(FAIL, "Couldn't create program!" ,vertexShader, fragmentShader,glError); return -1; } glAttachShader(shaderProgram, fs); glAttachShader(shaderProgram,vs); glError = glGetError(); if(glError != GL_NO_ERROR){ report(FAIL, "Couldn't prepare linking %s and %s, error:" ,vertexShader, fragmentShader,glError); return -1; } glLinkProgram(shaderProgram); glError = glGetError(); if(glError != GL_NO_ERROR){ report(FAIL, "Couldn't link %s and %s, error:" ,vertexShader, fragmentShader,glError); return -1; } report(PASS, "Linked %s and %s", vertexShader, fragmentShader); return shaderProgram; } void GLFWCALL My_Key_Callback(int key, int action){ if(key == GLFW_KEY_SPACE && action == GLFW_PRESS) exit(EXIT_SUCCESS); } int initialize(){ glewExperimental = GL_TRUE; GLenum err; if( glfwInit() != GL_TRUE){ report(FAIL, "Couldn't Initialize GLFW!"); return -1; } //Start by initializing OpenGL, glfwOpenWindowHint(GLFW_OPENGL_VERSION_MAJOR,3); glfwOpenWindowHint(GLFW_OPENGL_VERSION_MINOR,0); //glfwOpenWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); { //Scope block because we don't need this anywhere else and it's to little to warrant a function. int major,minor,rev; glfwGetVersion(&major,&minor,&rev); report(INFO, "Using GLFW version %d.%d, revision %d.", major,minor,rev); } if( glfwOpenWindow( 600,600, 0,0,0,0,0,0, GLFW_WINDOW ) != GL_TRUE){ report(FAIL, "Couldn't create window!"); glfwTerminate(); return -2; } err = glGetError(); if(err != GL_NO_ERROR){ report(FAIL, "Error on opening window!"); } //Initialize GLEW so we can use our extensions. err = glewInit(); if(err !=GLEW_OK){ report(FAIL,"Couldn't initialze GLEW: %s", glewGetErrorString(err)); return -3; } report(INFO, "Using GLEW %s", glewGetString(GLEW_VERSION)); err = glGetError(); if(err != GL_NO_ERROR){ report(WARN, "Glew set GL_ERROR, should be fine though!"); } //glfwSwapInterval(0); //vsync off //Report some information about the window if wanted./* report(INFO,"Using OpenGL Version %d.%d.",glfwGetWindowParam(GLFW_OPENGL_VERSION_MAJOR), glfwGetWindowParam(GLFW_OPENGL_VERSION_MINOR)); report(INFO,"Using (%d,%d,%d)RGB bit-depth.",glfwGetWindowParam(GLFW_RED_BITS),glfwGetWindowParam(GLFW_GREEN_BITS),glfwGetWindowParam(GLFW_BLUE_BITS)); report(INFO,"Hardware acceleration: %s.", glfwGetWindowParam(GLFW_ACCELERATED) == GL_TRUE? "Supported": "Unsupported"); report(INFO,"Refresh Rate: %dHz.", glfwGetWindowParam(GLFW_REFRESH_RATE)); report(PASS, "Intialized."); glfwSetKeyCallback(My_Key_Callback); return 0; } int main(int argc, char **argv) { GLenum glError; if(initialize()) //basic initialisation exit(EXIT_FAILURE); glError = glGetError(); if(glError != GL_NO_ERROR){ report(FAIL, "Failed to init!"); return -1; } //create the shaders GLuint shaderProgram = createProgramFromFilenames("./shaders/pointPath.vert", "./shaders/spritePoint.frag"); glUseProgram (shaderProgram); if(glGetError() != GL_NO_ERROR) report(FAIL, "An error occured while building the shader program!"); else report(PASS, "Succesfully using shaders"); //Create and set first texture. v2f path[] = {{-0.5,0.5},//A path "t -> (x,y)" along which we will place our sprites {-0.5,-0.5}, {0.5,-0.5}, {0.5,0.5}}; glActiveTexture(GL_TEXTURE0); if(glGetError() != GL_NO_ERROR) report(FAIL, "Couldn't activate texture!"); GLuint pathTex; glGenTextures(1, &pathTex); //create a new texture glBindTexture(GL_TEXTURE_1D, pathTex); //start using it as a 1D texture glTexImage1D(GL_TEXTURE_1D,0,GL_RG32F, sizeof(path)/sizeof(v2f),0,GL_RG,GL_FLOAT,path); //store the coordinates of path in the texture so that we can interpolate our path in the shader. glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_BASE_LEVEL, 0);//We need these two lines glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAX_LEVEL, 0);//because we don't have mipmaps. glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);//We want the path to be linearly filtered glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);//Set the min filter just to be safe. if(glGetError() != GL_NO_ERROR) report(FAIL, "Something went wrong setting up pathTex"); GLint uniformLoc = glGetUniformLocation(shaderProgram, "pathTexture"); //locate the uniform uniformLoc >= 0?glUniform1i(uniformLoc, 0):report(FAIL, "found uniform spriteTexture at %d", uniformLoc); //and set it to "0" because we're using GL_TEXTURE0 if(glGetError() != GL_NO_ERROR) report(FAIL, "Couldn't set uniform!"); report(PASS, "Setup texture for path"); //create and set second texture rgba sprite[] = {{1.0,0,0,1},{0,1.0,0,1},{0,0,1.0,1},{1,1,0,1}}; //our sprite, a simple "red,green,blue,yellow" square. glActiveTexture(GL_TEXTURE0+1); //use texUnit 1 now. if(glGetError() != GL_NO_ERROR) report(FAIL, "Couldn't activate texture!"); GLuint spriteTex; glGenTextures(1, &spriteTex); //create a new texture glBindTexture(GL_TEXTURE_2D, spriteTex); //start using it as a 2D texture glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA, 2,2,0,GL_RGBA,GL_FLOAT,sprite); //load the data again. 2x2 sprite. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);//We need these two lines glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);//because we don't have mipmaps. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);//We want our sprites to be filtered to glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);//the nearest pixel, not interpolated. if(glGetError() != GL_NO_ERROR) report(FAIL, "Something went wrong setting up pathTex"); uniformLoc = glGetUniformLocation(shaderProgram, "spriteTexture"); //locates and set the second sampler. uniformLoc >= 0?glUniform1i(uniformLoc, 1):report(FAIL, "found uniform spriteTexture at %d", uniformLoc); if(glGetError() != GL_NO_ERROR) report(FAIL, "Couldn't set uniform!"); report(PASS, "Setup texture for sprite"); //Create our sprite locations #define Npoints 1024 //any number > the number of path points will do. GLfloat points[Npoints]; //the location in "t-space" of our sprites, i.e. the texture coordinate for our path texture. for(size_t i = 0; i < Npoints;i++) points[i] = (float)i/(float)Npoints; //fill it from 0 to 1. report(PASS, "generated points array."); //set-up a our buffers. unsigned int vaSprites; glGenVertexArrays(1,&vaSprites); report(PASS, "Generated vertex array"); unsigned int vbSprites; glGenBuffers(1, &vbSprites); glBindBuffer(GL_ARRAY_BUFFER, vbSprites); glBufferData (GL_ARRAY_BUFFER, sizeof(points), points, GL_STATIC_DRAW); if(glGetError() != GL_NO_ERROR) report(FAIL, "Something went wrong generating the vbSprites!"); glBindVertexArray(vaSprites); GLint inputAttrib = glGetAttribLocation(shaderProgram, "t"); glEnableVertexAttribArray(inputAttrib); glVertexAttribPointer (inputAttrib, 1, GL_FLOAT, GL_FALSE, 0, (GLubyte*)NULL); if(glGetError() != GL_NO_ERROR) report(FAIL, "Something went wrong generating the vaSprites!"); else report(PASS, "Set-up vaSprites."); glEnable(GL_POINT_SPRITE); //We need this (on Nvidia atleast) for obvious reasons. glPointSize(64); while(1){ //our main loop,it's broken by hitting space. glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glDrawArrays(GL_POINTS,0, Npoints); glfwSwapBuffers(); } return 0; } #include #include #include #include #include //Declare vectors for gcc. typedef float v4f __attribute__ ((vector_size (16))); typedef float rgba __attribute__ ((vector_size (16))); typedef float v2f __attribute__ ((vector_size (8))); //Used by the report function defined below. #define REPORT_TIMESTAMP #define DEBUG #define FAIL 1 #define WARN 2 #define INFO 4 #define PASS 8 #define REPORT_SHOW (FAIL|WARN|INFO|PASS) void report(unsigned char level, const char* format, ...){//A "fancy-smancy printf replacer" for debugging purposes. if(REPORT_SHOW & level){ va_list args; va_start (args, format); #ifdef REPORT_TIMESTAMP fprintf(stderr, "\033[1;37m[%7.4f]",glfwGetTime()); #endif if(level & FAIL)//critical failure fputs("\033[1;31m[FAIL]\033[0m", stderr); else if(level & PASS)//something went right fputs("\033[1;32m[PASS]\033[0m", stderr); else if(level &WARN)//Watch out for this. fputs("\033[0;31m[WARN]\033[0m", stderr); else if(level & INFO) //Information. fputs("\033[1;34m[INFO]\033[0m", stderr); vfprintf(stderr, format, args); fputs("\n",stderr); va_end(args); } } GLuint shaderFromFilename(char *File,GLenum shaderType){ GLenum glError; GLuint shader = glCreateShader(shaderType); glError = glGetError(); if(glError != GL_NO_ERROR){ report(FAIL, "Failed to create shader."); return -1; } FILE * fp; unsigned long fileSize; GLchar* source; fp = fopen(File, "r"); if(fp == NULL){ report(FAIL, "Couldn't open shader file!"); return 0; } fseek(fp, 0, SEEK_END); fileSize = ftell(fp); rewind(fp); //be kind, rewind. source = malloc((fileSize+1)*sizeof(char)); if(source == NULL){ report(FAIL, "Couldn't allocate earth for shader!"); return 0; } if(fread(source,1,fileSize,fp) != fileSize){ report(FAIL, "Couldn't read the opend shader file!"); return 0; } source[fileSize] = '\0'; glShaderSource(shader,1,(const GLchar**)&source,NULL); glCompileShader(shader); return shader; } void reportShaderLog(GLuint shader){ GLsizei logLength; glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &logLength); if(logLength != 1){ GLchar *shaderLog = malloc(logLength); glGetShaderInfoLog(shader,logLength,NULL,shaderLog); report(WARN, "Shader log:\n %s",shaderLog); free(shaderLog); } } GLuint createProgramFromFilenames(char *vertexShader, char *fragmentShader){//simple wrapper for vertex+frag shader program creation. GLenum glError; GLuint vs = shaderFromFilename(vertexShader,GL_VERTEX_SHADER); glError = glGetError(); if(glError != GL_NO_ERROR){ report(FAIL, "Failed everything!" ,vertexShader, fragmentShader,glError); return -1; } GLint isCompiled; glGetShaderiv(vs,GL_COMPILE_STATUS,&isCompiled); isCompiled == GL_TRUE? report(PASS,"Compiled %s", vertexShader) : report(FAIL, "Couldn't compile %s",vertexShader); reportShaderLog(vs); GLuint fs = shaderFromFilename(fragmentShader,GL_FRAGMENT_SHADER); glGetShaderiv(fs,GL_COMPILE_STATUS,&isCompiled); isCompiled == GL_TRUE? report(PASS,"Compiled %s", fragmentShader) : report(FAIL, "Couldn't compile %s",fragmentShader); glError = glGetError(); if(glError != GL_NO_ERROR){ report(FAIL, "Failed to compile everything!" ,vertexShader, fragmentShader,glError); return -1; } reportShaderLog(fs); glError = glGetError(); if(glError != GL_NO_ERROR){ report(FAIL, "what!" ,vertexShader, fragmentShader,glError); return -1; } GLuint shaderProgram = glCreateProgram(); glError = glGetError(); if(glError != GL_NO_ERROR){ report(FAIL, "Couldn't create program!" ,vertexShader, fragmentShader,glError); return -1; } glAttachShader(shaderProgram, fs); glAttachShader(shaderProgram,vs); glError = glGetError(); if(glError != GL_NO_ERROR){ report(FAIL, "Couldn't prepare linking %s and %s, error:" ,vertexShader, fragmentShader,glError); return -1; } glLinkProgram(shaderProgram); glError = glGetError(); if(glError != GL_NO_ERROR){ report(FAIL, "Couldn't link %s and %s, error:" ,vertexShader, fragmentShader,glError); return -1; } report(PASS, "Linked %s and %s", vertexShader, fragmentShader); return shaderProgram; } void GLFWCALL My_Key_Callback(int key, int action){ if(key == GLFW_KEY_SPACE && action == GLFW_PRESS) exit(EXIT_SUCCESS); } int initialize(){ glewExperimental = GL_TRUE; GLenum err; if( glfwInit() != GL_TRUE){ report(FAIL, "Couldn't Initialize GLFW!"); return -1; } //Start by initializing OpenGL, glfwOpenWindowHint(GLFW_OPENGL_VERSION_MAJOR,3); glfwOpenWindowHint(GLFW_OPENGL_VERSION_MINOR,0); //glfwOpenWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); { //Scope block because we don't need this anywhere else and it's to little to warrant a function. int major,minor,rev; glfwGetVersion(&major,&minor,&rev); report(INFO, "Using GLFW version %d.%d, revision %d.", major,minor,rev); } if( glfwOpenWindow( 600,600, 0,0,0,0,0,0, GLFW_WINDOW ) != GL_TRUE){ report(FAIL, "Couldn't create window!"); glfwTerminate(); return -2; } err = glGetError(); if(err != GL_NO_ERROR){ report(FAIL, "Error on opening window!"); } //Initialize GLEW so we can use our extensions. err = glewInit(); if(err !=GLEW_OK){ report(FAIL,"Couldn't initialze GLEW: %s", glewGetErrorString(err)); return -3; } report(INFO, "Using GLEW %s", glewGetString(GLEW_VERSION)); err = glGetError(); if(err != GL_NO_ERROR){ report(WARN, "Glew set GL_ERROR, should be fine though!"); } //glfwSwapInterval(0); //vsync off //Report some information about the window if wanted./* report(INFO,"Using OpenGL Version %d.%d.",glfwGetWindowParam(GLFW_OPENGL_VERSION_MAJOR), glfwGetWindowParam(GLFW_OPENGL_VERSION_MINOR)); report(INFO,"Using (%d,%d,%d)RGB bit-depth.",glfwGetWindowParam(GLFW_RED_BITS),glfwGetWindowParam(GLFW_GREEN_BITS),glfwGetWindowParam(GLFW_BLUE_BITS)); report(INFO,"Hardware acceleration: %s.", glfwGetWindowParam(GLFW_ACCELERATED) == GL_TRUE? "Supported": "Unsupported"); report(INFO,"Refresh Rate: %dHz.", glfwGetWindowParam(GLFW_REFRESH_RATE)); report(PASS, "Intialized."); glfwSetKeyCallback(My_Key_Callback); return 0; } int main(int argc, char **argv) { GLenum glError; if(initialize()) //basic initialisation exit(EXIT_FAILURE); glError = glGetError(); if(glError != GL_NO_ERROR){ report(FAIL, "Failed to init!"); return -1; } //create the shaders GLuint shaderProgram = createProgramFromFilenames("./shaders/pointPath.vert", "./shaders/spritePoint.frag"); glUseProgram (shaderProgram); if(glGetError() != GL_NO_ERROR) report(FAIL, "An error occured while building the shader program!"); else report(PASS, "Succesfully using shaders"); //Create and set first texture. v2f path[] = {{-0.5,0.5},//A path "t -> (x,y)" along which we will place our sprites {-0.5,-0.5}, {0.5,-0.5}, {0.5,0.5}}; glActiveTexture(GL_TEXTURE0); if(glGetError() != GL_NO_ERROR) report(FAIL, "Couldn't activate texture!"); GLuint pathTex; glGenTextures(1, &pathTex); //create a new texture glBindTexture(GL_TEXTURE_1D, pathTex); //start using it as a 1D texture glTexImage1D(GL_TEXTURE_1D,0,GL_RG32F, sizeof(path)/sizeof(v2f),0,GL_RG,GL_FLOAT,path); //store the coordinates of path in the texture so that we can interpolate our path in the shader. glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_BASE_LEVEL, 0);//We need these two lines glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAX_LEVEL, 0);//because we don't have mipmaps. glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);//We want the path to be linearly filtered glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);//Set the min filter just to be safe. if(glGetError() != GL_NO_ERROR) report(FAIL, "Something went wrong setting up pathTex"); GLint uniformLoc = glGetUniformLocation(shaderProgram, "pathTexture"); //locate the uniform uniformLoc >= 0?glUniform1i(uniformLoc, 0):report(FAIL, "found uniform spriteTexture at %d", uniformLoc); //and set it to "0" because we're using GL_TEXTURE0 if(glGetError() != GL_NO_ERROR) report(FAIL, "Couldn't set uniform!"); report(PASS, "Setup texture for path"); //create and set second texture rgba sprite[] = {{1.0,0,0,1},{0,1.0,0,1},{0,0,1.0,1},{1,1,0,1}}; //our sprite, a simple "red,green,blue,yellow" square. glActiveTexture(GL_TEXTURE0+1); //use texUnit 1 now. if(glGetError() != GL_NO_ERROR) report(FAIL, "Couldn't activate texture!"); GLuint spriteTex; glGenTextures(1, &spriteTex); //create a new texture glBindTexture(GL_TEXTURE_2D, spriteTex); //start using it as a 2D texture glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA, 2,2,0,GL_RGBA,GL_FLOAT,sprite); //load the data again. 2x2 sprite. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);//We need these two lines glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);//because we don't have mipmaps. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);//We want our sprites to be filtered to glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);//the nearest pixel, not interpolated. if(glGetError() != GL_NO_ERROR) report(FAIL, "Something went wrong setting up pathTex"); uniformLoc = glGetUniformLocation(shaderProgram, "spriteTexture"); //locates and set the second sampler. uniformLoc >= 0?glUniform1i(uniformLoc, 1):report(FAIL, "found uniform spriteTexture at %d", uniformLoc); if(glGetError() != GL_NO_ERROR) report(FAIL, "Couldn't set uniform!"); report(PASS, "Setup texture for sprite"); //Create our sprite locations #define Npoints 1024 //any number > the number of path points will do. GLfloat points[Npoints]; //the location in "t-space" of our sprites, i.e. the texture coordinate for our path texture. for(size_t i = 0; i < Npoints;i++) points[i] = (float)i/(float)Npoints; //fill it from 0 to 1. report(PASS, "generated points array."); //set-up a our buffers. unsigned int vaSprites; glGenVertexArrays(1,&vaSprites); report(PASS, "Generated vertex array"); unsigned int vbSprites; glGenBuffers(1, &vbSprites); glBindBuffer(GL_ARRAY_BUFFER, vbSprites); glBufferData (GL_ARRAY_BUFFER, sizeof(points), points, GL_STATIC_DRAW); if(glGetError() != GL_NO_ERROR) report(FAIL, "Something went wrong generating the vbSprites!"); glBindVertexArray(vaSprites); GLint inputAttrib = glGetAttribLocation(shaderProgram, "t"); glEnableVertexAttribArray(inputAttrib); glVertexAttribPointer (inputAttrib, 1, GL_FLOAT, GL_FALSE, 0, (GLubyte*)NULL); if(glGetError() != GL_NO_ERROR) report(FAIL, "Something went wrong generating the vaSprites!"); else report(PASS, "Set-up vaSprites."); glEnable(GL_POINT_SPRITE); //We need this (on Nvidia atleast) for obvious reasons. glPointSize(64); while(1){ //our main loop,it's broken by hitting space. glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glDrawArrays(GL_POINTS,0, Npoints); glfwSwapBuffers(); } return 0; }