/* Had to change the params in antons math class because near and far are already defined somewhere else..i think. Also to get rid of that stupid ambiguous variable error I got rid of the "using namespace std". Will just use "std::" if i need anything. */ #define _CRT_SECURE_NO_DEPRECATE //Some Windows Headers (For Time, IO, etc.) #include #include #include #include #include #include "maths_funcs.h" //Anton's math class #include "teapot.h" // teapot mesh // Macro for indexing vertex buffer #define BUFFER_OFFSET(i) ((char *)NULL + (i)) //using namespace std; GLuint shaderProgramID; GLfloat rotateSpeed = 0.0f, move = -40.0f; unsigned int teapot_vao = 0; int width = 800.0; int height = 600.0; // Shader Functions- click on + to expand #pragma region SHADER_FUNCTIONS // Create a NULL-terminated string by reading the provided file char* readShaderSource(const char* shaderFile) { FILE* fp = fopen(shaderFile, "rb"); //!->Why does binary flag "RB" work and not "R"... wierd msvc thing? 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; } static void AddShader(GLuint ShaderProgram, const char* pShaderText, GLenum ShaderType) { // create a shader object GLuint ShaderObj = glCreateShader(ShaderType); if (ShaderObj == 0) { fprintf(stderr, "Error creating shader type %d\n", ShaderType); exit(0); } /** pShaderText is the problem.... **/ const char* pShaderSource = readShaderSource(pShaderText); // Bind the source code to the shader, this happens before compilation glShaderSource(ShaderObj, 1, (const GLchar**)&pShaderSource, NULL); // compile the shader and check for errors glCompileShader(ShaderObj); GLint success; // check for shader related errors using glGetShaderiv glGetShaderiv(ShaderObj, GL_COMPILE_STATUS, &success); if (!success) { GLchar InfoLog[1024]; glGetShaderInfoLog(ShaderObj, 1024, NULL, InfoLog); fprintf(stderr, "Error compiling shader type %d: '%s'\n", ShaderType, InfoLog); exit(1); } // Attach the compiled shader object to the program object glAttachShader(ShaderProgram, ShaderObj); } GLuint CompileShaders() { //Start the process of setting up our shaders by creating a program ID //Note: we will link all the shaders together into this ID shaderProgramID = glCreateProgram(); if (shaderProgramID == 0) { fprintf(stderr, "Error creating shader program\n"); exit(1); } // Create two shader objects, one for the vertex, and one for the fragment shader AddShader(shaderProgramID, "../Shaders/simpleVertexShader.txt", GL_VERTEX_SHADER); AddShader(shaderProgramID, "../Shaders/simpleFragmentShader.txt", GL_FRAGMENT_SHADER); GLint Success = 0; GLchar ErrorLog[1024] = { 0 }; // After compiling all shader objects and attaching them to the program, we can finally link it glLinkProgram(shaderProgramID); // check for program related errors using glGetProgramiv glGetProgramiv(shaderProgramID, GL_LINK_STATUS, &Success); if (Success == 0) { glGetProgramInfoLog(shaderProgramID, sizeof(ErrorLog), NULL, ErrorLog); fprintf(stderr, "Error linking shader program: '%s'\n", ErrorLog); exit(1); } // program has been successfully linked but needs to be validated to check whether the program can execute given the current pipeline state glValidateProgram(shaderProgramID); // check for program related errors using glGetProgramiv glGetProgramiv(shaderProgramID, GL_VALIDATE_STATUS, &Success); if (!Success) { glGetProgramInfoLog(shaderProgramID, sizeof(ErrorLog), NULL, ErrorLog); fprintf(stderr, "Invalid shader program: '%s'\n", ErrorLog); exit(1); } // Finally, use the linked shader program // Note: this program will stay in effect for all draw calls until you replace it with another or explicitly disable its use glUseProgram(shaderProgramID); return shaderProgramID; } #pragma endregion SHADER_FUNCTIONS // VBO Functions - click on + to expand #pragma region VBO_FUNCTIONS void generateObjectBufferTeapot () { GLuint vp_vbo = 0; glGenBuffers (1, &vp_vbo); glBindBuffer (GL_ARRAY_BUFFER, vp_vbo); glBufferData (GL_ARRAY_BUFFER, 3 * teapot_vertex_count * sizeof (float), teapot_vertex_points, GL_STATIC_DRAW); GLuint vn_vbo = 0; glGenBuffers (1, &vn_vbo); glBindBuffer (GL_ARRAY_BUFFER, vn_vbo); glBufferData (GL_ARRAY_BUFFER, 3 * teapot_vertex_count * sizeof (float), teapot_normals, GL_STATIC_DRAW); glGenVertexArrays (1, &teapot_vao); glBindVertexArray (teapot_vao); glEnableVertexAttribArray (0); glBindBuffer (GL_ARRAY_BUFFER, vp_vbo); glVertexAttribPointer (0, 3, GL_FLOAT, GL_FALSE, 0, NULL); glEnableVertexAttribArray (1); glBindBuffer (GL_ARRAY_BUFFER, vn_vbo); glVertexAttribPointer (1, 3, GL_FLOAT, GL_FALSE, 0, NULL); } void linkCurrentBuffertoShader(GLuint shaderProgramID){ glBindAttribLocation (shaderProgramID, 0, "vertex_position"); glBindAttribLocation (shaderProgramID, 1, "vertex_normals"); } #pragma endregion VBO_FUNCTIONS void display(){ // tell GL to only draw onto a pixel if the shape is closer to the viewer glEnable (GL_DEPTH_TEST); // enable depth-testing glDepthFunc (GL_LESS); // depth-testing interprets a smaller value as "closer" glClearColor (0.5f, 0.5f, 0.5f, 1.0f); glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glUseProgram (shaderProgramID); //Declare your uniform variables that will be used in your shader int matrix_location = glGetUniformLocation (shaderProgramID, "model"); int view_mat_location = glGetUniformLocation (shaderProgramID, "view"); int proj_mat_location = glGetUniformLocation (shaderProgramID, "proj"); rotateSpeed = rotateSpeed + 0.4f; if (move > 40.0f){ move = -40.0f; } move = move + 0.4f; //Here is where the code for the viewport lab will go, to get you started I have drawn a t-pot in the bottom left //The model transform rotates the object by 45 degrees, the view transform sets the camera at -40 on the z-axis, and the perspective projection is setup using Antons method //****************************************************************************************************************************************************************************** // bottom-left mat4 view = translate (identity_mat4 (), vec3 (0.0, 0.0, -40.0)); mat4 persp_proj = perspective(50.0, (float)width/(float)height, 0.1, 100.0); mat4 model = rotate_x_deg (identity_mat4 (), 40); glViewport (0, 0, width / 2, height / 2); GLfloat aspect = (width/2) / (height/2); glOrtho(-aspect,aspect,-1,1,-1,1000); glUniformMatrix4fv (proj_mat_location, 1, GL_FALSE, persp_proj.m); glUniformMatrix4fv (view_mat_location, 1, GL_FALSE, view.m); glUniformMatrix4fv (matrix_location, 1, GL_FALSE, model.m); glDrawArrays (GL_TRIANGLES, 0, teapot_vertex_count); //****************************************************************************************************************************************************************************** // bottom-right mat4 view1 = translate (identity_mat4 (), vec3 (move, 0.0, -40.0)); mat4 persp_proj1 = perspective(50.0, (float)width/(float)height, 0.1, 100);// mat4 persp_proj1 = perspective(50.0, (float)width/(float)height, 0.1, move); this will allow the object to fade in and out. mat4 model1 = rotate_x_deg (identity_mat4 (), rotateSpeed); model1 = model1 * rotate_y_deg(model1, rotateSpeed*10); model1 = model1 * rotate_x_deg(model1, rotateSpeed); glViewport (400, 0, width / 2, height / 2); glUniformMatrix4fv (proj_mat_location, 1, GL_FALSE, persp_proj1.m); glUniformMatrix4fv (view_mat_location, 1, GL_FALSE, view1.m); glUniformMatrix4fv (matrix_location, 1, GL_FALSE, model1.m); glDrawArrays (GL_TRIANGLES, 0, teapot_vertex_count); //****************************************************************************************************************************************************************************** // top-left mat4 view2 = translate (identity_mat4 (), vec3 (0.0, 0.0, -40.0)); mat4 persp_proj2 = perspective(50.0, (float)width/(float)height, 0.1, 100.0); mat4 model2 = rotate_x_deg (identity_mat4 (), 0); //model2 = model2 * rotate_x_deg(model, ); glViewport (0, 300, width / 2, height / 2); glUniformMatrix4fv (proj_mat_location, 1, GL_FALSE, persp_proj2.m); glUniformMatrix4fv (view_mat_location, 1, GL_FALSE, view2.m); glUniformMatrix4fv (matrix_location, 1, GL_FALSE, model2.m); glDrawArrays (GL_TRIANGLES, 0, teapot_vertex_count); //****************************************************************************************************************************************************************************** // top-right mat4 view3 = translate (identity_mat4 (), vec3 (0.0, 0.0, -40.0)); mat4 persp_proj3 = perspective(50.0, (float)width/(float)height, 0.1, 100.0); mat4 model3 = rotate_y_deg (identity_mat4 (), 90); //model = model * rotate_x_deg(model, ); glViewport (400, 300, width / 2, height / 2); glUniformMatrix4fv (proj_mat_location, 1, GL_FALSE, persp_proj3.m); glUniformMatrix4fv (view_mat_location, 1, GL_FALSE, view3.m); glUniformMatrix4fv (matrix_location, 1, GL_FALSE, model3.m); glDrawArrays (GL_TRIANGLES, 0, teapot_vertex_count); glutSwapBuffers(); } void updateScene() { // Wait until at least 16ms passed since start of last frame (Effectively caps framerate at ~60fps) static DWORD last_time = 0; DWORD curr_time = timeGetTime(); float delta = (curr_time - last_time) * 0.001f; if (delta > 0.03f) delta = 0.03f; last_time = curr_time; // Draw the next frame glutPostRedisplay(); } void init() { // Create 3 vertices that make up a triangle that fits on the viewport GLfloat vertices[] = {-1.0f, -1.0f, 0.0f, 1.0, 1.0f, -1.0f, 0.0f, 1.0, 0.0f, 1.0f, 0.0f, 1.0}; // Create a color array that identfies the colors of each vertex (format R, G, B, A) GLfloat colors[] = {0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f}; // Set up the shaders GLuint shaderProgramID = CompileShaders(); // load teapot mesh into a vertex buffer array generateObjectBufferTeapot (); // Link the current buffer to the shader linkCurrentBuffertoShader(shaderProgramID); } void keyPressed(unsigned char key, int x, int y){ switch(key){ case 27: exit(0); break; default: break; } } int main(int argc, char** argv){ // Set up the window glutInit(&argc, argv); glutInitDisplayMode(GLUT_DOUBLE|GLUT_RGB); glutInitWindowSize(width, height); glutCreateWindow("Viewport Teapots"); glutKeyboardFunc(keyPressed); // Tell glut where the display function is glutDisplayFunc(display); glutIdleFunc(updateScene); // A call to glewInit() must be done after glut is initialized! GLenum res = glewInit(); // Check for any errors if (res != GLEW_OK) { fprintf(stderr, "Error: '%s'\n", glewGetErrorString(res)); return 1; } // Set up your objects and shaders init(); // Begin infinite event loop glutMainLoop(); return 0; }