#ifndef APP_H #define APP_H #include #include #include #include #include #include #include #include "stfu/stf.hpp" #include "pngwriter/pngwriter.h" #include "shader.h" #include "fbo.h" static const std::string filenames[] = { "resources/attractor_2011-04-28_10-30-35-2.stf", "resources/attractor_2011-04-28_10-05-11-1.stf", "resources/attractor_2011-04-29_04-34-41-9.stf", "resources/attractor_2011-04-29_15-19-03-9.stf" }; static const GLfloat quad[] = { 1.0, 1.0, 1.0, -1.0, -1.0, -1.0, -1.0, 1.0 }; static const GLfloat tex_quad[] = { 1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 }; class App { int counter; unsigned int width, height; shader mshader; shader clear_shader; shader texture_shader; shader blur_shader1; shader blur_shader2; fbo fbo1; fbo fbo2; static constexpr size_t number_of_lines = 40000; static constexpr size_t number_of_vertices = 2*number_of_lines; std::array lines; std::array parameters; std::array random_parameters; public: App(unsigned int w, unsigned int h) : counter(0), width(w), height(h), mshader("resources/myTeaShader.vert", "resources/myTeaShader.frag"), clear_shader("resources/myClearShader.vert", "resources/myClearShader.frag"), texture_shader("resources/myTextureShader.vert", "resources/myTextureShader.frag"), blur_shader1("resources/myHBlurShader.vert", "resources/myHBlurShader.frag"), blur_shader2("resources/myVBlurShader.vert", "resources/myVBlurShader.frag"), fbo1(width, height), fbo2(width, height), lines(), parameters(), random_parameters() { set_points(); //glEnable(GL_DEPTH_TEST); glEnable(GL_BLEND); glEnable(GL_TEXTURE_2D); std::string filename = filenames[3]; set_parameters(filename); } ~App() { } void resize(int w, int h) { std::cout << w << "x" << h << std::endl; } void update() { ++counter; iterate(); if(counter % 5000 == 0) { set_parameters(filenames[rand() % 4]); set_points(); } } void draw() { fbo & read_fbo = (counter % 2) ? fbo1 : fbo2; fbo & draw_fbo = (counter % 2) ? fbo2 : fbo1; shader & blur_shader = (counter % 2) ? blur_shader1 : blur_shader2; glClearColor(0.0, 0.0, 0.0, 0.0); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); draw_fbo.begin(); glClearColor(0.0, 0.0, 0.0, 0.0); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); blur_shader.begin(); texture(read_fbo); mshader.begin(); scene(); draw_fbo.end(); texture_shader.begin(); texture(draw_fbo); //save_screen(); } void fade() { glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glEnableClientState(GL_VERTEX_ARRAY); glVertexPointer(2, GL_FLOAT, 0, &quad[0]); glDrawArrays(GL_QUADS, 0, 4); glDisableClientState(GL_VERTEX_ARRAY); } void texture(fbo const & read_fbo) { glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); texture_shader.set_texture("tex", GL_TEXTURE_2D, read_fbo.texture_id, 0); glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_TEXTURE_COORD_ARRAY); glVertexPointer(2, GL_FLOAT, 0, &quad[0]); glTexCoordPointer(2, GL_FLOAT, 0, &tex_quad[0]); glDrawArrays(GL_QUADS, 0, 4); glDisableClientState(GL_TEXTURE_COORD_ARRAY); glDisableClientState(GL_VERTEX_ARRAY); } void scene() { glBlendFunc(GL_ONE, GL_ONE); mshader.set_uniform("steps", counter/10); glRotatef(0.05, std::sin(counter/13370.0), 1.0, 0.0); const unsigned int part = 8; glEnableClientState(GL_VERTEX_ARRAY); glVertexPointer(3, GL_FLOAT, 0, &lines[0]); glPointSize(3.0); glDrawArrays(GL_POINTS, 0, number_of_vertices/part); glPointSize(1.0); glDrawArrays(GL_POINTS, number_of_vertices/part, (part-1)*number_of_vertices/part); glDisableClientState(GL_VERTEX_ARRAY); } void iterate() { for(size_t i = 0; i < number_of_lines; ++i) { GLfloat* vectorNew = &lines[3*2*i]; GLfloat* vectorOld = &lines[3*2*i+3]; if(counter % 2) std::swap(vectorNew, vectorOld); vectorNew[0] = parameters[0]*(vectorOld[2] + parameters[1]); vectorNew[1] = parameters[2]*(vectorOld[0] + parameters[3]); vectorNew[2] = parameters[4]*(vectorOld[1] + parameters[5]); const double dist = vectorNew[0]*vectorNew[0] + vectorNew[1]*vectorNew[1] + vectorNew[2]*vectorNew[2]; if(dist > parameters[6]*parameters[6]) { const double sqrtDist = std::sqrt(dist); const double p = 1.0 - parameters[6] * (static_cast(sqrtDist / parameters[6]) + 1.0) / sqrtDist; vectorNew[0] *= p; vectorNew[1] *= p; vectorNew[2] *= p; } } for(size_t i = 0; i < 7; ++i){ parameters[i] += random_parameters[i]; } } void save_screen(){ unsigned char data[width*height*6]; glReadPixels(0, 0, width, height, GL_RGB, GL_UNSIGNED_SHORT, data); char filename[256]; sprintf(filename, "render/shot_%08d.png", counter); pngwriter png(width, height, &data[0], filename); png.close(); } void set_parameters(std::string filename){ stfu::node file; file.read(filename.c_str()); for(unsigned int i = 0; i < 7; ++i) { stfu::node const attractorParameters = file.getChild("AttractorKernel").getChild("parameters"); parameters[i] = atof(attractorParameters.getValue(i).c_str()); random_parameters[i] = (rand() / (double)RAND_MAX - 0.5) * counter / 5000000.0; } } void set_points(){ std::generate(lines.begin(), lines.end(), []() { return 2.0 * rand() / (double)RAND_MAX - 1.0; }); } }; #endif // APP_H