domino-dungeon/main.c
2025-10-15 15:11:47 +02:00

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;
}