diff options
| author | Charles <sircharlesaze@gmail.com> | 2020-05-19 21:41:09 +0200 |
|---|---|---|
| committer | Charles <sircharlesaze@gmail.com> | 2020-05-19 21:41:09 +0200 |
| commit | 3b2e7cc2347d88dbd8d7697a7cbd8354e7728fc0 (patch) | |
| tree | 56cd83dca6d3627844347cc2ca86a6f6255f87d5 | |
| parent | b0998910dd974280b3c6f3f65e21bfd5859b117f (diff) | |
| download | mandelbrot-3b2e7cc2347d88dbd8d7697a7cbd8354e7728fc0.tar.gz mandelbrot-3b2e7cc2347d88dbd8d7697a7cbd8354e7728fc0.tar.bz2 mandelbrot-3b2e7cc2347d88dbd8d7697a7cbd8354e7728fc0.zip | |
Added OpenGL boilerplate
| -rw-r--r-- | Makefile | 9 | ||||
| -rw-r--r-- | inc/mandel.h | 39 | ||||
| -rw-r--r-- | shader/fragment.glsl | 8 | ||||
| -rw-r--r-- | shader/vertex.glsl | 5 | ||||
| -rw-r--r-- | src/error.c | 37 | ||||
| -rw-r--r-- | src/event.c | 33 | ||||
| -rw-r--r-- | src/shader.c | 73 | ||||
| -rw-r--r-- | src/state.c | 77 |
8 files changed, 197 insertions, 84 deletions
@@ -7,9 +7,10 @@ INC_DIR = inc OBJ_DIR = obj CC = gcc -OFLAG = -Ofast -funroll-loops -ffast-math -CCFLAGS = -I$(INC_DIR) -Wall -Wextra $(OFLAG) -LDFLAGS = -lm -lpthread $(shell sdl2-config --libs --cflags) +OFLAG = -O0 #-Ofast -funroll-loops -ffast-math +CCFLAGS = -I$(INC_DIR) -Wall -Wextra -Wpedantic $(OFLAG) \ + $(shell pkg-config --cflags sdl2 glew) +LDFLAGS = $(shell pkg-config --libs sdl2 glew) INC = $(shell find $(INC_DIR) -type f -name '*.h') SRC = $(shell find $(SRC_DIR) -type f -name '*.c') @@ -23,7 +24,7 @@ prebuild: $(NAME): $(OBJ) $(CC) -o $@ $(OBJ) $(LDFLAGS) -$(OBJ_DIR)/%.o: $(SRC_DIR)/%.c $(HEADER) +$(OBJ_DIR)/%.o: $(SRC_DIR)/%.c $(INC) $(CC) $(CCFLAGS) -c -o $@ $< debug: OFLAG = -g diff --git a/inc/mandel.h b/inc/mandel.h index a98e007..f55466c 100644 --- a/inc/mandel.h +++ b/inc/mandel.h @@ -1,18 +1,27 @@ #ifndef MANDEL_H # define MANDEL_H +# include <stdio.h> # include <stdlib.h> # include <stdbool.h> # include <math.h> -# include <immintrin.h> +# include <GL/glew.h> # include <SDL2/SDL.h> +# include <assert.h> + #define SDL_CALL(x) do { \ SDL_ClearError(); \ x; \ error_check_sdl(#x, __FILE__, __LINE__); \ } while (0) +# define GL_CALL(x) do { \ + error_clear_gl(); \ + x; \ + error_check_gl(#x, __FILE__, __LINE__); \ +} while (0) + typedef union { uint32_t data; @@ -39,11 +48,28 @@ typedef struct typedef struct { + unsigned int id; + struct + { + int iteration; + } location; +} Shader; + +typedef struct +{ SDL_Window *window; - SDL_Renderer *renderer; + SDL_GLContext context; bool running; - SDL_Texture *texture; - Color *palette; + int width; + int height; + + unsigned int vertex_buf; + unsigned int texture; + + Shader shader; + + // Color *palette; + double real_start; double real_end; double imag_start; @@ -64,8 +90,13 @@ void event_handle(State *state); // error.c void error_check_sdl(const char *code, const char *filename, int line_num); +void error_clear_gl(void); +void error_check_gl(const char *code, const char *filename, int line_num); // color.c Color *color_palette_new(Color *palette, int iterations); +// shader.c +bool shader_init(Shader *shader); + #endif diff --git a/shader/fragment.glsl b/shader/fragment.glsl new file mode 100644 index 0000000..3fbeac5 --- /dev/null +++ b/shader/fragment.glsl @@ -0,0 +1,8 @@ +#version 400 core + +out vec4 out_color; + +void main() +{ + out_color = vec4(1.0, 1.0, 1.0, 1.0); +} diff --git a/shader/vertex.glsl b/shader/vertex.glsl new file mode 100644 index 0000000..9ec6439 --- /dev/null +++ b/shader/vertex.glsl @@ -0,0 +1,5 @@ +#version 400 core + +void main() +{ +} diff --git a/src/error.c b/src/error.c index 92e3a71..1e2975f 100644 --- a/src/error.c +++ b/src/error.c @@ -7,7 +7,42 @@ void error_check_sdl(const char *code, const char *filename, int line_num) err = SDL_GetError(); if (*err == '\0') return ; - SDL_Log("[ERROR SDL] %s\n\t(%s) at %s:%d", err, code, filename, line_num); + SDL_Log("[ERROR SDL] %s\n\t(%s) at %s:%d\n", err, code, filename, line_num); SDL_Quit(); exit(EXIT_FAILURE); } + +void error_clear_gl(void) +{ + while (glGetError() != GL_NO_ERROR) + ; +} + +void error_check_gl(const char *code, const char *filename, int line_num) +{ + GLenum err; + bool occured; + char *err_str = ""; + + occured = false; + while ((err = glGetError()) != GL_NO_ERROR) + { + switch (err) + { + case GL_INVALID_OPERATION: + err_str = "GL_INVALID_OPERATION"; + break; + case GL_INVALID_VALUE: + err_str = "GL_INVALID_VALUE"; + break; + case GL_INVALID_ENUM: + err_str = "GL_INVALID_ENUM"; + break; + } + fprintf(stderr, "[ERROR OPENGL] (%d) %s\n\t(%s) at %s:%d\n", + err, err_str, code, filename, line_num); + occured = true; + } + if (occured) + exit(EXIT_FAILURE); +} diff --git a/src/event.c b/src/event.c index f0f0e14..2ce5cc9 100644 --- a/src/event.c +++ b/src/event.c @@ -21,13 +21,13 @@ void event_handle(State *state) { case SDLK_r: state->iterations += 10; - state->palette = color_palette_new(state->palette, state->iterations); + /* state->palette = color_palette_new(state->palette, state->iterations); */ break; case SDLK_e: state->iterations -= 10; if (state->iterations <= 0) state->iterations = 1; - state->palette = color_palette_new(state->palette, state->iterations); + /* state->palette = color_palette_new(state->palette, state->iterations); */ break; case SDLK_UP: case SDLK_k: @@ -68,26 +68,15 @@ void event_handle(State *state) case SDL_WINDOWEVENT: if (e.window.event == SDL_WINDOWEVENT_RESIZED) { - int width; - int height; - SDL_QueryTexture(state->texture, NULL, NULL, &width, &height); - - double w_ratio = (double)width / (double)e.window.data1; - double h_ratio = (double)height / (double)e.window.data2; - - state->real_start /= w_ratio; - state->real_end /= w_ratio; - state->imag_start /= h_ratio; - state->imag_end /= h_ratio; - - SDL_DestroyTexture(state->texture); - SDL_CALL(state->texture = SDL_CreateTexture( - state->renderer, - SDL_PIXELFORMAT_RGB888, - SDL_TEXTUREACCESS_STREAMING, - e.window.data1, - e.window.data2 - )); + SDL_GL_GetDrawableSize(state->window, &state->width, &state->height); + GL_CALL(glViewport(0, 0, state->width, state->height)); + /* double w_ratio = (double)width / (double)e.window.data1; */ + /* double h_ratio = (double)height / (double)e.window.data2; */ + /* */ + /* state->real_start /= w_ratio; */ + /* state->real_end /= w_ratio; */ + /* state->imag_start /= h_ratio; */ + /* state->imag_end /= h_ratio; */ } break; } diff --git a/src/shader.c b/src/shader.c new file mode 100644 index 0000000..478c93b --- /dev/null +++ b/src/shader.c @@ -0,0 +1,73 @@ +#include "mandel.h" + +#define MANDEL_SHADER_VERT_FILE "shader/vertex.glsl" +#define MANDEL_SHADER_FRAG_FILE "shader/fragment.glsl" + +static unsigned int st_compile(char *filepath, unsigned int type); + +bool shader_init(Shader *shader) +{ + unsigned int shader_vert; + unsigned int shader_frag; + + shader_vert = st_compile(MANDEL_SHADER_VERT_FILE, GL_VERTEX_SHADER); + if (shader_vert == 0) + return false; + shader_frag = st_compile(MANDEL_SHADER_FRAG_FILE, GL_FRAGMENT_SHADER); + if (shader_frag == 0) + return false; + + GL_CALL(shader->id = glCreateProgram()); + GL_CALL(glAttachShader(shader->id, shader_vert)); + GL_CALL(glAttachShader(shader->id, shader_frag)); + GL_CALL(glLinkProgram(shader->id)); + GL_CALL(glValidateProgram(shader->id)); + GL_CALL(glDeleteShader(shader_vert)); + GL_CALL(glDeleteShader(shader_frag)); + return (true); +} + +static unsigned int st_compile(char *filepath, unsigned int type) +{ + unsigned int id; + int result; + FILE *file; + char *source; + + if ((file = fopen(filepath, "r")) == NULL) + return 0; + fseek(file, 0, SEEK_END); + long file_size = ftell(file); + rewind(file); + + if ((source = malloc(sizeof(char) * (file_size + 1))) == NULL + || fread(source, sizeof(char), file_size, file) != (unsigned long)file_size) + { + free(source); + fclose(file); + return 0; + } + fclose(file); + source[file_size] = '\0'; + + GL_CALL(id = glCreateShader(type)); + GL_CALL(glShaderSource(id, 1, (const char**)&source, (int*)&file_size)); + free(source); + GL_CALL(glCompileShader(id)); + + GL_CALL(glGetShaderiv(id, GL_COMPILE_STATUS, &result)); + if (result == GL_FALSE) + { + int len; + char *msg; + GL_CALL(glGetShaderiv(id, GL_INFO_LOG_LENGTH, &len)); + if ((msg = malloc(sizeof(char) * (len + 1))) == NULL) + return 0; + GL_CALL(glGetShaderInfoLog(id, len, &len, msg)); + fputs(msg, stderr); + free(msg); + GL_CALL(glDeleteShader(id)); + return 0; + } + return id; +} diff --git a/src/state.c b/src/state.c index 395d590..b2ea45c 100644 --- a/src/state.c +++ b/src/state.c @@ -4,25 +4,32 @@ bool state_init(State *state) { SDL_CALL(SDL_Init(SDL_INIT_VIDEO)); + SDL_CALL(SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 4)); + SDL_CALL(SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0)); + SDL_CALL(SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE)); + SDL_CALL(SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1)); SDL_CALL(state->window = SDL_CreateWindow( MANDEL_WINDOW_TITLE, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, MANDEL_WINDOW_WIDTH, MANDEL_WINDOW_HEIGHT, - SDL_WINDOW_RESIZABLE + SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE )); - SDL_CALL(state->renderer = SDL_CreateRenderer(state->window, -1, 0)); - SDL_CALL(state->texture = SDL_CreateTexture( - state->renderer, - SDL_PIXELFORMAT_RGB888, - SDL_TEXTUREACCESS_STREAMING, - MANDEL_WINDOW_WIDTH, - MANDEL_WINDOW_HEIGHT - )); - state->palette = color_palette_new(NULL, MANDEL_ITERATIONS); - if (state->palette == NULL) + SDL_CALL(state->context = SDL_GL_CreateContext(state->window)); + assert(glewInit() == GLEW_OK); + SDL_CALL(SDL_GL_SetSwapInterval(1)); + if (!shader_init(&state->shader)) + { + perror(NULL); return false; + } + SDL_GL_GetDrawableSize(state->window, &state->width, &state->height); + GL_CALL(glViewport(0, 0, state->width, state->height)); + + /* state->palette = color_palette_new(NULL, MANDEL_ITERATIONS); */ + /* if (state->palette == NULL) */ + /* return false; */ state->iterations = MANDEL_ITERATIONS; state->real_start = -2.0; state->real_end = 2.0; @@ -37,55 +44,19 @@ void state_run(State *state) while (state->running) { event_handle(state); + glClearColor(0.2, 0.3, 0.2, 1.0); + glClear(GL_COLOR_BUFFER_BIT); - double real_step; - double imag_step; - double real; - double imag; - void *pixels; - int pitch; - int width; - int height; - - SDL_CALL(SDL_LockTexture(state->texture, NULL, &pixels, &pitch)); - SDL_CALL(SDL_QueryTexture(state->texture, NULL, NULL, &width, &height)); - - real_step = (state->real_end - state->real_start) / width; - imag_step = (state->imag_end - state->imag_start) / height; - imag = state->imag_start; - - uint32_t render_start_time = SDL_GetTicks(); - - for (int i = 0; i < height; i++) - { - real = state->real_start; - for (int j = 0; j < width; j++) - { - int n = mandelbrot(real, imag, state->iterations); - Color c = state->palette[n]; - ((Color*)pixels)[i * width + j] = c; - real += real_step; - } - imag += imag_step; - } - - uint32_t render_end_time = SDL_GetTicks(); - - printf("%ums\r", (render_end_time - render_start_time)); - fflush(stdout); - - SDL_UnlockTexture(state->texture); - SDL_CALL(SDL_RenderCopy(state->renderer, state->texture, NULL, NULL)); - SDL_RenderPresent(state->renderer); + SDL_GL_SwapWindow(state->window); SDL_Delay(3); } } void state_quit(State *state) { - free(state->palette); - SDL_DestroyTexture(state->texture); - SDL_DestroyRenderer(state->renderer); + /* free(state->palette); */ + GL_CALL(glDeleteProgram(state->shader.id)); + SDL_GL_DeleteContext(state->context); SDL_DestroyWindow(state->window); SDL_Quit(); } |
