// compile using // g++ -o pftest pftest.cpp -std=c++11 -lSDL2 -lepoxy // #include #include #include namespace { GLAPIENTRY void debugHandler(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, GLchar const *message, void const *userParam) { std::cout << "GL message: " << message << '\n'; } float const vertices[] = {-1.0, -1.0, -1.0, 1.0, 1.0, -1.0, 1.0, 1.0}; unsigned short const indices[] = {0, 1, 2, 1, 2, 3}; char const* const vsSource = R"( #version 330 #extension GL_ARB_shading_language_420pack : require layout(binding = 0) uniform Block { float t; }; layout(location = 0) in vec2 inPos; void main() { float s = sin(t); float c = cos(t); gl_Position = vec4(inPos.x * c + inPos.y * s, inPos.y * c - inPos.x * s, 0, 2); } )"; char const* const fsSource = R"( #version 330 #extension GL_ARB_shading_language_420pack : require out vec4 color; void main() { color = vec4(1.0); } )"; GLuint createShader(GLenum type, char const* source) { auto shader = glCreateShader(type); glShaderSource(shader, 1, &source, 0); glCompileShader(shader); return shader; } } int main() { SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTS); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3); SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, SDL_GL_CONTEXT_DEBUG_FLAG); SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); SDL_Window *window = SDL_CreateWindow("pageflip", 0, 0, 1920, 1080, SDL_WINDOW_OPENGL); SDL_GLContext context = SDL_GL_CreateContext(window); glDebugMessageCallbackARB(debugHandler, nullptr); glClearColor(0.f, 0.f, 0.f, 0.f); auto vs = createShader(GL_VERTEX_SHADER, vsSource); auto fs = createShader(GL_FRAGMENT_SHADER, fsSource); auto prog = glCreateProgram(); glAttachShader(prog, vs); glAttachShader(prog, fs); glLinkProgram(prog); glUseProgram(prog); GLuint vao; glGenVertexArrays(1, &vao); glBindVertexArray(vao); GLuint vbo, ibo; glGenBuffers(1, &vbo); glBindBuffer(GL_ARRAY_BUFFER, vbo); glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); glVertexAttribPointer(0, 2, GL_FLOAT, false, 8, nullptr); glEnableVertexAttribArray(0); glGenBuffers(1, &ibo); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo); glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW); bool shouldExit = false; float t = 0; for (;;) { SDL_Event event; while (SDL_PollEvent(&event)) { if (event.type == SDL_QUIT || (event.type == SDL_KEYDOWN && event.key.keysym.sym == SDLK_ESCAPE)) shouldExit = true; if(event.type == SDL_KEYDOWN && event.key.keysym.sym == SDLK_SPACE) t += 1.0; } if (shouldExit) break; glClear(GL_COLOR_BUFFER_BIT); GLuint ubo; glGenBuffers(1, &ubo); glBindBuffer(GL_UNIFORM_BUFFER, ubo); glBufferData(GL_UNIFORM_BUFFER, sizeof(t), &t, GL_STATIC_DRAW); glBindBufferBase(GL_UNIFORM_BUFFER, 0, ubo); glDrawElementsInstanced(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, nullptr, 1000); SDL_GL_SwapWindow(window); } // no cleanup: not needed }