diff options
author | Schark <jordan@schark.online> | 2024-03-06 02:00:59 -0800 |
---|---|---|
committer | Schark <jordan@schark.online> | 2024-03-06 02:00:59 -0800 |
commit | c356e96932b5d1a23bf41914934cf83e8b535994 (patch) | |
tree | 9ee15f23c0ae584443d8af63b473d5c2eee094ba /src/main.c | |
parent | ce811be0799bfee8355aa56d3ab566fb5b5dab55 (diff) | |
download | gamedev-c356e96932b5d1a23bf41914934cf83e8b535994.tar.gz gamedev-c356e96932b5d1a23bf41914934cf83e8b535994.zip |
Working barebones heightmap renderer
Diffstat (limited to 'src/main.c')
-rw-r--r-- | src/main.c | 285 |
1 files changed, 0 insertions, 285 deletions
diff --git a/src/main.c b/src/main.c deleted file mode 100644 index cbe13d8..0000000 --- a/src/main.c +++ /dev/null @@ -1,285 +0,0 @@ -#include <GL/glew.h> // must come before glfw3 -#include <GLFW/glfw3.h> -#include <stdio.h> -#include <math.h> - -#include "player.h" - -// TODO: move to implicit map definition with level editor in future -#define MAP_HEIGHT 20 -#define MAP_WIDTH 10 -int world_map[MAP_HEIGHT][MAP_WIDTH] = { - {1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, - {1, 0, 0, 0, 0, 0, 0, 0, 0, 1}, - {1, 0, 2, 2, 2, 0, 0, 0, 0, 1}, - {1, 0, 2, 2, 2, 0, 0, 0, 0, 1}, - {1, 0, 2, 2, 2, 0, 0, 0, 0, 1}, - {1, 0, 2, 2, 2, 0, 0, 0, 0, 1}, - {1, 0, 2, 2, 2, 0, 4, 4, 0, 1}, - {1, 0, 0, 0, 0, 0, 4, 4, 0, 1}, - {1, 0, 0, 0, 0, 0, 4, 4, 0, 1}, - {1, 0, 0, 0, 0, 0, 4, 4, 0, 1}, - {1, 0, 0, 0, 0, 0, 4, 4, 0, 1}, - {1, 0, 0, 0, 0, 0, 4, 4, 0, 1}, - {1, 0, 0, 0, 0, 0, 4, 4, 0, 1}, - {1, 0, 3, 3, 3, 0, 4, 4, 0, 1}, - {1, 0, 3, 3, 3, 0, 0, 0, 0, 1}, - {1, 0, 3, 3, 3, 0, 0, 0, 0, 1}, - {1, 0, 3, 3, 3, 0, 0, 0, 0, 1}, - {1, 0, 3, 3, 3, 0, 0, 0, 0, 1}, - {1, 0, 0, 0, 0, 0, 0, 0, 0, 1}, - {1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, -}; - -typedef struct { - unsigned char r, g, b; -} ColorRGB; - -// honest- this function can from chatgpt- cross-reference this with other raycasting guides -void raycast(Player *player, GLubyte *pixels, int width, int height) { - int screen_width = width; - int screen_height = height; - - for (int x = 0; x < screen_width; ++x) { - // Calculate ray position and direction - double camera_x = 2.0 * x / (double)screen_width - 1; // x-coordinate in camera space - double ray_dir_x = player->dir_x + player->plane_x * camera_x; - double ray_dir_y = player->dir_y + player->plane_y * camera_x; - - // Which box of the map we're in - int map_x = (int)player->pos_x; - int map_y = (int)player->pos_y; - - // Length of ray from one x or y-side to next x or y-side - double delta_dist_x = fabs(1 / ray_dir_x); - double delta_dist_y = fabs(1 / ray_dir_y); - - // Length of ray from current position to next x or y-side - double side_dist_x; - double side_dist_y; - - // Direction to step in x or y-direction (either +1 or -1) - int step_x; - int step_y; - - // Was a wall hit? - int hit = 0; - // Was the wall hit a wall facing north, east-west, or south? - int side; - if (ray_dir_x < 0) { - step_x = -1; - side_dist_x = (player->pos_x - map_x) * delta_dist_x; - } else { - step_x = 1; - side_dist_x = (map_x + 1.0 - player->pos_x) * delta_dist_x; - } - if (ray_dir_y < 0) { - step_y = -1; - side_dist_y = (player->pos_y - map_y) * delta_dist_y; - } else { - step_y = 1; - side_dist_y = (map_y + 1.0 - player->pos_y) * delta_dist_y; - } - - // Perform DDA - while (hit == 0) { - // Jump to next map square - if (side_dist_x < side_dist_y) { - side_dist_x += delta_dist_x; - map_x += step_x; - side = (ray_dir_x > 0) ? 0 : 2; - } else { - side_dist_y += delta_dist_y; - map_y += step_y; - side = 1; - } - // Check if ray has hit a wall - if (world_map[map_x][map_y] > 0) { hit = 1; } - } - - // calculate distance projected on camera direction - double perp_wall_dist; - if (side == 0 || side == 2) { perp_wall_dist = (map_x - player->pos_x + (1 - step_x) / 2) / ray_dir_x; } - else { perp_wall_dist = (map_y - player->pos_y + (1 - step_y) / 2) / ray_dir_y; } - - // fog effect - float fog_distance = 15.0f; - float scale_factor = 1.0f - perp_wall_dist / fog_distance; - if (scale_factor < 0.0f) { scale_factor = 0.0f; } - - // calculate height of line on screen - int line_height = (int)(screen_height / perp_wall_dist); - //int draw_start = -line_height / 2 + screen_height / 2; - //if (draw_start < 0) { draw_start = 0; } - //int draw_end = line_height / 2 + screen_height / 2; - //if (draw_end >= screen_height) { draw_end = screen_height - 1; } - int pitch = screen_height / 2 * player->look_angle; - int start_y = -line_height / 2 + screen_height / 2 + pitch; - if (start_y < 0) { start_y = 0; } - int end_y = line_height / 2 + screen_height / 2 + pitch; - if (end_y >= screen_height) { end_y = screen_height - 1; } - - - // colors :) - ColorRGB color; - if (world_map[map_x][map_y] == 1) color = (ColorRGB){.r = 255, .g = 255, .b = 255}; - else if (world_map[map_x][map_y] == 2) color = (ColorRGB){.r = 255, .g = 0, .b = 0}; - else if (world_map[map_x][map_y] == 3) color = (ColorRGB){.r = 0, .g = 255, .b = 0}; - else if (world_map[map_x][map_y] == 4) color = (ColorRGB){.r = 0, .g = 0, .b = 255}; - else color = (ColorRGB){.r = 0, .g = 0, .b = 0}; - - if (side == 1) { - color.r /= 2; - color.g /= 2; - color.b /= 2; - } else if (side == 2) { - color.r /= 4; - color.g /= 4; - color.b /= 4; - } - - // scale brightness in accordance with distance (for fog) - color.r *= scale_factor; - color.g *= scale_factor; - color.b *= scale_factor; - - int index; - for (int y = 0; y < screen_height; y++) { - index = y * screen_width * 3 + x * 3; - if (y >= start_y && y <= end_y) { - // draw something - pixels[index] = color.r; - pixels[index+1] = color.g; - pixels[index+2] = color.b; - } else { - // fill blank space - pixels[index] = 0; - pixels[index+1] = 0; - pixels[index+2] = 0; - } - } - - } -} - -int main(int argc, char *argv[]) { - GLFWwindow* window; - - double mouse_x; - double mouse_y; - - // init player - Player player; - player.pos_y = 2.0f; - player.pos_x = 9.0f; - player.dir_x = 1.0f; - player.dir_y = 0.0f; - player.plane_x = 0.20f; // FOV related - player.plane_y = 0.90f; // FOV related - player.look_angle = 0.0f; - player.move_speed = 0.035f; - player.sensitivity = 0.001f; - - // initiate glfw library - if (!glfwInit()){ - printf("Failed to initiate GLFW.\n"); - return -1; - } - - // create glfw window - GLFWmonitor* primary = glfwGetPrimaryMonitor(); - const GLFWvidmode* mode = glfwGetVideoMode(primary); - //window = glfwCreateWindow(800, 600, "raycaster", NULL, NULL); - window = glfwCreateWindow(mode->width, mode->height, "raycaster", primary, NULL); - if (!window){ - printf("Failed to create GLFW window.\n"); - glfwTerminate(); - return -1; - } - - // make window current - glfwMakeContextCurrent(window); - glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED); - - // update mouse position - // glfwGetCursorPos(window, &mouse_x, &mouse_y); - mouse_x -= mode->width / 2; - mouse_y -= mode->height / 2; - - // setup orthographic projection camera - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - glOrtho(0.0, mode->width, mode->height, 0.0, -1.0, 1.0); - glMatrixMode(GL_MODELVIEW); - - // TODO: move timers into a header - double last_time = glfwGetTime(); - int nb_frames = 0; - // TODO: render FPS with freetype or something as opposed to updating title - char title[200]; - - // setup pbo for optimized performance - if (glewInit() != GLEW_OK) { - printf("Failed to initiate GLEW.\n"); - return -1; - } - GLuint pbo = 0; - - glGenBuffers(1, &pbo); - glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo); - glBufferData(GL_PIXEL_UNPACK_BUFFER, mode->width * mode->height * 3, 0, GL_STREAM_DRAW); - - int index = 0; - glViewport(0, 0, mode->width, mode->height); - while (!glfwWindowShouldClose(window)) { - - // Stop loop if window isn't focused - if(!glfwGetWindowAttrib(window, GLFW_FOCUSED)){ - continue; - } - - // timing section - double current_time = glfwGetTime(); - nb_frames++; - if (current_time - last_time >= 1.0) { - sprintf(title, "FPS: %d", nb_frames); - glfwSetWindowTitle(window, title); - nb_frames = 0; - last_time += 1.0; - } - - - // clear window - glClear(GL_COLOR_BUFFER_BIT); - glLoadIdentity(); - - // main raycast function - float prev_position[2] = {player.pos_x, player.pos_y}; - move_player(&player, window, &mouse_x, &mouse_y, mode->width, mode->height); - if (world_map[(int)player.pos_x][(int)player.pos_y] != 0) { - player.pos_x = prev_position[0]; - player.pos_y = prev_position[1]; - } - GLubyte* pixels = (GLubyte*)glMapBuffer(GL_PIXEL_UNPACK_BUFFER, GL_WRITE_ONLY); - raycast(&player, pixels, mode->width, mode->height); - - // pbo - glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER); - glPixelStorei(GL_UNPACK_ALIGNMENT, 1); - glPixelStorei(GL_UNPACK_ROW_LENGTH, mode->width); - glWindowPos2i(0, 0); - glDrawPixels(mode->width, mode->height, GL_RGB, GL_UNSIGNED_BYTE, 0); - - - glfwSwapBuffers(window); - glfwPollEvents(); - - } - - printf("Terminating GLFW...\n"); - glfwTerminate(); - printf("Clearing buffer...\n"); - glDeleteBuffers(1, &pbo); - return 0; - -} |