#include #include #include #include #include #define UNUSED(a) ((void) (a)) static const float verts[] = { -0.5, 0.5, 0, 0.5, 0.5, 0, 0.0, -0.5, 0, }; static const char * vs_src = "#version 320 es\n" "\n" "layout (location = 0) in mediump vec3 pos;\n" "\n" "void main() {\n" " gl_Position = vec4(pos.x, pos.y, pos.z, 1);\n" "}\n"; static const char * fs_src = "#version 320 es\n" "\n" "out mediump vec4 color;\n" "\n" "uniform mediump float time;\n" "\n" "void main() {\n" " color = vec4(0.5f + 0.5 * sin(time * 3.141), 0, 0, 1);\n" "}\n"; static GLuint compile_shader( const GLenum type, const char *src ) { // create shader GLuint r = glCreateShader(type); // compile shader glShaderSource(r, 1, &src, NULL); glCompileShader(r); // check for error GLint ok; glGetShaderiv(r, GL_COMPILE_STATUS, &ok); if (!ok) { GLchar log[1024]; glGetShaderInfoLog(r, sizeof(log), NULL, log); fprintf(stderr, "Shader Compile Error: %s\n", log); exit(EXIT_FAILURE); } // return result return r; } static GLuint link_render_program( const char * const vs_src, const char * const fs_src ) { // create program GLuint r = glCreateProgram(); // compile shaders GLuint vs = compile_shader(GL_VERTEX_SHADER, vs_src), fs = compile_shader(GL_FRAGMENT_SHADER, fs_src); // attach shaders glAttachShader(r, vs); glAttachShader(r, fs); // link program glLinkProgram(r); // check link status GLint ok; glGetProgramiv(r, GL_LINK_STATUS, &ok); if (!ok) { GLchar log[1024]; glGetProgramInfoLog(r, sizeof(log), NULL, log); fprintf(stderr, "Program Link Error: %s\n", log); exit(EXIT_FAILURE); } // delete shaders glDeleteShader(vs); glDeleteShader(fs); // return result return r; } #if 0 static GLuint link_compute_program( const char * const cs_src ) { // create program GLuint r = glCreateProgram(); } #endif static SDL_Window * init(void) { if (SDL_Init(SDL_INIT_VIDEO) < 0) { SDL_Log("SDL_Init() failed: %s", SDL_GetError()); exit(EXIT_FAILURE); } // create window SDL_Window *win = SDL_CreateWindow( "Compute Test", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 640, 480, SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE ); // check for error if (!win) { SDL_Log("SDL_CreateWindow() failed: %s", SDL_GetError()); exit(EXIT_FAILURE); } // set gl context majory version hint if (SDL_GL_SetAttribute( SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES ) < 0) { SDL_Log("SDL_GL_SetAttribute() failed: %s", SDL_GetError()); exit(EXIT_FAILURE); } // set gl context majory version hint if (SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3) < 0) { SDL_Log("SDL_GL_SetAttribute() failed: %s", SDL_GetError()); exit(EXIT_FAILURE); } // set gl context minor version hint if (SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2) < 0) { SDL_Log("SDL_GL_SetAttribute() failed: %s", SDL_GetError()); exit(EXIT_FAILURE); } // create GL context SDL_GLContext context = SDL_GL_CreateContext(win); if (!context) { SDL_Log("SDL_GL_CreateContext() failed: %s", SDL_GetError()); exit(EXIT_FAILURE); } // init glew // (do this immediately after setting context) { GLenum err = glewInit(); if (err != GLEW_OK) { SDL_Log("glewInit() failed: %s", glewGetErrorString(err)); exit(EXIT_FAILURE); } } // set swap interval // (after context init) if (SDL_GL_SetSwapInterval(1) < 0) { SDL_Log("SDL_GL_SetSwapInterval() failed: %s", SDL_GetError()); exit(EXIT_FAILURE); } // return window return win; } int main(int argc, char *argv[]) { UNUSED(argc); UNUSED(argv); SDL_Window *win = init(); // generate vertex array GLuint vao; glGenVertexArrays(1, &vao); glBindVertexArray(vao); // generate vertex buffer GLuint vbo; glGenBuffers(1, &vbo); glBindBuffer(GL_ARRAY_BUFFER, vbo); glBufferData(GL_ARRAY_BUFFER, sizeof(verts), verts, GL_STATIC_DRAW); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (GLvoid*) 0); glEnableVertexAttribArray(0); // unbind vao glBindVertexArray(0); // link program GLuint prog = link_render_program(vs_src, fs_src); GLint u_time = glGetUniformLocation(prog, "time"); // main loop bool done = false, fullscreen = false; while (!done) { // clear screen glClearColor(0, 0, 0, 1); glClear(GL_COLOR_BUFFER_BIT); // use program, set uniform glUseProgram(prog); glUniform1f(u_time, SDL_GetTicks() / 1000.0); // draw glBindVertexArray(vao); glDrawArrays(GL_TRIANGLES, 0, 3); glBindVertexArray(0); // swap buffer SDL_GL_SwapWindow(win); // handle events { SDL_Event ev; while (SDL_PollEvent(&ev)) { switch (ev.type) { case SDL_QUIT: done = true; break; case SDL_KEYDOWN: switch (ev.key.keysym.sym) { case SDLK_ESCAPE: done = true; break; case SDLK_F11: // toggle fullscreen fullscreen = !fullscreen; if (SDL_SetWindowFullscreen( win, fullscreen ? SDL_WINDOW_FULLSCREEN_DESKTOP : 0 ) < 0) { SDL_Log("SDL_SetWindowFullscreen() failed: %s", SDL_GetError()); fullscreen = !fullscreen; } break; } break; case SDL_WINDOWEVENT: switch (ev.window.event) { case SDL_WINDOWEVENT_SIZE_CHANGED: // update viewport glViewport(0, 0, ev.window.data1, ev.window.data2); break; } break; } } } } // destroy window SDL_DestroyWindow(win); // return success return EXIT_SUCCESS; }