268 lines
7.7 KiB
C
268 lines
7.7 KiB
C
#include <stdint.h>
|
|
#include <stdio.h>
|
|
|
|
#include <glad/glad.h>
|
|
#include <GLFW/glfw3.h>
|
|
#include <math.h>
|
|
|
|
#ifdef __EMSCRIPTEN__
|
|
#include <emscripten.h>
|
|
#endif
|
|
|
|
#include "game.h"
|
|
|
|
unsigned int SCR_WIDTH = 800;
|
|
unsigned int SCR_HEIGHT = 600;
|
|
|
|
GLFWwindow* window;
|
|
unsigned int texture;
|
|
GLuint shader_program;
|
|
unsigned int VAO;
|
|
|
|
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 init(struct image canvas);
|
|
extern void render(struct image canvas);
|
|
|
|
uint32_t buffer[256 * 240] = {0};
|
|
|
|
struct image canvas = {
|
|
.width = 256,
|
|
.height = 240,
|
|
.bufsize = 256 * 240,
|
|
.buf = buffer,
|
|
};
|
|
|
|
const char *vertex_shader_source =
|
|
"#version 300 es\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 300 es\n"
|
|
"precision mediump float;\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);
|
|
}
|
|
|
|
void loop() {
|
|
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);
|
|
|
|
render(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_RGBA, 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();
|
|
}
|
|
|
|
int main() {
|
|
|
|
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
|
|
|
|
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;
|
|
}
|
|
|
|
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, 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);
|
|
|
|
// 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);
|
|
|
|
init(canvas);
|
|
|
|
#ifdef __EMSCRIPTEN__
|
|
emscripten_set_main_loop(loop, 0, true);
|
|
#else
|
|
while (!glfwWindowShouldClose(window))
|
|
loop();
|
|
#endif
|
|
|
|
glfwTerminate();
|
|
|
|
return 0;
|
|
}
|