#define GL_GLEXT_PROTOTYPES #include #include #include #include #include void checkGlError() { const char *err = SDL_GetError(); if (*err != 0) { printf("OpenGL error: %s", err); } } /// returns 0 if failed. GLuint compile_shader(GLuint type, const char *src) { GLuint id = glCreateShader(type); glShaderSource(id, 1, &src, 0); glCompileShader(id); int result; glGetShaderiv(id, GL_COMPILE_STATUS, &result); if (result == GL_FALSE) { int length; glGetShaderiv(id, GL_INFO_LOG_LENGTH, &result); char *message = alloca(length * sizeof(char)); glGetShaderInfoLog(id, length, &length, message); printf("failed to compile %s shader\n", type == GL_VERTEX_SHADER ? "vertex" : "fragment"); printf("%s\n", message); glDeleteShader(id); return 0; } return id; } /// returns 0 if failed. GLuint create_shader(const char *fragment_src) { GLuint program = glCreateProgram(); GLuint fragment_shader = compile_shader(GL_FRAGMENT_SHADER, fragment_src); if (!(fragment_shader == 0)) { glAttachShader(program, fragment_shader); glLinkProgram(program); glValidateProgram(program); glDeleteShader(fragment_shader); return program; } else { return 0; } } GLuint load_shader(const char *path) { FILE *handle = fopen(path, "r"); fseek(handle, 0L, SEEK_END); long length = ftell(handle); fseek(handle, 0L, SEEK_SET); char *string = malloc(length * sizeof(char)); if (!fread(string, sizeof(char), length, handle)) { printf("failed to read shader file"); exit(1); } fclose(handle); GLuint shader = create_shader(string); if (shader == 0) { // print file int line_count = 1; printf("%i\t", line_count); line_count++; for (int i = 0; i < length; i++) { printf("%c", string[i]); if (string[i] == '\n') { printf("%i\t", line_count); line_count++; } } printf("\n"); } free(string); return shader; } struct timespec program_start; void init_timer() { clock_gettime(CLOCK_MONOTONIC, &program_start); } double time_since_start() { struct timespec now; clock_gettime(CLOCK_MONOTONIC, &now); return (now.tv_sec - program_start.tv_sec) + (now.tv_nsec - program_start.tv_nsec) / 1e9; } int main() { init_timer(); printf("Good Morning 🍵\n"); SDL_Init(SDL_INIT_VIDEO); SDL_Window* window = SDL_CreateWindow("SDL3 OpenGL Cube", 800, 600, SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE); if (!window) { printf("CreateWindow Error: %s\n", SDL_GetError()); SDL_Quit(); return 1; } SDL_GLContext glContext = SDL_GL_CreateContext(window); if (!glContext) { printf("GL Context Error: %s\n", SDL_GetError()); SDL_DestroyWindow(window); SDL_Quit(); return 1; } glEnable(GL_DEPTH_TEST); SDL_Event e; int running = 1; GLuint shader = load_shader("fragment.glsl"); //create_shader(fragment_shader_source); int w, h; double time; while (running) { while (SDL_PollEvent(&e)) { if (e.type == SDL_EVENT_QUIT) running = false; if (e.type == SDL_EVENT_WINDOW_RESIZED) { SDL_GetWindowSize(window, &w, &h); } } checkGlError(); // Rendorrrr glViewport(0, 0, w, h); glClearColor(0.1f, 0.1f, 0.1f, 1.0f); // Dark gray background glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Shader parameters. glUseProgram(shader); int uniform_WindowSize = glGetUniformLocation(shader, "WindowSize"); glUniform2f(uniform_WindowSize, w, h); time = time_since_start(); int uniform_time = glGetUniformLocation(shader, "time"); glUniform1f(uniform_time, (float)time); // Draw quad. glBegin(GL_QUADS); glVertex2f(-1, 1); glVertex2f(-1,-1); glVertex2f( 1,-1); glVertex2f( 1, 1); glEnd(); SDL_GL_SwapWindow(window); } checkGlError(); }