Advertisement
acampbellblack

Untitled

Jan 22nd, 2024
254
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 11.05 KB | None | 0 0
  1. #include "shader.h"
  2.  
  3. #include <glad/glad.h>
  4. #include <GLFW/glfw3.h>
  5. #define STB_IMAGE_IMPLEMENTATION
  6. #include "stb_image.h"
  7. #include <glm/glm.hpp>
  8. #include <glm/gtc/matrix_transform.hpp>
  9.  
  10. #include <iostream>
  11. #include <cmath>
  12.  
  13. void framebuffer_size_callback(GLFWwindow* window, int width, int height);
  14. GLuint load_texture(const char* filepath, GLenum format);
  15. void process_input(GLFWwindow* window);
  16.  
  17. const unsigned int SCREEN_WIDTH = 800;
  18. const unsigned int SCREEN_HEIGHT = 600;
  19.  
  20. float mix_ratio = 0.2f;
  21.  
  22. glm::vec3 camera_position = glm::vec3(0.0f, 0.0f, 3.0f);
  23. glm::vec3 camera_front = glm::vec3(0.0f, 0.0f, -1.0f);
  24. glm::vec3 camera_up = glm::vec3(0.0f, 1.0f, 0.0f);
  25.  
  26. float delta_time;
  27. float last_frame_time;
  28.  
  29. int main()
  30. {
  31.     glfwInit();
  32.     glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
  33.     glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
  34.     glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
  35.     glfwWindowHint(GLFW_SCALE_TO_MONITOR, GLFW_TRUE);
  36. #ifdef __APPLE__
  37.     glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
  38. #endif
  39.  
  40.     GLFWwindow* window = glfwCreateWindow(800, 600, "LearnOpenGL", NULL, NULL);
  41.     if (window == NULL) {
  42.         std::cout << "Failed to create GLFW window." << std::endl;
  43.         glfwTerminate();
  44.         return -1;
  45.     }
  46.     glfwMakeContextCurrent(window);
  47.     glfwSetFramebufferSizeCallback(window, framebuffer_size_callback); // called when framebuffer of window is resized
  48.  
  49.     if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) {
  50.         std::cout << "Failed to initialize GLAD." << std::endl;
  51.         return -1;
  52.     }
  53.     glEnable(GL_DEPTH_TEST);
  54.  
  55.     stbi_set_flip_vertically_on_load(true); // usually top left is (0, 0) but OpenGL expects bottom left to be (0, 0)
  56.  
  57.     GLuint crate_texture = load_texture("container.jpg", GL_RGB);
  58.     GLuint face_texture = load_texture("awesomeface.png", GL_RGBA);
  59.  
  60.     float vertices[] = {
  61.         // positions          // texture coords
  62.         -0.5f, -0.5f, -0.5f,  0.0f, 0.0f,
  63.          0.5f, -0.5f, -0.5f,  1.0f, 0.0f,
  64.          0.5f,  0.5f, -0.5f,  1.0f, 1.0f,
  65.          0.5f,  0.5f, -0.5f,  1.0f, 1.0f,
  66.         -0.5f,  0.5f, -0.5f,  0.0f, 1.0f,
  67.         -0.5f, -0.5f, -0.5f,  0.0f, 0.0f,
  68.  
  69.         -0.5f, -0.5f,  0.5f,  0.0f, 0.0f,
  70.          0.5f, -0.5f,  0.5f,  1.0f, 0.0f,
  71.          0.5f,  0.5f,  0.5f,  1.0f, 1.0f,
  72.          0.5f,  0.5f,  0.5f,  1.0f, 1.0f,
  73.         -0.5f,  0.5f,  0.5f,  0.0f, 1.0f,
  74.         -0.5f, -0.5f,  0.5f,  0.0f, 0.0f,
  75.  
  76.         -0.5f,  0.5f,  0.5f,  1.0f, 0.0f,
  77.         -0.5f,  0.5f, -0.5f,  1.0f, 1.0f,
  78.         -0.5f, -0.5f, -0.5f,  0.0f, 1.0f,
  79.         -0.5f, -0.5f, -0.5f,  0.0f, 1.0f,
  80.         -0.5f, -0.5f,  0.5f,  0.0f, 0.0f,
  81.         -0.5f,  0.5f,  0.5f,  1.0f, 0.0f,
  82.  
  83.          0.5f,  0.5f,  0.5f,  1.0f, 0.0f,
  84.          0.5f,  0.5f, -0.5f,  1.0f, 1.0f,
  85.          0.5f, -0.5f, -0.5f,  0.0f, 1.0f,
  86.          0.5f, -0.5f, -0.5f,  0.0f, 1.0f,
  87.          0.5f, -0.5f,  0.5f,  0.0f, 0.0f,
  88.          0.5f,  0.5f,  0.5f,  1.0f, 0.0f,
  89.  
  90.         -0.5f, -0.5f, -0.5f,  0.0f, 1.0f,
  91.          0.5f, -0.5f, -0.5f,  1.0f, 1.0f,
  92.          0.5f, -0.5f,  0.5f,  1.0f, 0.0f,
  93.          0.5f, -0.5f,  0.5f,  1.0f, 0.0f,
  94.         -0.5f, -0.5f,  0.5f,  0.0f, 0.0f,
  95.         -0.5f, -0.5f, -0.5f,  0.0f, 1.0f,
  96.  
  97.         -0.5f,  0.5f, -0.5f,  0.0f, 1.0f,
  98.          0.5f,  0.5f, -0.5f,  1.0f, 1.0f,
  99.          0.5f,  0.5f,  0.5f,  1.0f, 0.0f,
  100.          0.5f,  0.5f,  0.5f,  1.0f, 0.0f,
  101.         -0.5f,  0.5f,  0.5f,  0.0f, 0.0f,
  102.         -0.5f,  0.5f, -0.5f,  0.0f, 1.0f
  103.     };
  104.  
  105.     GLuint vao, vbo, ebo;
  106.     glGenVertexArrays(1, &vao); // create a vertex array object, an array of attribute pointers telling OpenGL how to interpret our data
  107.     glGenBuffers(1, &vbo); // create a buffer on the GPU and get its id
  108.     //glGenBuffers(1, &ebo);
  109.  
  110.     // Bind VAO. Typically each mesh corresponds to a VAO.
  111.     glBindVertexArray(vao); // VBOs and EBOs that are bound while the VAO is bound will be linked to it
  112.  
  113.     // Bind VBO, upload data to it, and configure vertex attributes.
  114.     glBindBuffer(GL_ARRAY_BUFFER, vbo); // bind it as the current GL_ARRAY_BUFFER, which is for storing vertex attributes, setting VAO attribute pointers will now point to this VBO
  115.     glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); // copies vertex data into the currently bound GL_ARRAY_BUFFER
  116.  
  117.     glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)0); // add attribute pointer to VAO, corresponds to "layout (location = 0)" in vertex shader, applies to currently bound VAO
  118.     glEnableVertexAttribArray(0); // enable vertex attribute of currently bound VAO with name 0
  119.  
  120.     glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(3 * sizeof(float)));
  121.     glEnableVertexAttribArray(1);
  122.  
  123.     /*
  124.     // Bind EBO and upload data to it.
  125.     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo); // since this is bound while the VAO is bound, the VAO will keep track of it, so when VAO bound, will automatically bind the EBO
  126.     glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
  127.     */
  128.  
  129.     // VAO is bound while VBO and EBO are bound, and attributes set, all state is now contained within the VAO.
  130.  
  131.     // glBindBuffer(GL_ARRAY_BUFFER, 0); // we can safely unbind the VBO as we have registered it as the VAO attribute's bound vertex buffer object
  132.     glBindVertexArray(0); // unbind VAO so other VAO calls won't accidentally modify this VAO
  133.     // glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); // do not unbind EBO while VAO is bound, because EBO is stored in the VAO, unbinding EBO after VAO is fine
  134.     // We will bind another VBO or VAO before making changes to them, so explicitly unbinding them is typically not necessary.
  135.  
  136.     Shader shader("shader.vert", "shader.frag");
  137.     shader.use();
  138.  
  139.     glm::vec3 cubePositions[] = {
  140.         glm::vec3(0.0f,  0.0f,  0.0f),
  141.         glm::vec3(2.0f,  5.0f, -15.0f),
  142.         glm::vec3(-1.5f, -2.2f, -2.5f),
  143.         glm::vec3(-3.8f, -2.0f, -12.3f),
  144.         glm::vec3(2.4f, -0.4f, -3.5f),
  145.         glm::vec3(-1.7f,  3.0f, -7.5f),
  146.         glm::vec3(1.3f, -2.0f, -2.5f),
  147.         glm::vec3(1.5f,  2.0f, -2.5f),
  148.         glm::vec3(1.5f,  0.2f, -1.5f),
  149.         glm::vec3(-1.3f,  1.0f, -1.5f)
  150.     };
  151.  
  152.     while (!glfwWindowShouldClose(window)) {
  153.         float current_frame_time = glfwGetTime();
  154.         delta_time = current_frame_time - last_frame_time;
  155.         last_frame_time = current_frame_time;
  156.  
  157.         process_input(window);
  158.  
  159.         glClearColor(0.2f, 0.3f, 0.3f, 1.0f); // specify clear values for the color buffers
  160.         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // clear buffers to preset values, in this case the color buffer, but can also be depth and stencil buffers
  161.  
  162.         shader.use();
  163.         glm::mat4 model = glm::mat4(1.0f);
  164.         model = glm::rotate(model, (float)glfwGetTime() * glm::radians(50.0f), glm::vec3(0.5f, 1.0f, 0.0f));
  165.         shader.set_mat4("model", model);
  166.  
  167.         const float radius = 10.0f;
  168.         float camX = sin(glfwGetTime()) * radius;
  169.         float camZ = cos(glfwGetTime()) * radius;
  170.         glm::mat4 view;
  171.         view = glm::lookAt(camera_position, camera_position + camera_front, camera_up);
  172.         shader.set_mat4("view", view);
  173.  
  174.         glm::mat4 projection;
  175.         int viewport[4];
  176.         glGetIntegerv(GL_VIEWPORT, viewport);
  177.         projection = glm::perspective(45.0f, (float)viewport[2] / viewport[3], 0.1f, 100.0f);
  178.         shader.set_mat4("projection", projection);
  179.  
  180.         // shader.set_float("offset", offset);
  181.         glActiveTexture(GL_TEXTURE0); // set unit zero as the active texture unit, subsequent texture state calls will affect this unit
  182.         glBindTexture(GL_TEXTURE_2D, crate_texture); // crate texture bound as texture unit 0
  183.         glActiveTexture(GL_TEXTURE1);
  184.         glBindTexture(GL_TEXTURE_2D, face_texture);
  185.  
  186.         shader.set_int("crate_texture", 0); // assign units to sampler2D variables in shader
  187.         shader.set_int("face_texture", 1);
  188.         shader.set_float("mix_ratio", mix_ratio);
  189.  
  190.         //glBindTexture(GL_TEXTURE_2D, texture);
  191.         glBindVertexArray(vao);
  192.         for (int i = 0; i < 10; i++) {
  193.             glm::mat4 model = glm::mat4(1.0f);
  194.             model = glm::translate(model, cubePositions[i]);
  195.             float angle = 20.0f * i;
  196.             model = glm::rotate(model, glm::radians(angle) + (float)glfwGetTime(), glm::vec3(1.0f, 0.3f, 0.5f));
  197.             shader.set_mat4("model", model);
  198.             glDrawArrays(GL_TRIANGLES, 0, 36);
  199.         }
  200.  
  201.         // glDrawElements(GL_TRIANGLES, sizeof(indices) / sizeof(indices[0]), GL_UNSIGNED_INT, 0);
  202.  
  203.         glfwSwapBuffers(window);
  204.         glfwPollEvents();
  205.     }
  206.  
  207.     glfwTerminate();
  208.     return 0;
  209. }
  210.  
  211. // NOTE(ACB): Saves texture as same internal format as file format (is this correct?)
  212. GLuint load_texture(const char* filepath, GLenum format)
  213. {
  214.     GLuint texture;
  215.     glGenTextures(1, &texture);
  216.     glBindTexture(GL_TEXTURE_2D, texture);
  217.     // Defaults to GL_REPEAT on S and T axes
  218.     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
  219.     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  220.  
  221.     int width, height, components_per_pixel;
  222.     unsigned char* data = stbi_load(filepath, &width, &height, &components_per_pixel, 0);
  223.     if (data) {
  224.         glTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, format, GL_UNSIGNED_BYTE, data); // texture image, allow image data to be read by shaders, applies to texture currently bound to target (GL_TEXTURE_2D)
  225.         glGenerateMipmap(GL_TEXTURE_2D); // generate mipmap for texture currently bound to GL_TEXTURE_2D target
  226.     } else {
  227.         std::cout << "Failed to load container.jpg." << std::endl;
  228.     }
  229.     stbi_image_free(data);
  230.  
  231.     return texture;
  232. }
  233.  
  234. void process_input(GLFWwindow* window)
  235. {
  236.     if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS) {
  237.         glfwSetWindowShouldClose(window, true);
  238.     }
  239.     if (glfwGetKey(window, GLFW_KEY_UP) == GLFW_PRESS) {
  240.         mix_ratio += 0.001f;
  241.         if (mix_ratio > 1.0f)
  242.             mix_ratio = 1.0f;
  243.     }
  244.     if (glfwGetKey(window, GLFW_KEY_DOWN) == GLFW_PRESS) {
  245.         mix_ratio -= 0.001f;
  246.         if (mix_ratio < 0.0f)
  247.             mix_ratio = 0.0f;
  248.     }
  249.  
  250.     const float camera_speed = 2.5f * delta_time;
  251.     if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS)
  252.         camera_position += camera_speed * camera_front;
  253.     if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS)
  254.         camera_position += camera_speed * glm::normalize(glm::cross(camera_up, camera_front));
  255.     if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS)
  256.         camera_position -= camera_speed * camera_front;
  257.     if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS)
  258.         camera_position -= camera_speed * glm::normalize(glm::cross(camera_up, camera_front));
  259. }
  260.  
  261. void framebuffer_size_callback(GLFWwindow* window, int width, int height)
  262. {
  263.     glViewport(0, 0, width, height);
  264. }
  265.  
  266. // NOTES:
  267. void manually_create_camera_view_matrix() {
  268.     // Manually calculate the camera view matrix. This is done for us using glm::lookAt().
  269.     //
  270.     glm::vec3 camera_position = glm::vec3(0.0f, 0.0f, 3.0f);
  271.     glm::vec3 camera_target = glm::vec3(0.0f, 0.0f, 0.0f);
  272.     glm::vec3 camera_direction = glm::normalize(camera_position - camera_target); // positive z-axis, points from orign to camera location, because OpenGL uses the right-hand coordinate system, the negative z-axis is the direction we are looking in
  273.  
  274.     glm::vec3 up = glm::vec3(0.0f, 1.0f, 0.0f);
  275.     glm::vec3 camera_right = glm::normalize(glm::cross(up, camera_direction)); // positive x-axis
  276.  
  277.     glm::vec3 camera_up = glm::cross(camera_direction, camera_right); // positive y-axis
  278.     //
  279.     // We have created a set of 3 axes for the camera, we can now use these plus a translation vector to transform our vertices to the coordinate space of the camera i.e. relative to the camera, with objects in front with negative z values. This creates a view matrix that we can use. glm::lookAt is a shortcut of this process.
  280. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement