void Draw(double time, double fade) { // Shadow map shadows_fbo.Bind(FramebufferTarget::Draw); gl.Viewport(shadow_size, shadow_size); gl.Clear().DepthBuffer(); auto light = CamMatrixf::Orbiting( Vec3f(0, side*0.25, 0), side*1.5, Degrees(-time * 27), Degrees(SineWave(time / 19.0)*25 + 45) ); shadow_prog.fade.Set(fade); shadow_prog.camera_matrix.Set(light); shadow_prog.Use(); shadow_vao.Bind(); gl.Enable(Capability::PolygonOffsetFill); cube.Draw(side*side); gl.Disable(Capability::PolygonOffsetFill); gl.Finish(); // On-screen default_fb.Bind(Framebuffer::Target::Draw); gl.Viewport(width, height); gl.Clear().ColorBuffer().DepthBuffer(); auto camera = CamMatrixf::Orbiting( Vec3f(), side*1.1, Degrees(time * 19), Degrees(SineWave(time / 20.0) * 39 + 50) ); display_prog.fade.Set(fade); display_prog.light_pos.Set(light.Position()); display_prog.camera_pos.Set(camera.Position()); display_prog.light_matrix.Set(light); display_prog.camera_matrix.Set(camera); display_prog.Use(); display_vao.Bind(); cube.Draw(side*side); }
void window_loop( const x11::Window& window, AppData& app_data, CommonData& common, RaytracerTarget& rt_target, std::size_t n_threads ) { Context gl; Renderer renderer(app_data, rt_target.tex_unit); renderer.Use(app_data); Saver saver(app_data); window.SelectInput(StructureNotifyMask| PointerMotionMask| KeyPressMask); ::XEvent event; while(!common.Done()) { if(app_data.verbosity > 0) { app_data.logstr() << "Rendering cube face " << common.Face() << std::endl; } // clear the raytrace target rt_target.Clear(app_data); renderer.InitFrame(app_data, common.Face()); renderer.Render(app_data); common.context.SwapBuffers(window); // setup logging period std::chrono::system_clock::duration log_period; if(app_data.verbosity > 4) { log_period = std::chrono::seconds(1); } else if(app_data.verbosity > 3) { log_period = std::chrono::seconds(5); } else if(app_data.verbosity > 2) { log_period = std::chrono::seconds(15); } else if(app_data.verbosity > 1) { log_period = std::chrono::minutes(1); } auto log_time = std::chrono::system_clock::now(); // signal all threads that they can start raytracing tiles common.master_ready.Signal(n_threads); while(!common.FaceDone()) { unsigned slot = 0; while(common.display.NextEvent(event)) { switch(event.type) { case ClientMessage: case DestroyNotify: common.Stop(); break; case ConfigureNotify: app_data.render_width = event.xconfigure.width; app_data.render_height = event.xconfigure.height; break; case MotionNotify: break; case KeyPress: if(::XLookupKeysym(&event.xkey, 0) == XK_Escape) common.Stop(); break; default:; } } if(common.Done()) break; if((slot++ % 5) == 0) { auto lock = common.Lock(); renderer.Render(app_data); gl.Finish(); lock.unlock(); common.context.SwapBuffers(window); } if(app_data.verbosity > 1) { auto now = std::chrono::system_clock::now(); if(log_time + log_period < now) { common.LogProgress(app_data); log_time = now; } } std::chrono::milliseconds period(5); std::this_thread::sleep_for(period); } if(common.Done()) break; // wait for all raytracer threads to finish common.thread_ready.Wait(n_threads); renderer.Render(app_data); common.context.SwapBuffers(window); if(app_data.verbosity > 1) { app_data.logstr() << "Finished cube face " << common.Face() << std::endl; } // save the face image saver.SaveFrame(app_data, rt_target, common.Face()); // switch the face common.NextFace(app_data); // signal that the master is ready to render // the next face common.master_ready.Signal(n_threads); } }
void pbuffer_loop( const glx::Pbuffer& pbuffer, AppData& app_data, CommonData& common, RaytracerTarget& rt_target, std::size_t n_threads ) { Context gl; Renderer renderer(app_data, rt_target.tex_unit); renderer.Use(app_data); Saver saver(app_data); while(!common.Done()) { if(app_data.verbosity > 0) { app_data.logstr() << "Rendering cube face " << common.Face() << std::endl; } // clear the raytrace target rt_target.Clear(app_data); renderer.InitFrame(app_data, common.Face()); renderer.Render(app_data); gl.Finish(); // signal all threads that they can start raytracing tiles common.master_ready.Signal(n_threads); if(common.Done()) break; if(app_data.verbosity > 1) { // setup logging period std::chrono::system_clock::duration log_period; if(app_data.verbosity > 4) { log_period = std::chrono::seconds(1); } else if(app_data.verbosity > 3) { log_period = std::chrono::seconds(5); } else if(app_data.verbosity > 2) { log_period = std::chrono::seconds(10); } else if(app_data.verbosity > 1) { log_period = std::chrono::seconds(30); } auto log_time = std::chrono::system_clock::now(); while(!common.thread_ready.Signalled()) { auto now = std::chrono::system_clock::now(); if(log_time + log_period < now) { common.LogProgress(app_data); log_time = now; } std::chrono::milliseconds period(50); std::this_thread::sleep_for(period); } } // wait for all raytracer threads to finish common.thread_ready.Wait(n_threads); for(unsigned b=0; b!=2; ++b) { renderer.Render(app_data); gl.Finish(); common.context.SwapBuffers(pbuffer); } // save the face image saver.SaveFrame(app_data, rt_target, common.Face()); // switch the face common.NextFace(app_data); // signal that the master is ready to render // the next face common.master_ready.Signal(n_threads); } }
void thread_loop(AppData& app_data, CommonData& common, x11::Display& display, glx::Context& context) { Context gl; ResourceAllocator alloc; RaytraceCopier::Params rtc_params( display, context, common.context ); RaytraceCopier rt_copier(app_data, common.rt_target); RaytracerResources rt_res(app_data, common.rt_data, alloc); Raytracer raytracer(app_data, rt_res); raytracer.Use(app_data); std::vector<unsigned> backlog(app_data.cols()); std::chrono::milliseconds bl_interval(100); while(!common.Done()) { // all threads must wait until // the raytrace target is cleared common.master_ready.Wait(); if(common.Done()) break; raytracer.InitFrame(app_data, common.Face()); auto bl_begin = std::chrono::steady_clock::now(); unsigned tile = 0; while(common.NextFaceTile(tile)) { raytracer.Raytrace(app_data, tile); backlog.push_back(tile); auto now = std::chrono::steady_clock::now(); if(bl_begin + bl_interval < now) { gl.Finish(); auto lock = common.Lock(); for(unsigned bl_tile : backlog) { rt_copier.Copy( app_data, rtc_params, raytracer, bl_tile ); } lock.unlock(); backlog.clear(); bl_begin = now; } else gl.Finish(); } auto lock = common.Lock(); for(unsigned bl_tile : backlog) { rt_copier.Copy( app_data, rtc_params, raytracer, bl_tile ); } lock.unlock(); backlog.clear(); gl.Finish(); // signal to the master that the raytracing // of the current face has finished common.thread_ready.Signal(); if(common.Done()) break; // wait for the master to save the face image common.master_ready.Wait(); } }
void RenderShadowMap(GLuint size) { // matrices auto lt_proj= CamMatrixf::PerspectiveX(Degrees(12), 1.0, 85.0, 110.0); auto light = CamMatrixf::LookingAt(light_position, Vec3f()); // setup the texture Texture::Active(shadow_tex_unit); mask_prog.Use(); Uniform<Mat4f>(mask_prog, "LightMatrix").Set(lt_proj*light); UniformSampler(mask_prog, "ShadowMap").Set(GLuint(shadow_tex_unit)); draw_prog.Use(); Uniform<Mat4f>(draw_prog, "LightMatrix").Set(lt_proj*light); UniformSampler(draw_prog, "ShadowMap").Set(GLuint(shadow_tex_unit)); Texture::Target tex_tgt = Texture::Target::_2D; shadow_map.Bind(tex_tgt); Texture::MinFilter(tex_tgt, TextureMinFilter::Linear); Texture::MagFilter(tex_tgt, TextureMagFilter::Linear); Texture::WrapS(tex_tgt, TextureWrap::ClampToEdge); Texture::WrapT(tex_tgt, TextureWrap::ClampToEdge); Texture::CompareMode(tex_tgt, TextureCompareMode::CompareRefToTexture); Texture::Image2D( tex_tgt, 0, PixelDataInternalFormat::DepthComponent32, size, size, 0, PixelDataFormat::DepthComponent, PixelDataType::Float, nullptr ); // create shadow program ShadowProgram shadow_prog(vert_shader); // VAO for the meshes in shadow program VertexArray vao = meshes.VAOForProgram(shadow_prog); vao.Bind(); // FBO for offscreen rendering of the shadow map Framebuffer::Target fbo_tgt = Framebuffer::Target::Draw; Framebuffer fbo; fbo.Bind(fbo_tgt); Framebuffer::AttachTexture(fbo_tgt, FramebufferAttachment::Depth, shadow_map, 0); // RBO for offscreen rendering Renderbuffer::Target rbo_tgt = Renderbuffer::Target::Renderbuffer; Renderbuffer rbo; rbo.Bind(rbo_tgt); Renderbuffer::Storage(rbo_tgt, PixelDataInternalFormat::RGBA, size, size); Framebuffer::AttachRenderbuffer(fbo_tgt, FramebufferAttachment::Color, rbo); // setup the matrices shadow_prog.projection_matrix.Set(lt_proj); shadow_prog.camera_matrix.Set(light); // setup and clear the viewport gl.Viewport(size, size); gl.Clear().DepthBuffer(); // draw the meshes gl.PolygonOffset(1.0, 1.0); gl.Enable(Capability::PolygonOffsetFill); meshes.Draw(); gl.Disable(Capability::PolygonOffsetFill); gl.Finish(); // bind the default framebuffer DefaultFramebuffer().Bind(Framebuffer::Target::Draw); }