|
| 1 | +#include <iostream> |
| 2 | +#include <stdlib.h> |
| 3 | + |
| 4 | +// GLEW |
| 5 | +#define GLEW_STATIC |
| 6 | +#include <GL/glew.h> |
| 7 | + |
| 8 | +// GLFW |
| 9 | +#include <GLFW/glfw3.h> |
| 10 | + |
| 11 | +// Other includes |
| 12 | +#include "include/shader.h" |
| 13 | +#include <include/camera.h> |
| 14 | + |
| 15 | +// glm |
| 16 | +#include <include/glm/glm.hpp> |
| 17 | +#include <include/glm/gtc/matrix_transform.hpp> |
| 18 | +#include <include/glm/gtc/type_ptr.hpp> |
| 19 | + |
| 20 | + |
| 21 | +//callbacks |
| 22 | +void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode); |
| 23 | +void scroll_callback(GLFWwindow* window, double xoffset, double yoffset); |
| 24 | +void mouse_callback(GLFWwindow* window, double xpos, double ypos); |
| 25 | + |
| 26 | +//function prototypes |
| 27 | +void Do_Movement(); |
| 28 | + |
| 29 | +// Camera |
| 30 | +Camera camera(glm::vec3(0.0f, 0.0f, 3.0f)); |
| 31 | +bool keys[1024]; |
| 32 | +GLfloat lastX = 400, lastY = 300; |
| 33 | +bool firstMouse = true; |
| 34 | + |
| 35 | +GLfloat deltaTime = 0.0f; |
| 36 | +GLfloat lastFrame = 0.0f; |
| 37 | +GLuint frames = 0; |
| 38 | +GLfloat timePassed = 0.0f; |
| 39 | +GLfloat startTime = 0.0f; |
| 40 | +glm::mat4 MVPM; |
| 41 | + |
| 42 | + |
| 43 | +// Window dimensions |
| 44 | +const GLuint WIDTH = 800, HEIGHT = 600; |
| 45 | + |
| 46 | +// The MAIN function, from here we start the application and run the game loop |
| 47 | +int main() |
| 48 | +{ |
| 49 | + // Init GLFW |
| 50 | + glfwInit(); |
| 51 | + // Set all the required options for GLFW |
| 52 | + glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); |
| 53 | + glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); |
| 54 | + glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); |
| 55 | + glfwWindowHint(GLFW_RESIZABLE, GL_FALSE); |
| 56 | + glfwWindowHint(GLFW_SAMPLES, 4); |
| 57 | + |
| 58 | + // Create a GLFWwindow object that we can use for GLFW's functions |
| 59 | + GLFWwindow* window = glfwCreateWindow(WIDTH, HEIGHT, "Instanced Cubes", nullptr, nullptr); |
| 60 | + glfwMakeContextCurrent(window); |
| 61 | + |
| 62 | + // Set the required callback functions |
| 63 | + glfwSetKeyCallback(window, key_callback); |
| 64 | + glfwSetCursorPosCallback(window, mouse_callback); |
| 65 | + glfwSetScrollCallback(window, scroll_callback); |
| 66 | + |
| 67 | + //glfw options |
| 68 | + glfwSetWindowPos(window, 200, 17);//so you can see frame rate |
| 69 | + glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED); |
| 70 | + |
| 71 | + // Set this to true so GLEW knows to use a modern approach to retrieving function pointers and extensions |
| 72 | + glewExperimental = GL_TRUE; |
| 73 | + // Initialize GLEW to setup the OpenGL Function pointers |
| 74 | + glewInit(); |
| 75 | + |
| 76 | + // Define the viewport dimensions |
| 77 | + glViewport(0, 0, WIDTH, HEIGHT); |
| 78 | + |
| 79 | + //openGL options |
| 80 | + glEnable(GL_MULTISAMPLE); |
| 81 | + glEnable(GL_DEPTH_TEST); |
| 82 | + glEnable(GL_CULL_FACE); |
| 83 | + //glEnable(GL_BLEND); |
| 84 | + //glEnable(GL_PROGRAM_POINT_SIZE); |
| 85 | + //glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); |
| 86 | + |
| 87 | + // Build and compile our shader program |
| 88 | + Shader ourShader("basic.vert", "basic.frag"); |
| 89 | + |
| 90 | + |
| 91 | + // Set up vertex data (and buffer(s)) and attribute pointers |
| 92 | + GLfloat vertices[] = { |
| 93 | + // Positions // Colors //texcoords |
| 94 | + 1.0f, 1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f,// back-top-right |
| 95 | + 1.0f, -1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f,// back-bottom-right |
| 96 | + -1.0f, -1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f,// back-bottom-left |
| 97 | + -1.0f, 1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f,// back-top-left |
| 98 | + 1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f,// front-bottom-right |
| 99 | + -1.0f, -1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f,// front-bottom-left |
| 100 | + -1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f,// front-top-left |
| 101 | + 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f // front-top-right |
| 102 | + }; |
| 103 | + GLuint indices[] = { |
| 104 | + 0, 1, 3,//back face |
| 105 | + 1, 2, 3, |
| 106 | + 0, 7, 1,//right face |
| 107 | + 1, 7, 4, |
| 108 | + 2, 6, 3,//left face |
| 109 | + 5, 6, 2, |
| 110 | + 7, 6, 4,//front face |
| 111 | + 6, 5, 4, |
| 112 | + 3, 7, 0,//top face |
| 113 | + 3, 6, 7, |
| 114 | + 1, 4, 2,//bottom face |
| 115 | + 2, 4, 5 |
| 116 | + }; |
| 117 | + |
| 118 | + int length = 100000; |
| 119 | + glm::mat4 *translations = new glm::mat4[length]; |
| 120 | + int index = 0; |
| 121 | + |
| 122 | + for(GLint x = 0; x < length; x += 1) { |
| 123 | + glm::mat4 translation; |
| 124 | + GLfloat angle = 20.0f * x; |
| 125 | + translation = glm::translate(translation, glm::vec3((GLfloat) (rand()%100), (GLfloat) (rand()%100), (GLfloat) (rand()%100))); |
| 126 | + translation = glm::rotate(translation, angle, glm::vec3(1.0f, 0.3f, 0.5f)); |
| 127 | + translations[index++] = translation; |
| 128 | + } |
| 129 | + |
| 130 | + GLuint VBO, VAO, EBO, instanceVBO; |
| 131 | + glGenVertexArrays(1, &VAO); |
| 132 | + glGenBuffers(1, &VBO); |
| 133 | + glGenBuffers(1, &EBO); |
| 134 | + glGenBuffers(1, &instanceVBO); |
| 135 | + // Bind the Vertex Array Object first, then bind and set vertex buffer(s) and attribute pointer(s). |
| 136 | + glBindVertexArray(VAO); |
| 137 | + |
| 138 | + glBindBuffer(GL_ARRAY_BUFFER, VBO); |
| 139 | + glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); |
| 140 | + |
| 141 | + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO); |
| 142 | + glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW); |
| 143 | + |
| 144 | + glBindBuffer(GL_ARRAY_BUFFER, instanceVBO); |
| 145 | + glBufferData(GL_ARRAY_BUFFER, sizeof(glm::mat4)*length, translations, GL_STATIC_DRAW); |
| 146 | + |
| 147 | + glBindBuffer(GL_ARRAY_BUFFER, VBO); |
| 148 | + // Position attribute |
| 149 | + GLint posAttrib = glGetAttribLocation(ourShader.Program, "position"); |
| 150 | + glVertexAttribPointer(posAttrib, 3, GL_FLOAT, GL_FALSE, 9 * sizeof(GLfloat), (GLvoid*)0); |
| 151 | + glEnableVertexAttribArray(posAttrib); |
| 152 | + // Color attribute |
| 153 | + GLint colAttrib = glGetAttribLocation(ourShader.Program, "color"); |
| 154 | + glVertexAttribPointer(colAttrib, 3, GL_FLOAT, GL_FALSE, 9 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat))); |
| 155 | + glEnableVertexAttribArray(colAttrib); |
| 156 | + |
| 157 | + GLint texAttrib = glGetAttribLocation(ourShader.Program, "texCoords"); |
| 158 | + glVertexAttribPointer(texAttrib, 3, GL_FLOAT, GL_FALSE, 9 * sizeof(GLfloat), (GLvoid*)(6 * sizeof(GLfloat))); |
| 159 | + glEnableVertexAttribArray(texAttrib); |
| 160 | + |
| 161 | + // per-instance attributes |
| 162 | + glBindBuffer(GL_ARRAY_BUFFER, instanceVBO); |
| 163 | + |
| 164 | + GLint offAttrib = glGetAttribLocation(ourShader.Program, "model"); |
| 165 | + glVertexAttribPointer(offAttrib, 4, GL_FLOAT, GL_FALSE, sizeof(glm::vec4)*4, ( GLvoid*)0); |
| 166 | + glEnableVertexAttribArray(offAttrib); |
| 167 | + glVertexAttribDivisor(offAttrib, 1); |
| 168 | + |
| 169 | + glVertexAttribPointer(offAttrib+1, 4, GL_FLOAT, GL_FALSE, sizeof(glm::vec4)*4, ( GLvoid*)(4 * sizeof(GLfloat))); |
| 170 | + glEnableVertexAttribArray(offAttrib+1); |
| 171 | + glVertexAttribDivisor(offAttrib+1, 1); |
| 172 | + |
| 173 | + glVertexAttribPointer(offAttrib+2, 4, GL_FLOAT, GL_FALSE, sizeof(glm::vec4)*4, ( GLvoid*)(8 * sizeof(GLfloat))); |
| 174 | + glEnableVertexAttribArray(offAttrib+2); |
| 175 | + glVertexAttribDivisor(offAttrib+2, 1); |
| 176 | + |
| 177 | + glVertexAttribPointer(offAttrib+3, 4, GL_FLOAT, GL_FALSE, sizeof(glm::vec4)*4, ( GLvoid*)(12 * sizeof(GLfloat))); |
| 178 | + glEnableVertexAttribArray(offAttrib+3); |
| 179 | + glVertexAttribDivisor(offAttrib+3, 1); |
| 180 | + |
| 181 | + glBindBuffer(GL_ARRAY_BUFFER, 0); |
| 182 | + glBindVertexArray(0); // Unbind VAO |
| 183 | + |
| 184 | + //set up Model-View-Projection matrix |
| 185 | + //this way you only update when camera moves |
| 186 | + glm::mat4 view; |
| 187 | + view = camera.GetViewMatrix(); |
| 188 | + glm::mat4 projection; |
| 189 | + projection = glm::perspective(glm::radians(camera.Zoom), (float)WIDTH/(float)HEIGHT, 0.1f, 1000.0f); |
| 190 | + MVPM = projection * view ; |
| 191 | + |
| 192 | + GLuint uniformMatrix = glGetUniformLocation(ourShader.Program, "MVPM"); |
| 193 | + // Game loop |
| 194 | + while (!glfwWindowShouldClose(window)) |
| 195 | + { |
| 196 | + // Set frame time |
| 197 | + GLfloat currentFrame = glfwGetTime(); |
| 198 | + deltaTime = currentFrame - lastFrame; |
| 199 | + timePassed = currentFrame; |
| 200 | + if (timePassed - startTime > 0.25 && frames > 10) { |
| 201 | + //frame rate |
| 202 | + //std::cout<<frames/(timePassed-startTime)<<std::endl; |
| 203 | + //time in milliseconds |
| 204 | + std::cout<<deltaTime*1000.0<<endl; |
| 205 | + startTime = timePassed; |
| 206 | + frames = 0; |
| 207 | + } |
| 208 | + lastFrame = currentFrame; |
| 209 | + frames++; |
| 210 | + // Check and call events |
| 211 | + glfwPollEvents(); |
| 212 | + Do_Movement(); |
| 213 | + |
| 214 | + // Render |
| 215 | + // Clear the colorbuffer |
| 216 | + glClearColor(0.2f, 0.3f, 0.3f, 1.0f); |
| 217 | + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); |
| 218 | + |
| 219 | + // Draw the triangle |
| 220 | + ourShader.Use(); |
| 221 | + |
| 222 | + // Pass the matrices to the shader |
| 223 | + glUniformMatrix4fv(uniformMatrix, 1, GL_FALSE, glm::value_ptr(MVPM)); |
| 224 | + |
| 225 | + glBindVertexArray(VAO); |
| 226 | + |
| 227 | + glDrawElementsInstanced(GL_TRIANGLES, 36, GL_UNSIGNED_INT, 0, length); |
| 228 | + //glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_INT, 0); |
| 229 | + glBindVertexArray(0); |
| 230 | + |
| 231 | + // Swap the screen buffers |
| 232 | + glfwSwapBuffers(window); |
| 233 | + } |
| 234 | + // Properly de-allocate all resources once they've outlived their purpose |
| 235 | + glDeleteVertexArrays(1, &VAO); |
| 236 | + glDeleteBuffers(1, &VBO); |
| 237 | + // Terminate GLFW, clearing any resources allocated by GLFW. |
| 238 | + glfwTerminate(); |
| 239 | + return 0; |
| 240 | +} |
| 241 | + |
| 242 | +void Do_Movement() |
| 243 | +{ |
| 244 | + // Camera controls |
| 245 | + if(keys[GLFW_KEY_W]) |
| 246 | + camera.ProcessKeyboard(FORWARD, deltaTime); |
| 247 | + if(keys[GLFW_KEY_S]) |
| 248 | + camera.ProcessKeyboard(BACKWARD, deltaTime); |
| 249 | + if(keys[GLFW_KEY_A]) |
| 250 | + camera.ProcessKeyboard(LEFT, deltaTime); |
| 251 | + if(keys[GLFW_KEY_D]) |
| 252 | + camera.ProcessKeyboard(RIGHT, deltaTime); |
| 253 | + |
| 254 | + glm::mat4 view; |
| 255 | + view = camera.GetViewMatrix(); |
| 256 | + glm::mat4 projection; |
| 257 | + projection = glm::perspective(glm::radians(camera.Zoom), (float)WIDTH/(float)HEIGHT, 0.1f, 1000.0f); |
| 258 | + MVPM = projection * view; |
| 259 | +} |
| 260 | + |
| 261 | +// Is called whenever a key is pressed/released via GLFW |
| 262 | +void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode) |
| 263 | +{ |
| 264 | + //cout << key << endl; |
| 265 | + if(key == GLFW_KEY_ESCAPE && action == GLFW_PRESS) |
| 266 | + glfwSetWindowShouldClose(window, GL_TRUE); |
| 267 | + if (key >= 0 && key < 1024) |
| 268 | + { |
| 269 | + if(action == GLFW_PRESS) |
| 270 | + keys[key] = true; |
| 271 | + else if(action == GLFW_RELEASE) |
| 272 | + keys[key] = false; |
| 273 | + } |
| 274 | +} |
| 275 | + |
| 276 | +void mouse_callback(GLFWwindow* window, double xpos, double ypos) |
| 277 | +{ |
| 278 | + if(firstMouse) |
| 279 | + { |
| 280 | + lastX = xpos; |
| 281 | + lastY = ypos; |
| 282 | + firstMouse = false; |
| 283 | + } |
| 284 | + |
| 285 | + GLfloat xoffset = xpos - lastX; |
| 286 | + GLfloat yoffset = lastY - ypos; // Reversed since y-coordinates go from bottom to left |
| 287 | + |
| 288 | + lastX = xpos; |
| 289 | + lastY = ypos; |
| 290 | + |
| 291 | + camera.ProcessMouseMovement(xoffset, yoffset); |
| 292 | + |
| 293 | + glm::mat4 view; |
| 294 | + view = camera.GetViewMatrix(); |
| 295 | + glm::mat4 projection; |
| 296 | + projection = glm::perspective(glm::radians(camera.Zoom), (float)WIDTH/(float)HEIGHT, 0.1f, 1000.0f); |
| 297 | + MVPM = projection * view; |
| 298 | +} |
| 299 | + |
| 300 | + |
| 301 | +void scroll_callback(GLFWwindow* window, double xoffset, double yoffset) |
| 302 | +{ |
| 303 | + camera.ProcessMouseScroll(yoffset); |
| 304 | + |
| 305 | + glm::mat4 view; |
| 306 | + view = camera.GetViewMatrix(); |
| 307 | + glm::mat4 projection; |
| 308 | + projection = glm::perspective(glm::radians(camera.Zoom), (float)WIDTH/(float)HEIGHT, 0.1f, 1000.0f); |
| 309 | + MVPM = projection * view; |
| 310 | +} |
0 commit comments