diff options
Diffstat (limited to 'main.c')
| -rw-r--r-- | main.c | 232 |
1 files changed, 232 insertions, 0 deletions
@@ -0,0 +1,232 @@ +#include <stdint.h> +#include <stdio.h> +#include <spng.h> + +#include <glad/glad.h> +#include <GLFW/glfw3.h> +#include <math.h> + +unsigned int SCR_WIDTH = 800; +unsigned int SCR_HEIGHT = 600; + +typedef struct decoded_image { + size_t width; + size_t height; + uint32_t *buf; + ssize_t buf_size; +} decoded_image; + +struct decoded_image canvas = { + .width = 256, + .height = 240, + .buf_size = 256 * 240, +}; + +const char *vertex_shader_source = + "#version 330 core\n" + "layout (location = 0) in vec3 aPos;\n" + "layout (location = 1) in vec3 aColor;\n" + "layout (location = 2) in vec2 aTexCoord;\n" + "\n" + "out vec3 ourColor;\n" + "out vec2 TexCoord;\n" + "\n" + "uniform mat4 transform;" + "\n" + "void main() {\n" + " gl_Position = transform * vec4(aPos, 1.0);\n" + " ourColor = aColor;\n" + " TexCoord = vec2(aTexCoord.x, 1.0 - aTexCoord.y);\n" + "}\n"; + +const char *fragment_shader_source = + "#version 330 core\n" + "out vec4 FragColor;\n" + "\n" + "in vec3 ourColor;\n" + "in vec2 TexCoord;\n" + "\n" + "uniform sampler2D texture1;\n" + "\n" + "void main() {\n" + " FragColor = texture(texture1, TexCoord);\n" + "}\n"; + +void character_callback(GLFWwindow* window, unsigned int codepoint) { + printf("%c\n", codepoint); +} + +void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods) { + if (action != GLFW_PRESS) return; + switch (key) { + case GLFW_KEY_ENTER: + break; + case GLFW_KEY_BACKSPACE: + break; + } +} + +void framebuffer_size_callback(GLFWwindow* window, int width, int height) { + glViewport(0, 0, width, height); + SCR_WIDTH = width; + SCR_HEIGHT = height; +} + +const uint32_t COLOR_RGBA = 0xFF21FF00; + +int main(int argc, const char *argv[]) { + + canvas.buf = malloc(canvas.buf_size * sizeof(int)); + for (int i = 0; i < canvas.buf_size; i++) canvas.buf[i] = i; + + glfwInit(); + glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); + glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); + glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); + +#ifdef __APPLE__ + glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); +#endif + + GLFWwindow* window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, "202-anything", NULL, NULL); + if (window == NULL) { + printf("Failed to create GLFW window\n"); + glfwTerminate(); + return -1; + } + glfwMakeContextCurrent(window); + glfwSetFramebufferSizeCallback(window, framebuffer_size_callback); + glfwSetCharCallback(window, character_callback); + glfwSetKeyCallback(window, key_callback); + + if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) { + printf("Failed to initialize GLAD\n"); + return -1; + } + + GLint success; + GLuint vertex_shader = glCreateShader(GL_VERTEX_SHADER); + glShaderSource(vertex_shader, 1, (const char **)&vertex_shader_source, NULL); + glCompileShader(vertex_shader); + glGetShaderiv(vertex_shader, GL_COMPILE_STATUS, &success); + + if(success == GL_FALSE) { + char infoLog[512]; + glGetShaderInfoLog(vertex_shader, 512, NULL, infoLog); + fprintf(stderr, "Shader compilation error: %s\n", infoLog); + glDeleteShader(vertex_shader); + return 1; + } + + GLuint fragment_shader = glCreateShader(GL_FRAGMENT_SHADER); + glShaderSource(fragment_shader, 1, (const char **)&fragment_shader_source, NULL); + glCompileShader(fragment_shader); + glGetShaderiv(fragment_shader, GL_COMPILE_STATUS, &success); + + if(success == GL_FALSE) { + char infoLog[512]; + glGetShaderInfoLog(fragment_shader, 512, NULL, infoLog); + fprintf(stderr, "Shader compilation error: %s\n", infoLog); + glDeleteShader(fragment_shader); + return 1; + } + + GLuint shader_program = glCreateProgram(); + glAttachShader(shader_program, vertex_shader); + glAttachShader(shader_program, fragment_shader); + glLinkProgram(shader_program); + + float vertices[] = { + // positions // colors // texture coords + 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, // top right + 0.5f, -0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, // bottom right + -0.5f, -0.5f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, // bottom left + -0.5f, 0.5f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f // top left + }; + unsigned int indices[] = { + 0, 1, 3, // first triangle + 1, 2, 3 // second triangle + }; + 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(vertices), vertices, GL_STATIC_DRAW); + + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW); + + // position attribute + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)0); + glEnableVertexAttribArray(0); + // color attribute + glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(3 * sizeof(float))); + glEnableVertexAttribArray(1); + // texture coord attribute + glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(6 * sizeof(float))); + glEnableVertexAttribArray(2); + + unsigned int texture; + // texture 1 + // --------- + glGenTextures(1, &texture); + glBindTexture(GL_TEXTURE_2D, texture); + // set the texture wrapping parameters + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + // set texture filtering parameters + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, canvas.width, canvas.height, 0, GL_RGBA, GL_UNSIGNED_BYTE, canvas.buf); + + glUseProgram(shader_program); + glUniform1i(glGetUniformLocation(shader_program, "texture1"), 0); + + while (!glfwWindowShouldClose(window)) { + if(glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS) + glfwSetWindowShouldClose(window, 1); + + glClearColor(0.2f, 0.3f, 0.3f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT); + + // bind textures on corresponding texture units + glActiveTexture(GL_TEXTURE); + glBindTexture(GL_TEXTURE_2D, texture); + + float scale_x = fmin( + (float) SCR_HEIGHT / SCR_WIDTH * (float) canvas.height / canvas.width, + 1.0 + ); + float scale_y = fmin((float) SCR_WIDTH / SCR_HEIGHT * (float) canvas.width / canvas.height, + 1.0 + ); + + float m[] = { + 2.0 * scale_x, 0.0, 0.0, 0.0, + 0.0, 2.0 * scale_y, 0.0, 0.0, + 0.0, 0.0, 1.0, 0.0, + 0.0, 0.0, 0.0, 1.0, + }; + + // render container + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, canvas.width, canvas.height, 0, GL_RGBA, GL_UNSIGNED_BYTE, canvas.buf); + glUseProgram(shader_program); + glUniform1i(glGetUniformLocation(shader_program, "texture1"), 0); + glUniformMatrix4fv(glGetUniformLocation(shader_program, "transform"), 1, GL_FALSE, m); + + glBindVertexArray(VAO); + glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0); + + glfwSwapBuffers(window); + glfwPollEvents(); + } + + glfwTerminate(); + + return 0; +} |
