Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include "shader.h"
- #include <glad/glad.h>
- #include <GLFW/glfw3.h>
- #define STB_IMAGE_IMPLEMENTATION
- #include "stb_image.h"
- #include <glm/glm.hpp>
- #include <glm/gtc/matrix_transform.hpp>
- #include <iostream>
- #include <cmath>
- void framebuffer_size_callback(GLFWwindow* window, int width, int height);
- GLuint load_texture(const char* filepath, GLenum format);
- void process_input(GLFWwindow* window);
- const unsigned int SCREEN_WIDTH = 800;
- const unsigned int SCREEN_HEIGHT = 600;
- float mix_ratio = 0.2f;
- glm::vec3 camera_position = glm::vec3(0.0f, 0.0f, 3.0f);
- glm::vec3 camera_front = glm::vec3(0.0f, 0.0f, -1.0f);
- glm::vec3 camera_up = glm::vec3(0.0f, 1.0f, 0.0f);
- float delta_time;
- float last_frame_time;
- int main()
- {
- glfwInit();
- glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
- glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
- glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
- glfwWindowHint(GLFW_SCALE_TO_MONITOR, GLFW_TRUE);
- #ifdef __APPLE__
- glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
- #endif
- GLFWwindow* window = glfwCreateWindow(800, 600, "LearnOpenGL", NULL, NULL);
- if (window == NULL) {
- std::cout << "Failed to create GLFW window." << std::endl;
- glfwTerminate();
- return -1;
- }
- glfwMakeContextCurrent(window);
- glfwSetFramebufferSizeCallback(window, framebuffer_size_callback); // called when framebuffer of window is resized
- if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) {
- std::cout << "Failed to initialize GLAD." << std::endl;
- return -1;
- }
- glEnable(GL_DEPTH_TEST);
- stbi_set_flip_vertically_on_load(true); // usually top left is (0, 0) but OpenGL expects bottom left to be (0, 0)
- GLuint crate_texture = load_texture("container.jpg", GL_RGB);
- GLuint face_texture = load_texture("awesomeface.png", GL_RGBA);
- float vertices[] = {
- // positions // texture coords
- -0.5f, -0.5f, -0.5f, 0.0f, 0.0f,
- 0.5f, -0.5f, -0.5f, 1.0f, 0.0f,
- 0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
- 0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
- -0.5f, 0.5f, -0.5f, 0.0f, 1.0f,
- -0.5f, -0.5f, -0.5f, 0.0f, 0.0f,
- -0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
- 0.5f, -0.5f, 0.5f, 1.0f, 0.0f,
- 0.5f, 0.5f, 0.5f, 1.0f, 1.0f,
- 0.5f, 0.5f, 0.5f, 1.0f, 1.0f,
- -0.5f, 0.5f, 0.5f, 0.0f, 1.0f,
- -0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
- -0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
- -0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
- -0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
- -0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
- -0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
- -0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
- 0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
- 0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
- 0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
- 0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
- 0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
- 0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
- -0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
- 0.5f, -0.5f, -0.5f, 1.0f, 1.0f,
- 0.5f, -0.5f, 0.5f, 1.0f, 0.0f,
- 0.5f, -0.5f, 0.5f, 1.0f, 0.0f,
- -0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
- -0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
- -0.5f, 0.5f, -0.5f, 0.0f, 1.0f,
- 0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
- 0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
- 0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
- -0.5f, 0.5f, 0.5f, 0.0f, 0.0f,
- -0.5f, 0.5f, -0.5f, 0.0f, 1.0f
- };
- GLuint vao, vbo, ebo;
- glGenVertexArrays(1, &vao); // create a vertex array object, an array of attribute pointers telling OpenGL how to interpret our data
- glGenBuffers(1, &vbo); // create a buffer on the GPU and get its id
- //glGenBuffers(1, &ebo);
- // Bind VAO. Typically each mesh corresponds to a VAO.
- glBindVertexArray(vao); // VBOs and EBOs that are bound while the VAO is bound will be linked to it
- // Bind VBO, upload data to it, and configure vertex attributes.
- 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
- glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); // copies vertex data into the currently bound GL_ARRAY_BUFFER
- 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
- glEnableVertexAttribArray(0); // enable vertex attribute of currently bound VAO with name 0
- glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(3 * sizeof(float)));
- glEnableVertexAttribArray(1);
- /*
- // Bind EBO and upload data to it.
- 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
- glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
- */
- // VAO is bound while VBO and EBO are bound, and attributes set, all state is now contained within the VAO.
- // 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
- glBindVertexArray(0); // unbind VAO so other VAO calls won't accidentally modify this VAO
- // 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
- // We will bind another VBO or VAO before making changes to them, so explicitly unbinding them is typically not necessary.
- Shader shader("shader.vert", "shader.frag");
- shader.use();
- glm::vec3 cubePositions[] = {
- glm::vec3(0.0f, 0.0f, 0.0f),
- glm::vec3(2.0f, 5.0f, -15.0f),
- glm::vec3(-1.5f, -2.2f, -2.5f),
- glm::vec3(-3.8f, -2.0f, -12.3f),
- glm::vec3(2.4f, -0.4f, -3.5f),
- glm::vec3(-1.7f, 3.0f, -7.5f),
- glm::vec3(1.3f, -2.0f, -2.5f),
- glm::vec3(1.5f, 2.0f, -2.5f),
- glm::vec3(1.5f, 0.2f, -1.5f),
- glm::vec3(-1.3f, 1.0f, -1.5f)
- };
- while (!glfwWindowShouldClose(window)) {
- float current_frame_time = glfwGetTime();
- delta_time = current_frame_time - last_frame_time;
- last_frame_time = current_frame_time;
- process_input(window);
- glClearColor(0.2f, 0.3f, 0.3f, 1.0f); // specify clear values for the color buffers
- 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
- shader.use();
- glm::mat4 model = glm::mat4(1.0f);
- model = glm::rotate(model, (float)glfwGetTime() * glm::radians(50.0f), glm::vec3(0.5f, 1.0f, 0.0f));
- shader.set_mat4("model", model);
- const float radius = 10.0f;
- float camX = sin(glfwGetTime()) * radius;
- float camZ = cos(glfwGetTime()) * radius;
- glm::mat4 view;
- view = glm::lookAt(camera_position, camera_position + camera_front, camera_up);
- shader.set_mat4("view", view);
- glm::mat4 projection;
- int viewport[4];
- glGetIntegerv(GL_VIEWPORT, viewport);
- projection = glm::perspective(45.0f, (float)viewport[2] / viewport[3], 0.1f, 100.0f);
- shader.set_mat4("projection", projection);
- // shader.set_float("offset", offset);
- glActiveTexture(GL_TEXTURE0); // set unit zero as the active texture unit, subsequent texture state calls will affect this unit
- glBindTexture(GL_TEXTURE_2D, crate_texture); // crate texture bound as texture unit 0
- glActiveTexture(GL_TEXTURE1);
- glBindTexture(GL_TEXTURE_2D, face_texture);
- shader.set_int("crate_texture", 0); // assign units to sampler2D variables in shader
- shader.set_int("face_texture", 1);
- shader.set_float("mix_ratio", mix_ratio);
- //glBindTexture(GL_TEXTURE_2D, texture);
- glBindVertexArray(vao);
- for (int i = 0; i < 10; i++) {
- glm::mat4 model = glm::mat4(1.0f);
- model = glm::translate(model, cubePositions[i]);
- float angle = 20.0f * i;
- model = glm::rotate(model, glm::radians(angle) + (float)glfwGetTime(), glm::vec3(1.0f, 0.3f, 0.5f));
- shader.set_mat4("model", model);
- glDrawArrays(GL_TRIANGLES, 0, 36);
- }
- // glDrawElements(GL_TRIANGLES, sizeof(indices) / sizeof(indices[0]), GL_UNSIGNED_INT, 0);
- glfwSwapBuffers(window);
- glfwPollEvents();
- }
- glfwTerminate();
- return 0;
- }
- // NOTE(ACB): Saves texture as same internal format as file format (is this correct?)
- GLuint load_texture(const char* filepath, GLenum format)
- {
- GLuint texture;
- glGenTextures(1, &texture);
- glBindTexture(GL_TEXTURE_2D, texture);
- // Defaults to GL_REPEAT on S and T axes
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- int width, height, components_per_pixel;
- unsigned char* data = stbi_load(filepath, &width, &height, &components_per_pixel, 0);
- if (data) {
- 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)
- glGenerateMipmap(GL_TEXTURE_2D); // generate mipmap for texture currently bound to GL_TEXTURE_2D target
- } else {
- std::cout << "Failed to load container.jpg." << std::endl;
- }
- stbi_image_free(data);
- return texture;
- }
- void process_input(GLFWwindow* window)
- {
- if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS) {
- glfwSetWindowShouldClose(window, true);
- }
- if (glfwGetKey(window, GLFW_KEY_UP) == GLFW_PRESS) {
- mix_ratio += 0.001f;
- if (mix_ratio > 1.0f)
- mix_ratio = 1.0f;
- }
- if (glfwGetKey(window, GLFW_KEY_DOWN) == GLFW_PRESS) {
- mix_ratio -= 0.001f;
- if (mix_ratio < 0.0f)
- mix_ratio = 0.0f;
- }
- const float camera_speed = 2.5f * delta_time;
- if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS)
- camera_position += camera_speed * camera_front;
- if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS)
- camera_position += camera_speed * glm::normalize(glm::cross(camera_up, camera_front));
- if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS)
- camera_position -= camera_speed * camera_front;
- if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS)
- camera_position -= camera_speed * glm::normalize(glm::cross(camera_up, camera_front));
- }
- void framebuffer_size_callback(GLFWwindow* window, int width, int height)
- {
- glViewport(0, 0, width, height);
- }
- // NOTES:
- void manually_create_camera_view_matrix() {
- // Manually calculate the camera view matrix. This is done for us using glm::lookAt().
- //
- glm::vec3 camera_position = glm::vec3(0.0f, 0.0f, 3.0f);
- glm::vec3 camera_target = glm::vec3(0.0f, 0.0f, 0.0f);
- 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
- glm::vec3 up = glm::vec3(0.0f, 1.0f, 0.0f);
- glm::vec3 camera_right = glm::normalize(glm::cross(up, camera_direction)); // positive x-axis
- glm::vec3 camera_up = glm::cross(camera_direction, camera_right); // positive y-axis
- //
- // 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.
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement