/*
* @topic T0L083 Index Buffers
* @brief OpenGL client program
*/
#include <GL/glew.h>
#include <GL/freeglut.h>
#include <stdio.h>
// main_Lecture08.cpp
// shader path configuration:
#define BCC_PROJECT_NAME "Lecture08_Index"
#define BCC_ROOT_PATH "../../example/"
#define BCC_VERTEX_SHADER BCC_ROOT_PATH BCC_PROJECT_NAME "/Shaders/vertexProgram_v.c"
#define BCC_FRAGMENT_SHADER BCC_ROOT_PATH BCC_PROJECT_NAME "/Shaders/fragmentProgram_f.c"
#define BCC_USING_INDEX_BUFFER 1
#ifdef BCC_USING_INDEX_BUFFER
#define NUM_VERTICES 6
#define NUM_INDICES 9
#else
#define NUM_VERTICES 9
#endif
#define BUFFER_OFFSET(i) ((char *)NULL + (i))
GLuint shader_program_ID;
GLuint vao = 0;
GLuint vbo;
GLuint position_ID, colorID;
GLuint index_buffer_ID;
// Begin shader functions
static char* load_text_file(const char* filename) {
// Open the file
FILE* fp = fopen (filename, "r");
// Move the file pointer to the end of the file and determing the length
fseek(fp, 0, SEEK_END);
long file_length = ftell(fp);
fseek(fp, 0, SEEK_SET);
char* contents = new char[file_length+1];
// zero out memory
for (int i = 0; i < file_length+1; i++) {
contents[i] = 0;
}
// Here's the actual read
fread (contents, 1, file_length, fp);
// This is how you denote the end of a string in C
contents[file_length] = '\0';
fclose(fp);
return contents;
}
bool is_shader_compiled_okay(GLint shader_ID){
GLint compiled = 0;
glGetShaderiv(shader_ID, GL_COMPILE_STATUS, &compiled);
if (compiled) {
return true;
}
else {
GLint log_length;
glGetShaderiv(shader_ID, GL_INFO_LOG_LENGTH, &log_length);
char* msg_buffer = new char[log_length];
glGetShaderInfoLog(shader_ID, log_length, NULL, msg_buffer);
printf ("%s\n", msg_buffer);
delete[] (msg_buffer);
return false;
}
}
GLuint compile_vertex_shader(const char* shader_source) {
GLuint vertex_shader_ID = glCreateShader(GL_VERTEX_SHADER);
glShaderSource (vertex_shader_ID, 1, (const GLchar**)&shader_source, NULL);
glCompileShader(vertex_shader_ID);
bool compiled_correctly = is_shader_compiled_okay(vertex_shader_ID);
if (compiled_correctly) {
return vertex_shader_ID;
}
return -1;
}
GLuint compile_fragment_shader(const char* shader_source) {
GLuint fragment_shader_ID = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragment_shader_ID, 1, (const GLchar**)&shader_source, NULL);
glCompileShader(fragment_shader_ID);
bool compiled_correctly = is_shader_compiled_okay(fragment_shader_ID);
if (compiled_correctly) {
return fragment_shader_ID;
}
return -1;
}
GLuint link_shader_program (GLuint vertex_shader_ID, GLuint fragment_shader_ID) {
GLuint shader_ID = glCreateProgram();
glAttachShader(shader_ID, vertex_shader_ID);
glAttachShader(shader_ID, fragment_shader_ID);
glLinkProgram(shader_ID);
return shader_ID;
}
// End shader functions
// Any time the window is resized, this function gets called. Set by the
// "glutReshapeFunc" in main.
void change_viewport(int w, int h){
glViewport(0, 0, w, h);
}
// Here is the function that gets called each time the window needs to be redrawn.
// It is the "paint" function for our program, and is set up from the glutDisplayFunc in main
void render() {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
#ifdef BCC_USING_INDEX_BUFFER
glDrawElements (GL_TRIANGLES, NUM_INDICES, GL_UNSIGNED_INT, NULL);
#else
glDrawArrays(GL_TRIANGLES, 0, NUM_VERTICES);
#endif
glutSwapBuffers();
}
int main (int argc, char** argv) {
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGBA|GLUT_DOUBLE|GLUT_DEPTH);
glutInitWindowSize(800, 600);
glutCreateWindow("Index Buffers");
glutReshapeFunc(change_viewport);
glutDisplayFunc(render);
glewInit();
#ifdef BCC_USING_INDEX_BUFFER
GLfloat vertices[] = {0.0f, 0.5f, 0.0f, // 0
-0.25f, 0.0f, 0.0f, // 1
0.25f, 0.0f, 0.0f, // 2
-0.5f, -0.5f, 0.0f, // 3
0.0f, -0.5f, 0.0f, // 4
0.5f, -0.5f, 0.0f // 5
};
GLfloat colors[] = {1.0f, 0.00f, 0.0f, 1.0f, // 0
0.0f, 1.00f, 0.0f, 1.0f, // 1
0.0f, 0.00f, 1.0f, 1.0f, // 2
0.0f, 0.00f, 1.0f, 1.0f, // 3
1.0f, 0.00f, 0.0f, 1.0f, // 4
0.0f, 1.0f, 0.0f, 1.0f // 5
};
GLuint indices[] = {0, 1, 2, 1, 3, 4, 2, 4, 5};
#else
GLfloat vertices[] = {-0.5f, -0.5f, 0.0f,
0.0f, -0.5f, 0.0f,
-0.25f, 0.0f, 0.0f,
-0.25f, 0.0f, 0.0f,
0.25f, 0.0f, 0.0f,
0.0f, 0.5f, 0.0f,
0.0f, -0.5f, 0.0f,
0.5f, -0.5f, 0.0f,
0.25f, 0.0f, 0.0f
};
GLfloat colors[] = {1.0f, 0.00f, 0.0f, 1.0f,
0.0f, 1.00f, 0.0f, 1.0f,
0.0f, 0.0f, 1.0f, 1.0f,
1.0f, 0.00f, 0.0f, 1.0f,
0.0f, 1.00f, 0.0f, 1.0f,
0.0f, 0.0f, 1.0f, 1.0f,
1.0f, 0.00f, 0.0f, 1.0f,
0.0f, 1.00f, 0.0f, 1.0f,
0.0f, 0.0f, 1.0f, 1.0f
};
#endif
// Make a shader
char* cstr_vertex_shader_source = load_text_file( BCC_VERTEX_SHADER );
char* cstr_fragment_shader_source = load_text_file( BCC_FRAGMENT_SHADER );
GLuint vert_shader_ID = compile_vertex_shader(cstr_vertex_shader_source);
GLuint frag_shader_ID = compile_fragment_shader(cstr_fragment_shader_source);
shader_program_ID = link_shader_program(vert_shader_ID, frag_shader_ID);
// Generate vertex array object names
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
// Create the buffer, but don't load anything yet
glBufferData(GL_ARRAY_BUFFER, 7*NUM_VERTICES*sizeof(GLfloat), NULL, GL_STATIC_DRAW);
// Load the vertex points
glBufferSubData(GL_ARRAY_BUFFER, 0, 3*NUM_VERTICES*sizeof(GLfloat), vertices);
// Load the colors right after that
glBufferSubData(GL_ARRAY_BUFFER, 3*NUM_VERTICES*sizeof(GLfloat),4*NUM_VERTICES*sizeof(GLfloat), colors);
#ifdef BCC_USING_INDEX_BUFFER
glGenBuffers(1, &index_buffer_ID);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index_buffer_ID);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, NUM_INDICES*sizeof(GLuint), indices, GL_STATIC_DRAW);
#endif
// Find the position of the variables in the shader
position_ID = glGetAttribLocation(shader_program_ID, "s_vPosition");
colorID = glGetAttribLocation(shader_program_ID, "s_vColor");
glVertexAttribPointer(position_ID, 3, GL_FLOAT, GL_FALSE, 0, 0);
glVertexAttribPointer(colorID, 4, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(sizeof(vertices)));
glUseProgram(shader_program_ID);
glEnableVertexAttribArray(position_ID);
glEnableVertexAttribArray(colorID);
glutMainLoop();
return 0;
}