#include #include #include #include #include #include // only include this one in the source file with main()! #define INITIAL_FPS 60 SDL_Window* window = NULL; SDL_GLContext glcontext = NULL; GLuint program; GLuint vbo; static double FPS = INITIAL_FPS; static double FrameTime = 1.0 / INITIAL_FPS; static double PerformancePeriod; static void panic ( const char *text ) __attribute__((noreturn)); static double GetTime( void ) { return PerformancePeriod * SDL_GetPerformanceCounter(); } static void SetTitle ( SDL_Window *window ) { char title[48] = {0}; SDL_snprintf(title, sizeof(title), "Crude frame limiter @ %6.3f Hz", FPS); SDL_SetWindowTitle(window, title); } void panic ( const char *text ) { //fprintf(stderr, "ERROR: %s. %s\n", text, SDL_GetError()); SDL_LogCritical(SDL_LOG_CATEGORY_ASSERT, "%s. %s\n", text, SDL_GetError()); SDL_GL_DestroyContext(glcontext); SDL_DestroyWindow(window); SDL_Quit(); exit(1); } char *readFile ( const char *fileName ) { SDL_IOStream *ioStream = SDL_IOFromFile(fileName, "rb"); if (!ioStream) panic("SDL_IOFromfile"); if (!SDL_SeekIO(ioStream, 0, SDL_IO_SEEK_END)) panic("SDL_SeekIO_END"); long len = SDL_TellIO(ioStream); if (!len) panic("SDL_TellIO"); if (!SDL_SeekIO(ioStream, 0, SDL_IO_SEEK_SET)) panic("SDL_SeekIO_SET"); char *res = SDL_malloc(len + 1); if (!res) panic("SDL_malloc_RES"); if (SDL_ReadIO(ioStream, res, len) != (size_t)len) panic("SDL_ReadIO"); if (!SDL_CloseIO(ioStream)) panic("SDL_CloseIO"); /* char *res = SDL_LoadFile_IO(ioStream, NULL, true); */ /* if (!res) panic("SDL_LoadFile_IO"); */ res[len] = 0; return res; } GLuint CreateShader ( const char *shaderFile, GLenum shaderType ) { const char *strShaderType; if (shaderType == GL_VERTEX_SHADER) { strShaderType = "vertex"; } else if (shaderType == GL_GEOMETRY_SHADER) { strShaderType = "geometry"; } else if (shaderType == GL_FRAGMENT_SHADER) { strShaderType = "fragment"; } else { SDL_LogCritical(SDL_LOG_CATEGORY_ASSERT, "Unrecognized shader type.\n"); exit(1); } GLuint shader = glCreateShader(shaderType); if (!shader) { SDL_LogCritical(SDL_LOG_CATEGORY_ASSERT, "Error create shader type %s\n", strShaderType); exit(1); } GLchar *content = readFile(shaderFile); glShaderSource(shader, 1, (const GLchar **)&content, NULL); SDL_free(content); glCompileShader(shader); GLint status; glGetShaderiv(shader, GL_COMPILE_STATUS, &status); if (status == GL_FALSE) { GLint infoLen; glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLen); GLchar *info = SDL_malloc(sizeof(GLchar) * (infoLen + 1)); glGetShaderInfoLog(shader, infoLen, NULL, info); SDL_LogCritical(SDL_LOG_CATEGORY_ASSERT, "Filed to compile %s shader:\n%s\n", strShaderType, info); exit(1); } return shader; } void CreateProgram ( GLuint *shaders, int len ) { program = glCreateProgram(); if (!program) { SDL_LogCritical(SDL_LOG_CATEGORY_ASSERT, "Can't to create shader program\n"); exit(1); } for (int i = 0; i < len; i++) { glAttachShader(program, shaders[i]); } glLinkProgram(program); GLint status; glGetProgramiv(program, GL_LINK_STATUS, &status); if (status == GL_FALSE) { GLint infoLen; glGetProgramiv(program, GL_INFO_LOG_LENGTH, &infoLen); GLchar *info = SDL_malloc(sizeof(GLchar) * (infoLen + 1)); glGetProgramInfoLog(program, infoLen, NULL, info); SDL_LogCritical(SDL_LOG_CATEGORY_ASSERT, "Link failed: %s\n", info); exit(1); } } void CreateBuffer ( void ) { float vertices[] = { -1.0f, -1.0f, 0.0f, 1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 0.0f }; glGenBuffers(1, &vbo); glBindBuffer(GL_ARRAY_BUFFER, vbo); glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); } void ConfProg ( void ) { CreateBuffer(); GLuint shaders[] = { CreateShader("vertex.glsl", GL_VERTEX_SHADER), CreateShader("fragmet.glsl", GL_FRAGMENT_SHADER) }; int len = sizeof(shaders) / sizeof(shaders[0]); CreateProgram(shaders, len); for (int i = 0; i < len; i++) { glDeleteShader(shaders[i]); } } int main( int argc, char* argv[] ) { const int WIDTH = 640; const int HEIGHT = 480; int delay_threshold = 2; double sleep_time; double time_counter = 0; bool loopShouldStop = false; SDL_SetHint(SDL_HINT_RENDER_VSYNC, 0); if (!SDL_Init(SDL_INIT_VIDEO)) { panic("SDL_Init failed"); } SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 5); SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 5); SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 5); SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16); SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); PerformancePeriod = 1.0 / SDL_GetPerformanceFrequency(); time_counter = GetTime(); window = SDL_CreateWindow("Hello SDL", WIDTH, HEIGHT, SDL_WINDOW_OPENGL|SDL_WINDOW_RESIZABLE); if (!window) { panic("SDL_CreateWindow"); } glcontext = SDL_GL_CreateContext(window); if (!glcontext) { panic("SDL_GL_CreateContext"); } ConfProg(); SetTitle(window); //if (!SDL_SetRenderVSync(renderer, 1)) //{ // panic("SDL_SetRenderVSync"); //} SDL_HideCursor(); int red = 0; int green = 0; int r, g, b; while (!loopShouldStop) { SDL_Event e; SDL_zero(e); while (SDL_PollEvent(&e)) { if (e.type == SDL_EVENT_QUIT) loopShouldStop = true; else if (e.type == SDL_EVENT_KEY_DOWN) { if (e.key.key == SDLK_X) { FPS -= 0.1; if (FPS < 1) { FPS = 1; } FrameTime = 1.0 / FPS; SetTitle(window); } else if (e.key.key == SDLK_C) { FPS += 0.1; FrameTime = 1.0 / FPS; SetTitle(window); } if (e.key.key == SDLK_ESCAPE) loopShouldStop = true; } } /* SDL_SetRenderDrawColor(renderer, red, green, 0, 255); */ /* SDL_RenderClear(renderer); */ glClearColor(0, 0, 0, 1); glClear(GL_COLOR_BUFFER_BIT); SDL_GL_SwapWindow(window); sleep_time = time_counter - GetTime(); if (sleep_time * 1000 > delay_threshold) { Uint32 ms = (Uint32)(sleep_time * 1000) - delay_threshold; SDL_Delay(ms); if (time_counter < GetTime()) { delay_threshold++; SDL_Log("Slept too long. Increased threshold to %u ms.", delay_threshold); } } while (time_counter > GetTime()) { /* Waiting for the right moment. */ } /* red = (red + 1) % 256; */ /* green = (green + 1) % 64; */ time_counter += FrameTime; } SDL_GL_GetAttribute(SDL_GL_RED_SIZE, &r); SDL_GL_GetAttribute(SDL_GL_GREEN_SIZE, &g); SDL_GL_GetAttribute(SDL_GL_BLUE_SIZE, &b); printf("Red size: %d, Green size: %d, Blue size: %d\n", r, g, b); SDL_DestroyWindow(window); SDL_GL_DestroyContext(glcontext); SDL_Quit(); exit(0); }