void Render(ExampleClock& clock) { if(long(clock.Now().Seconds()) % 4 == 0) { status += clock.Interval().Seconds(); } else if(status != double(long(status))) { if(status - double(long(status)) < 0.5) status = double(long(status)); else status = 1.0 + double(long(status)); } gl.Clear().ColorBuffer().DepthBuffer(); point_prog.status = GLfloat(0.5 - 0.5 * CosineWave(status * 0.5)); CamMatrixf camera = CamMatrixf::Orbiting( Vec3f(), 5.5f, FullCircles(clock.Now().Seconds() / 19.0), Degrees(45 + SineWave(clock.Now().Seconds() / 15.0) * 40)); point_prog.camera_matrix.Set(camera); point_prog.model_matrix.Set( ModelMatrixf::RotationX(RightAngles(status))); shape.Draw(); }
void Render(ExampleClock& clock) { positions.clear(); ages.clear(); // update the emitters and get the particle data for(auto i=emitters.begin(), e=emitters.end(); i!=e; ++i) { i->Update(clock); i->Upload(positions, ages); } assert(positions.size() == ages.size()); // make a camera matrix auto cameraMatrix = CamMatrixf::Orbiting( Vec3f(), 38.0 - SineWave(clock.Now().Seconds() / 6.0) * 17.0, FullCircles(clock.Now().Seconds() * 0.1), Degrees(SineWave(clock.Now().Seconds() / 20.0) * 60) ); std::vector<float> depths(positions.size()); std::vector<GLuint> indices(positions.size()); // calculate the depths of the particles for(GLuint i=0, n=positions.size(); i!=n; ++i) { depths[i] = (cameraMatrix * Vec4f(positions[i], 1.0)).z(); indices[i] = i; } // sort the indices by the depths std::sort( indices.begin(), indices.end(), [&depths](GLuint i, GLuint j) { return depths[i] < depths[j]; } ); // upload the particle positions pos_buf.Bind(Buffer::Target::Array); Buffer::Data(Buffer::Target::Array, positions, BufferUsage::DynamicDraw); // upload the particle ages age_buf.Bind(Buffer::Target::Array); Buffer::Data(Buffer::Target::Array, ages, BufferUsage::DynamicDraw); gl.Clear().ColorBuffer().DepthBuffer(); camera_matrix.Set(cameraMatrix); // use the indices to draw the particles gl.DrawElements( PrimitiveType::Points, indices.size(), indices.data() ); }
// Updates the emitter // Changes its position, emits new particles void Update(ExampleClock& clock) { assert(positions.size() == directions.size()); assert(positions.size() == ages.size()); assert(positions.size() == ids.size()); double time_diff = clock.Interval().Seconds(); double drag = 0.1 * time_diff; if(drag > 1.0) drag = 1.0; // go through the existing particles for(std::size_t i=0, n=positions.size(); i!=n; ++i) { // update the age ages[i] += time_diff / lifetime; // if the particle is "too old" if(ages[i] > 1.0) { // try to spawn a new one in its place SpawnParticle( clock.Now().Seconds(), positions[i], directions[i], ages[i], ids[i] ); } else { // otherwise just update its motion directions[i] *= (1.0 - drag); positions[i] += directions[i] * time_diff; } } Vec3f position; Vec3f direction; float age; int id; // spawn new particles if necessary while(SpawnParticle(clock.Now().Seconds(), position, direction, age, id)) { positions.push_back(position); directions.push_back(direction); ages.push_back(age); ids.push_back(id); } }
void Display(void) { _clock.Update(_os_clock.seconds()); double frame_time = _clock.Now().Seconds(); _frame_no++; GLuint primitives_per_frame = 0; if(_primitive_query) { try { auto query_exec = _primitive_query->Execute( Query::Target::PrimitivesGenerated, primitives_per_frame ); _example->Render(_clock); glutSwapBuffers(); } catch(Error&) { _primitive_query.reset(); } } else { _example->Render(_clock); glutSwapBuffers(); } _prim_count += double(primitives_per_frame); const double fps_interval = 10.0; const double this_interval = frame_time - _fps_time; if(this_interval >= fps_interval) { _fps_time = frame_time; std::cout.width(5); std::cout.precision(3); std::cout << _frame_no << " frames in " << std::fixed << this_interval << " seconds = " << std::fixed << _frame_no/this_interval << " FPS; " << std::scientific << _prim_count/this_interval << " PPS; " << std::scientific << _prim_count/_frame_no << " PPF; " << std::endl; _frame_no = 0; _prim_count = 0.0; } if(!_example->Continue(_clock)) { Quit(); } }
void Screenshot(void) { _example->Render(_clock); if(_clock.Now().Seconds() >= _example->ScreenshotTime()) { glFinish(); std::vector<char> pixels(_width * _height * 3); glReadPixels( 0, 0, _width, _height, GL_RGB, GL_UNSIGNED_BYTE, pixels.data() ); std::ofstream output(_screenshot_path); output.write(pixels.data(), pixels.size()); Quit(); } glutSwapBuffers(); _clock.Advance(_example->FrameTime()); }
void Render(ExampleClock& clock) { gl.Clear().ColorBuffer().DepthBuffer(); double time = clock.Now().Seconds(); auto langle = FullCircles(time / 23.0); light_position.Set( GLfloat(Cos(langle) * 20.0), GLfloat((1.2 + Sin(langle)) * 15.0), GLfloat(Sin(langle) * 20.0)); double x = SineWave(time / 13.0); if(x + 0.93 < 0.0) clock.Pace(0.2); else clock.Pace(1.0); auto camera = CamMatrixf::Orbiting( Vec3f(), GLfloat(9.5 + x * 5.1), FullCircles(time / 17.0), Degrees(SineWave(time / 20.0) * 89)); camera_matrix.Set(camera); camera_position.Set(camera.Position()); model_matrix.Set( ModelMatrixf::TranslationX(+2.0f) * ModelMatrixf::RotationX(FullCircles(time / 13.0))); shape.Draw(); model_matrix.Set( ModelMatrixf::TranslationX(-2.0f) * ModelMatrixf::RotationZ(FullCircles(time / 11.0))); shape.Draw(); }
/// Rendering procedure with advanced timing virtual void Render(ExampleClock& clock) { this->Render(clock.Now().Seconds()); }
/** Implementations of the main function may choose to ignore * the result of this function or not call it at all. * This is the overload for advanced timing. */ virtual bool Continue(const ExampleClock& clock) { return this->Continue(clock.Now().Seconds()); }