#include #include #include #include #include #include #include "game.h" unsigned int SCR_WIDTH = 800; unsigned int SCR_HEIGHT = 600; extern void key_callback(int key, int scancode, int action, int mods); extern void cursor_position_callback(int xpos, int ypos); extern void mouse_button_callback(int button, int action, int mods); extern void draw_image(decoded_image img); 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 framebuffer_size_callback(GLFWwindow* window, int width, int height) { (void) window; glViewport(0, 0, width, height); SCR_WIDTH = width; SCR_HEIGHT = height; } void glfw_key_callback(GLFWwindow* window, int key, int scancode, int action, int mods) { (void) window; key_callback(key, scancode, action, mods); } void glfw_cursor_position_callback(GLFWwindow* window, double xpos, double ypos) { (void) window; 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 ); cursor_position_callback( ((xpos - (SCR_WIDTH - scale_x * SCR_WIDTH )/2) / (scale_x * SCR_WIDTH)) * canvas.width, ((ypos - (SCR_HEIGHT - scale_y * SCR_HEIGHT)/2) / (scale_y * SCR_HEIGHT)) * canvas.height ); } void glfw_mouse_button_callback(GLFWwindow* window, int button, int action, int mods) { (void) window; mouse_button_callback(button, action, mods); } int main() { canvas.buf = malloc(canvas.buf_size * sizeof(int)); 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); glfwSetKeyCallback(window, glfw_key_callback); glfwSetCursorPosCallback(window, glfw_cursor_position_callback); glfwSetMouseButtonCallback(window, glfw_mouse_button_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); draw_image(canvas); // 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; }