From 8d29c1c8ca2bda77d9ef5e971986de62b76b7232 Mon Sep 17 00:00:00 2001 From: lamp Date: Sun, 5 Mar 2023 21:39:53 +0000 Subject: init --- main.c | 223 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 223 insertions(+) create mode 100644 main.c (limited to 'main.c') diff --git a/main.c b/main.c new file mode 100644 index 0000000..dc2c7e3 --- /dev/null +++ b/main.c @@ -0,0 +1,223 @@ +#include +#include + +#include +#include +#include +#include + +#include + +#define RESOLUTION_X 800 +#define RESOLUTION_Y 600 +#define CAMERA_MOVE_SPEED 0.02 +#define CAMERA_ROTATE_SPEED 0.005 + +const char* vertex_shader_source = +"#version 330 core\n" +"layout (location = 0) in vec3 aPos;\n" +"void main() {\n" +"gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);\n" +"}\0"; + +int u_resolution_location; + +double mouse_x = RESOLUTION_X / 2.0; +double mouse_y = RESOLUTION_Y / 2.0; + +typedef struct { + float x; + float y; + float z; +} Vec3; + +Vec3 vec_add(const Vec3 left, const Vec3 right) { + Vec3 result = {left.x + right.x, left.y + right.y, left.z + right.z}; + return result; +} + +Vec3 vec_sub(const Vec3 left, const Vec3 right) { + Vec3 result = {left.x - right.x, left.y - right.y, left.z - right.z}; + return result; +} + +Vec3 vec_mult_by_float(const Vec3 left, float right) { + Vec3 result = {left.x * right, left.y * right, left.z * right}; + return result; +} + +Vec3 vec_cross(const Vec3 left, const Vec3 right) { + Vec3 result = {left.y * right.z - left.z * right.y, left.z * right.x - left.x * right.z, left.x * right.y - left.y * right.x}; + return result; +} + +Vec3 vec_normalize(const Vec3 left) { + float length = sqrtf(left.x * left.x + left.y * left.y + left.z * left.z); + Vec3 result = {left.x / length, left.y / length, left.z / length}; + return result; +} + +typedef struct { + Vec3 position; + Vec3 look_at; + Vec3 vup; +} Camera; + +Camera camera = {{0.0, 0.0, 0.0}, {0.0, 0.0, -1.0}, {0.0, 1.0, 0.0}}; + +void on_resize(GLFWwindow* window, int width, int height) { + glViewport(0, 0, width, height); + glUniform2f(u_resolution_location, width, height); +} + +void on_mouse_event(GLFWwindow* window, double x_position, double y_position) { + double delta_x = x_position - mouse_x; + double delta_y = mouse_y - y_position; + mouse_x = x_position; + mouse_y = y_position; + camera.look_at = vec_normalize(vec_add(camera.look_at, vec_mult_by_float(vec_cross(camera.look_at, camera.vup), (delta_x * CAMERA_ROTATE_SPEED)))); + camera.look_at = vec_normalize(vec_add(camera.look_at, vec_mult_by_float(camera.vup, (delta_y * CAMERA_ROTATE_SPEED)))); +} + +int main(void) { + glfwInit(); + glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4); + glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1); + glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); +#ifdef __APPLE__ + glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); +#endif + + GLFWwindow* window = glfwCreateWindow(RESOLUTION_X, RESOLUTION_Y, "OpenGL", NULL, NULL); + if (window == NULL) { + fprintf(stderr, "Failed to create GLFW window.\n"); + glfwTerminate(); + return 1; + } + glfwMakeContextCurrent(window); + glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED); + + if (gladLoadGL(glfwGetProcAddress) == 0) { + fprintf(stderr, "Failed to initialise OpenGL context.\n"); + glfwTerminate(); + return 1; + } + + glViewport(0, 0, RESOLUTION_X, RESOLUTION_Y); + glfwSetFramebufferSizeCallback(window, on_resize); + glfwSetCursorPosCallback(window, on_mouse_event); + + int success; + unsigned int vertex_shader = glCreateShader(GL_VERTEX_SHADER); + glShaderSource(vertex_shader, 1, &vertex_shader_source, NULL); + glCompileShader(vertex_shader); + glGetShaderiv(vertex_shader, GL_COMPILE_STATUS, &success); + if (!success) { + char info_log[512]; + glGetShaderInfoLog(vertex_shader, 512, NULL, info_log); + fprintf(stderr, "Vertex shader compilation failed: %s", info_log); + glfwTerminate(); + return 1; + } + + unsigned int frag_shader = glCreateShader(GL_FRAGMENT_SHADER); + glShaderSource(frag_shader, 1, &rt_frag_shader_source, NULL); + glCompileShader(frag_shader); + glGetShaderiv(frag_shader, GL_COMPILE_STATUS, &success); + if (!success) { + char info_log[512]; + glGetShaderInfoLog(frag_shader, 512, NULL, info_log); + fprintf(stderr, "Fragment shader compilation failed: %s", info_log); + glfwTerminate(); + return 1; + } + + unsigned int program = glCreateProgram(); + glAttachShader(program, vertex_shader); + glAttachShader(program, frag_shader); + glLinkProgram(program); + glGetProgramiv(program, GL_LINK_STATUS, &success); + if (!success) { + char info_log[512]; + glGetProgramInfoLog(program, 512, NULL, info_log); + fprintf(stderr, "Program linking failed: %s", info_log); + glfwTerminate(); + return 1; + } + // Pull uniforms into variables here. + u_resolution_location = glGetUniformLocation(program, "u_resolution"); + int u_time_location = glGetUniformLocation(program, "u_time"); + int u_camera_location_location = glGetUniformLocation(program, "u_camera_location"); + int u_camera_lookat_location = glGetUniformLocation(program, "u_camera_lookat"); + int u_camera_vup_location = glGetUniformLocation(program, "u_camera_vup"); + glUseProgram(program); + // Define uniforms here. + glUniform2f(u_resolution_location, RESOLUTION_X, RESOLUTION_Y); + glUniform1f(u_time_location, 0.0); + glUniform3f(u_camera_location_location, camera.position.x, camera.position.y, camera.position.z); + Vec3 worldspace_look_at = vec_add(camera.position, camera.look_at); + glUniform3f(u_camera_lookat_location, worldspace_look_at.x, worldspace_look_at.y, worldspace_look_at.z); + glUniform3f(u_camera_vup_location, camera.vup.x, camera.vup.y, camera.vup.z); + glDeleteShader(vertex_shader); + glDeleteShader(frag_shader); + + float rect_vertices[] = { + 1.0, 1.0, 0.0, + 1.0, -1.0, 0.0, + -1.0, -1.0, 0.0, + -1.0, 1.0, 0.0, + }; + + unsigned int triangle_draw_indices[] = { + 0, 1, 3, + 1, 2, 3 + }; + + unsigned int vbo, vao, ebo; + glGenVertexArrays(1, &vao); + glGenBuffers(1, &vbo); + glGenBuffers(1, &ebo); + glBindVertexArray(vao); + glBindBuffer(GL_ARRAY_BUFFER, vbo); + glBufferData(GL_ARRAY_BUFFER, sizeof(rect_vertices), rect_vertices, GL_STATIC_DRAW); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(triangle_draw_indices), triangle_draw_indices, GL_STATIC_DRAW); + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0); + glEnableVertexAttribArray(0); + glBindBuffer(GL_ARRAY_BUFFER, 0); + + while (!glfwWindowShouldClose(window)) { + if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS) { + glfwSetWindowShouldClose(window, true); + } + if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS) { + camera.position = vec_add(camera.position, vec_mult_by_float(camera.look_at, CAMERA_MOVE_SPEED)); + glUniform3f(u_camera_location_location, camera.position.x, camera.position.y, camera.position.z); + } + if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS) { + camera.position = vec_sub(camera.position, vec_mult_by_float(camera.look_at, CAMERA_MOVE_SPEED)); + glUniform3f(u_camera_location_location, camera.position.x, camera.position.y, camera.position.z); + } + if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS) { + camera.position = vec_sub(camera.position, vec_mult_by_float(vec_normalize(vec_cross(camera.look_at, camera.vup)), CAMERA_MOVE_SPEED)); + glUniform3f(u_camera_location_location, camera.position.x, camera.position.y, camera.position.z); + } + if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS) { + camera.position = vec_add(camera.position, vec_mult_by_float(vec_normalize(vec_cross(camera.look_at, camera.vup)), CAMERA_MOVE_SPEED)); + glUniform3f(u_camera_location_location, camera.position.x, camera.position.y, camera.position.z); + } + Vec3 worldspace_look_at = vec_add(camera.position, camera.look_at); + glUniform3f(u_camera_lookat_location, worldspace_look_at.x, worldspace_look_at.y, worldspace_look_at.z); + glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0); + glUniform1f(u_time_location, glfwGetTime()); + glfwSwapBuffers(window); + glfwPollEvents(); + } + + glDeleteVertexArrays(1, &vao); + glDeleteBuffers(1, &vbo); + glDeleteBuffers(1, &ebo); + glDeleteProgram(program); + glfwTerminate(); + return 0; +} \ No newline at end of file -- cgit v1.2.3