Refactor the demo some more.
Move rendering code into its own module and split up `finish_drawing_frame()`.
This commit is contained in:
parent
29b137c81d
commit
4a4011d303
|
@ -17,22 +17,18 @@ use crate::camera::{Camera, Mode};
|
|||
use crate::concurrent::DemoExecutor;
|
||||
use crate::device::{GroundProgram, GroundVertexArray};
|
||||
use crate::ui::{DemoUI, UIAction};
|
||||
use crate::window::{Event, Keycode, SVGPath, View, Window, WindowSize};
|
||||
use crate::window::{Event, Keycode, SVGPath, Window, WindowSize};
|
||||
use clap::{App, Arg};
|
||||
use image::ColorType;
|
||||
use pathfinder_geometry::basic::point::{Point2DF32, Point2DI32};
|
||||
use pathfinder_geometry::basic::rect::RectF32;
|
||||
use pathfinder_geometry::basic::transform3d::Transform3DF32;
|
||||
use pathfinder_geometry::color::{ColorF, ColorU};
|
||||
use pathfinder_geometry::color::ColorU;
|
||||
use pathfinder_gl::GLDevice;
|
||||
use pathfinder_gpu::Device;
|
||||
use pathfinder_gpu::resources::ResourceLoader;
|
||||
use pathfinder_gpu::{ClearParams, DepthFunc, DepthState, Device, Primitive, RenderState};
|
||||
use pathfinder_gpu::{TextureFormat, UniformData};
|
||||
use pathfinder_renderer::concurrent::scene_proxy::{RenderCommandStream, SceneProxy};
|
||||
use pathfinder_renderer::gpu::renderer::{DestFramebuffer, RenderMode, RenderStats, Renderer};
|
||||
use pathfinder_renderer::gpu_data::RenderCommand;
|
||||
use pathfinder_renderer::gpu::renderer::{DestFramebuffer, RenderStats, Renderer};
|
||||
use pathfinder_renderer::options::{RenderOptions, RenderTransform};
|
||||
use pathfinder_renderer::post::{DEFRINGING_KERNEL_CORE_GRAPHICS, STEM_DARKENING_FACTORS};
|
||||
use pathfinder_renderer::post::STEM_DARKENING_FACTORS;
|
||||
use pathfinder_renderer::scene::Scene;
|
||||
use pathfinder_svg::BuiltSVG;
|
||||
use pathfinder_ui::{MousePosition, UIEvent};
|
||||
|
@ -72,30 +68,16 @@ const TRANSPARENT_BG_COLOR: ColorU = ColorU {
|
|||
a: 0,
|
||||
};
|
||||
|
||||
const GROUND_SOLID_COLOR: ColorU = ColorU {
|
||||
r: 80,
|
||||
g: 80,
|
||||
b: 80,
|
||||
a: 255,
|
||||
};
|
||||
const GROUND_LINE_COLOR: ColorU = ColorU {
|
||||
r: 127,
|
||||
g: 127,
|
||||
b: 127,
|
||||
a: 255,
|
||||
};
|
||||
|
||||
const APPROX_FONT_SIZE: f32 = 16.0;
|
||||
|
||||
const MESSAGE_TIMEOUT_SECS: u64 = 5;
|
||||
|
||||
pub const GRIDLINE_COUNT: i32 = 10;
|
||||
|
||||
pub mod window;
|
||||
|
||||
mod camera;
|
||||
mod concurrent;
|
||||
mod device;
|
||||
mod renderer;
|
||||
mod ui;
|
||||
|
||||
pub struct DemoApp<W> where W: Window {
|
||||
|
@ -224,61 +206,8 @@ impl<W> DemoApp<W> where W: Window {
|
|||
let transform = self.render_transform.clone().unwrap();
|
||||
self.current_frame = Some(Frame::new(transform, ui_events));
|
||||
|
||||
// Initialize and set the appropriate framebuffer.
|
||||
let view = self.ui.mode.view(0);
|
||||
self.window.make_current(view);
|
||||
let window_size = self.window_size.device_size();
|
||||
let scene_count = match self.camera.mode() {
|
||||
Mode::VR => {
|
||||
let viewport = self.window.viewport(View::Stereo(0));
|
||||
if self.scene_framebuffer.is_none()
|
||||
|| self.renderer.device.texture_size(
|
||||
&self
|
||||
.renderer
|
||||
.device
|
||||
.framebuffer_texture(self.scene_framebuffer.as_ref().unwrap()),
|
||||
) != viewport.size()
|
||||
{
|
||||
let scene_texture = self
|
||||
.renderer
|
||||
.device
|
||||
.create_texture(TextureFormat::RGBA8, viewport.size());
|
||||
self.scene_framebuffer =
|
||||
Some(self.renderer.device.create_framebuffer(scene_texture));
|
||||
}
|
||||
self.renderer
|
||||
.replace_dest_framebuffer(DestFramebuffer::Other(
|
||||
self.scene_framebuffer.take().unwrap(),
|
||||
));
|
||||
2
|
||||
}
|
||||
_ => {
|
||||
self.renderer
|
||||
.replace_dest_framebuffer(DestFramebuffer::Default {
|
||||
viewport: self.window.viewport(View::Mono),
|
||||
window_size,
|
||||
});
|
||||
1
|
||||
}
|
||||
};
|
||||
|
||||
// Begin drawing the scene.
|
||||
self.renderer.bind_dest_framebuffer();
|
||||
|
||||
// Clear to the appropriate color.
|
||||
let clear_color = if scene_count == 2 {
|
||||
ColorF::transparent_black()
|
||||
} else {
|
||||
self.background_color().to_f32()
|
||||
};
|
||||
self.renderer.device.clear(&ClearParams {
|
||||
color: Some(clear_color),
|
||||
depth: Some(1.0),
|
||||
stencil: Some(0),
|
||||
..ClearParams::default()
|
||||
});
|
||||
|
||||
scene_count
|
||||
// Prepare to render the frame.
|
||||
self.prepare_frame_rendering()
|
||||
}
|
||||
|
||||
fn build_scene(&mut self) {
|
||||
|
@ -501,155 +430,12 @@ impl<W> DemoApp<W> where W: Window {
|
|||
MousePosition { absolute, relative }
|
||||
}
|
||||
|
||||
pub fn draw_scene(&mut self) {
|
||||
let view = self.ui.mode.view(0);
|
||||
self.window.make_current(view);
|
||||
|
||||
if self.camera.mode() != Mode::VR {
|
||||
self.draw_environment();
|
||||
}
|
||||
|
||||
self.render_vector_scene();
|
||||
|
||||
// Reattach default framebuffer.
|
||||
if self.camera.mode() != Mode::VR {
|
||||
return;
|
||||
}
|
||||
|
||||
if let DestFramebuffer::Other(scene_framebuffer) =
|
||||
self.renderer
|
||||
.replace_dest_framebuffer(DestFramebuffer::Default {
|
||||
viewport: self.window.viewport(View::Mono),
|
||||
window_size: self.window_size.device_size(),
|
||||
})
|
||||
{
|
||||
self.scene_framebuffer = Some(scene_framebuffer);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn composite_scene(&mut self, render_scene_index: u32) {
|
||||
let (eye_transforms, scene_transform, modelview_transform) = match self.camera {
|
||||
Camera::ThreeD {
|
||||
ref eye_transforms,
|
||||
ref scene_transform,
|
||||
ref modelview_transform,
|
||||
..
|
||||
} if eye_transforms.len() > 1 => (eye_transforms, scene_transform, modelview_transform),
|
||||
_ => return,
|
||||
};
|
||||
|
||||
debug!(
|
||||
"scene_transform.perspective={:?}",
|
||||
scene_transform.perspective
|
||||
);
|
||||
debug!(
|
||||
"scene_transform.modelview_to_eye={:?}",
|
||||
scene_transform.modelview_to_eye
|
||||
);
|
||||
debug!("modelview transform={:?}", modelview_transform);
|
||||
|
||||
let viewport = self.window.viewport(View::Stereo(render_scene_index));
|
||||
self.renderer
|
||||
.replace_dest_framebuffer(DestFramebuffer::Default {
|
||||
viewport,
|
||||
window_size: self.window_size.device_size(),
|
||||
});
|
||||
|
||||
self.renderer.bind_draw_framebuffer();
|
||||
self.renderer.device.clear(&ClearParams {
|
||||
color: Some(self.background_color().to_f32()),
|
||||
depth: Some(1.0),
|
||||
stencil: Some(0),
|
||||
rect: Some(viewport),
|
||||
});
|
||||
|
||||
self.draw_environment();
|
||||
|
||||
let scene_framebuffer = self.scene_framebuffer.as_ref().unwrap();
|
||||
let scene_texture = self.renderer.device.framebuffer_texture(scene_framebuffer);
|
||||
|
||||
let quad_scale_transform = Transform3DF32::from_scale(
|
||||
self.scene_metadata.view_box.size().x(),
|
||||
self.scene_metadata.view_box.size().y(),
|
||||
1.0,
|
||||
);
|
||||
|
||||
let scene_transform_matrix = scene_transform
|
||||
.perspective
|
||||
.post_mul(&scene_transform.modelview_to_eye)
|
||||
.post_mul(&modelview_transform.to_transform())
|
||||
.post_mul(&quad_scale_transform);
|
||||
|
||||
let eye_transform = &eye_transforms[render_scene_index as usize];
|
||||
let eye_transform_matrix = eye_transform
|
||||
.perspective
|
||||
.post_mul(&eye_transform.modelview_to_eye)
|
||||
.post_mul(&modelview_transform.to_transform())
|
||||
.post_mul(&quad_scale_transform);
|
||||
|
||||
debug!(
|
||||
"eye transform({}).modelview_to_eye={:?}",
|
||||
render_scene_index, eye_transform.modelview_to_eye
|
||||
);
|
||||
debug!(
|
||||
"eye transform_matrix({})={:?}",
|
||||
render_scene_index, eye_transform_matrix
|
||||
);
|
||||
debug!("---");
|
||||
|
||||
self.renderer.reproject_texture(
|
||||
scene_texture,
|
||||
&scene_transform_matrix.transform,
|
||||
&eye_transform_matrix.transform,
|
||||
);
|
||||
}
|
||||
|
||||
pub fn finish_drawing_frame(&mut self) {
|
||||
if let Some(rendering_time) = self.renderer.shift_timer_query() {
|
||||
self.current_frame
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.scene_rendering_times
|
||||
.push(rendering_time);
|
||||
}
|
||||
|
||||
let build_time = self.build_time.unwrap();
|
||||
let mut frame = self.current_frame.take().unwrap();
|
||||
|
||||
if self.pending_screenshot_path.is_some() {
|
||||
self.take_screenshot();
|
||||
}
|
||||
|
||||
if !frame.scene_stats.is_empty() || !frame.scene_rendering_times.is_empty() {
|
||||
let zero = RenderStats::default();
|
||||
let aggregate_stats = frame.scene_stats.iter().fold(zero, |sum, item| sum + *item);
|
||||
let total_rendering_time = if frame.scene_rendering_times.is_empty() {
|
||||
None
|
||||
} else {
|
||||
let zero = Duration::new(0, 0);
|
||||
Some(
|
||||
frame
|
||||
.scene_rendering_times
|
||||
.iter()
|
||||
.fold(zero, |sum, item| sum + *item),
|
||||
)
|
||||
};
|
||||
self.renderer
|
||||
.debug_ui
|
||||
.add_sample(aggregate_stats, build_time, total_rendering_time);
|
||||
}
|
||||
|
||||
if self.options.ui != UIVisibility::None {
|
||||
let viewport = self.window.viewport(View::Mono);
|
||||
self.window.make_current(View::Mono);
|
||||
self.renderer
|
||||
.replace_dest_framebuffer(DestFramebuffer::Default {
|
||||
viewport,
|
||||
window_size: self.window_size.device_size(),
|
||||
});
|
||||
self.renderer.draw_debug_ui();
|
||||
}
|
||||
self.maybe_take_screenshot();
|
||||
self.update_stats();
|
||||
self.draw_debug_ui();
|
||||
|
||||
let frame = self.current_frame.take().unwrap();
|
||||
for ui_event in &frame.ui_events {
|
||||
self.dirty = true;
|
||||
self.renderer.debug_ui.ui.event_queue.push(*ui_event);
|
||||
|
@ -670,8 +456,46 @@ impl<W> DemoApp<W> where W: Window {
|
|||
&mut ui_action,
|
||||
);
|
||||
}
|
||||
|
||||
self.handle_ui_events(frame, &mut ui_action);
|
||||
|
||||
self.window.present();
|
||||
self.frame_counter += 1;
|
||||
}
|
||||
|
||||
fn update_stats(&mut self) {
|
||||
let frame = self.current_frame.as_mut().unwrap();
|
||||
if let Some(rendering_time) = self.renderer.shift_timer_query() {
|
||||
frame.scene_rendering_times.push(rendering_time);
|
||||
}
|
||||
|
||||
if frame.scene_stats.is_empty() && frame.scene_rendering_times.is_empty() {
|
||||
return
|
||||
}
|
||||
|
||||
let build_time = self.build_time.unwrap();
|
||||
|
||||
let zero = RenderStats::default();
|
||||
let aggregate_stats = frame.scene_stats.iter().fold(zero, |sum, item| sum + *item);
|
||||
let total_rendering_time = if frame.scene_rendering_times.is_empty() {
|
||||
None
|
||||
} else {
|
||||
let zero = Duration::new(0, 0);
|
||||
Some(
|
||||
frame
|
||||
.scene_rendering_times
|
||||
.iter()
|
||||
.fold(zero, |sum, item| sum + *item),
|
||||
)
|
||||
};
|
||||
|
||||
self.renderer.debug_ui.add_sample(aggregate_stats, build_time, total_rendering_time);
|
||||
}
|
||||
|
||||
fn handle_ui_events(&mut self, mut frame: Frame, ui_action: &mut UIAction) {
|
||||
frame.ui_events = self.renderer.debug_ui.ui.event_queue.drain();
|
||||
self.handle_ui_action(&mut ui_action);
|
||||
|
||||
self.handle_ui_action(ui_action);
|
||||
|
||||
// Switch camera mode (2D/3D) if requested.
|
||||
//
|
||||
|
@ -695,111 +519,6 @@ impl<W> DemoApp<W> where W: Window {
|
|||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
self.window.present();
|
||||
self.frame_counter += 1;
|
||||
}
|
||||
|
||||
fn draw_environment(&self) {
|
||||
// TODO(pcwalton): Use the viewport index!
|
||||
|
||||
let frame = &self.current_frame.as_ref().unwrap();
|
||||
|
||||
let perspective = match frame.transform {
|
||||
RenderTransform::Transform2D(..) => return,
|
||||
RenderTransform::Perspective(perspective) => perspective,
|
||||
};
|
||||
|
||||
if self.ui.background_color == BackgroundColor::Transparent {
|
||||
return;
|
||||
}
|
||||
|
||||
let ground_scale = self.scene_metadata.view_box.max_x() * 2.0;
|
||||
|
||||
let mut base_transform = perspective.transform;
|
||||
base_transform = base_transform.post_mul(&Transform3DF32::from_translation(
|
||||
-0.5 * self.scene_metadata.view_box.max_x(),
|
||||
self.scene_metadata.view_box.max_y(),
|
||||
-0.5 * ground_scale,
|
||||
));
|
||||
|
||||
// Fill ground.
|
||||
let mut transform = base_transform;
|
||||
transform =
|
||||
transform.post_mul(&Transform3DF32::from_scale(ground_scale, 1.0, ground_scale));
|
||||
|
||||
let device = &self.renderer.device;
|
||||
device.bind_vertex_array(&self.ground_vertex_array.vertex_array);
|
||||
device.use_program(&self.ground_program.program);
|
||||
device.set_uniform(
|
||||
&self.ground_program.transform_uniform,
|
||||
UniformData::from_transform_3d(&transform),
|
||||
);
|
||||
device.set_uniform(
|
||||
&self.ground_program.ground_color_uniform,
|
||||
UniformData::Vec4(GROUND_SOLID_COLOR.to_f32().0),
|
||||
);
|
||||
device.set_uniform(
|
||||
&self.ground_program.gridline_color_uniform,
|
||||
UniformData::Vec4(GROUND_LINE_COLOR.to_f32().0),
|
||||
);
|
||||
device.set_uniform(&self.ground_program.gridline_count_uniform,
|
||||
UniformData::Int(GRIDLINE_COUNT));
|
||||
device.draw_arrays(
|
||||
Primitive::TriangleFan,
|
||||
4,
|
||||
&RenderState {
|
||||
depth: Some(DepthState {
|
||||
func: DepthFunc::Less,
|
||||
write: true,
|
||||
}),
|
||||
stencil: None,
|
||||
..RenderState::default()
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
fn render_vector_scene(&mut self) {
|
||||
match self.scene_metadata.monochrome_color {
|
||||
None => self.renderer.set_render_mode(RenderMode::Multicolor),
|
||||
Some(fg_color) => {
|
||||
self.renderer.set_render_mode(RenderMode::Monochrome {
|
||||
fg_color: fg_color.to_f32(),
|
||||
bg_color: self.background_color().to_f32(),
|
||||
gamma_correction: self.ui.gamma_correction_effect_enabled,
|
||||
defringing_kernel: if self.ui.subpixel_aa_effect_enabled {
|
||||
// TODO(pcwalton): Select FreeType defringing kernel as necessary.
|
||||
Some(DEFRINGING_KERNEL_CORE_GRAPHICS)
|
||||
} else {
|
||||
None
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
if self.ui.mode == Mode::TwoD {
|
||||
self.renderer.disable_depth();
|
||||
} else {
|
||||
self.renderer.enable_depth();
|
||||
}
|
||||
|
||||
self.renderer.begin_scene();
|
||||
|
||||
// Issue render commands!
|
||||
for command in self.render_command_stream.as_mut().unwrap() {
|
||||
self.renderer.render_command(&command);
|
||||
|
||||
if let RenderCommand::Finish { build_time } = command {
|
||||
self.build_time = Some(build_time);
|
||||
}
|
||||
}
|
||||
|
||||
self.current_frame
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.scene_stats
|
||||
.push(self.renderer.stats);
|
||||
self.renderer.end_scene();
|
||||
}
|
||||
|
||||
fn handle_ui_action(&mut self, ui_action: &mut UIAction) {
|
||||
|
@ -845,23 +564,6 @@ impl<W> DemoApp<W> where W: Window {
|
|||
}
|
||||
}
|
||||
|
||||
fn take_screenshot(&mut self) {
|
||||
let screenshot_path = self.pending_screenshot_path.take().unwrap();
|
||||
let drawable_size = self.window_size.device_size();
|
||||
let pixels = self
|
||||
.renderer
|
||||
.device
|
||||
.read_pixels_from_default_framebuffer(drawable_size);
|
||||
image::save_buffer(
|
||||
screenshot_path,
|
||||
&pixels,
|
||||
drawable_size.x() as u32,
|
||||
drawable_size.y() as u32,
|
||||
ColorType::RGBA(8),
|
||||
)
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
fn background_color(&self) -> ColorU {
|
||||
match self.ui.background_color {
|
||||
BackgroundColor::Light => LIGHT_BG_COLOR,
|
||||
|
|
|
@ -0,0 +1,338 @@
|
|||
// pathfinder/demo/common/src/renderer.rs
|
||||
//
|
||||
// Copyright © 2019 The Pathfinder Project Developers.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
//! Rendering functionality for the demo.
|
||||
|
||||
use crate::camera::{Camera, Mode};
|
||||
use crate::window::{View, Window};
|
||||
use crate::{BackgroundColor, DemoApp, UIVisibility};
|
||||
use image::ColorType;
|
||||
use pathfinder_geometry::color::{ColorF, ColorU};
|
||||
use pathfinder_gpu::{ClearParams, DepthFunc, DepthState, Device, Primitive, RenderState};
|
||||
use pathfinder_gpu::{TextureFormat, UniformData};
|
||||
use pathfinder_geometry::basic::transform3d::Transform3DF32;
|
||||
use pathfinder_renderer::gpu::renderer::{DestFramebuffer, RenderMode};
|
||||
use pathfinder_renderer::gpu_data::RenderCommand;
|
||||
use pathfinder_renderer::options::RenderTransform;
|
||||
use pathfinder_renderer::post::DEFRINGING_KERNEL_CORE_GRAPHICS;
|
||||
|
||||
const GROUND_SOLID_COLOR: ColorU = ColorU {
|
||||
r: 80,
|
||||
g: 80,
|
||||
b: 80,
|
||||
a: 255,
|
||||
};
|
||||
|
||||
const GROUND_LINE_COLOR: ColorU = ColorU {
|
||||
r: 127,
|
||||
g: 127,
|
||||
b: 127,
|
||||
a: 255,
|
||||
};
|
||||
|
||||
const GRIDLINE_COUNT: i32 = 10;
|
||||
|
||||
impl<W> DemoApp<W> where W: Window {
|
||||
pub fn prepare_frame_rendering(&mut self) -> u32 {
|
||||
// Make the GL context current.
|
||||
let view = self.ui.mode.view(0);
|
||||
self.window.make_current(view);
|
||||
|
||||
// Set up framebuffers.
|
||||
let window_size = self.window_size.device_size();
|
||||
let scene_count = match self.camera.mode() {
|
||||
Mode::VR => {
|
||||
let viewport = self.window.viewport(View::Stereo(0));
|
||||
if self.scene_framebuffer.is_none()
|
||||
|| self.renderer.device.texture_size(
|
||||
&self
|
||||
.renderer
|
||||
.device
|
||||
.framebuffer_texture(self.scene_framebuffer.as_ref().unwrap()),
|
||||
) != viewport.size()
|
||||
{
|
||||
let scene_texture = self
|
||||
.renderer
|
||||
.device
|
||||
.create_texture(TextureFormat::RGBA8, viewport.size());
|
||||
self.scene_framebuffer =
|
||||
Some(self.renderer.device.create_framebuffer(scene_texture));
|
||||
}
|
||||
self.renderer
|
||||
.replace_dest_framebuffer(DestFramebuffer::Other(
|
||||
self.scene_framebuffer.take().unwrap(),
|
||||
));
|
||||
2
|
||||
}
|
||||
_ => {
|
||||
self.renderer
|
||||
.replace_dest_framebuffer(DestFramebuffer::Default {
|
||||
viewport: self.window.viewport(View::Mono),
|
||||
window_size,
|
||||
});
|
||||
1
|
||||
}
|
||||
};
|
||||
|
||||
// Begin drawing the scene.
|
||||
self.renderer.bind_dest_framebuffer();
|
||||
|
||||
// Clear to the appropriate color.
|
||||
let clear_color = if scene_count == 2 {
|
||||
ColorF::transparent_black()
|
||||
} else {
|
||||
self.background_color().to_f32()
|
||||
};
|
||||
self.renderer.device.clear(&ClearParams {
|
||||
color: Some(clear_color),
|
||||
depth: Some(1.0),
|
||||
stencil: Some(0),
|
||||
..ClearParams::default()
|
||||
});
|
||||
|
||||
scene_count
|
||||
}
|
||||
|
||||
pub fn draw_scene(&mut self) {
|
||||
let view = self.ui.mode.view(0);
|
||||
self.window.make_current(view);
|
||||
|
||||
if self.camera.mode() != Mode::VR {
|
||||
self.draw_environment();
|
||||
}
|
||||
|
||||
self.render_vector_scene();
|
||||
|
||||
// Reattach default framebuffer.
|
||||
if self.camera.mode() != Mode::VR {
|
||||
return;
|
||||
}
|
||||
|
||||
if let DestFramebuffer::Other(scene_framebuffer) =
|
||||
self.renderer
|
||||
.replace_dest_framebuffer(DestFramebuffer::Default {
|
||||
viewport: self.window.viewport(View::Mono),
|
||||
window_size: self.window_size.device_size(),
|
||||
})
|
||||
{
|
||||
self.scene_framebuffer = Some(scene_framebuffer);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn composite_scene(&mut self, render_scene_index: u32) {
|
||||
let (eye_transforms, scene_transform, modelview_transform) = match self.camera {
|
||||
Camera::ThreeD {
|
||||
ref eye_transforms,
|
||||
ref scene_transform,
|
||||
ref modelview_transform,
|
||||
..
|
||||
} if eye_transforms.len() > 1 => (eye_transforms, scene_transform, modelview_transform),
|
||||
_ => return,
|
||||
};
|
||||
|
||||
debug!(
|
||||
"scene_transform.perspective={:?}",
|
||||
scene_transform.perspective
|
||||
);
|
||||
debug!(
|
||||
"scene_transform.modelview_to_eye={:?}",
|
||||
scene_transform.modelview_to_eye
|
||||
);
|
||||
debug!("modelview transform={:?}", modelview_transform);
|
||||
|
||||
let viewport = self.window.viewport(View::Stereo(render_scene_index));
|
||||
self.renderer
|
||||
.replace_dest_framebuffer(DestFramebuffer::Default {
|
||||
viewport,
|
||||
window_size: self.window_size.device_size(),
|
||||
});
|
||||
|
||||
self.renderer.bind_draw_framebuffer();
|
||||
self.renderer.device.clear(&ClearParams {
|
||||
color: Some(self.background_color().to_f32()),
|
||||
depth: Some(1.0),
|
||||
stencil: Some(0),
|
||||
rect: Some(viewport),
|
||||
});
|
||||
|
||||
self.draw_environment();
|
||||
|
||||
let scene_framebuffer = self.scene_framebuffer.as_ref().unwrap();
|
||||
let scene_texture = self.renderer.device.framebuffer_texture(scene_framebuffer);
|
||||
|
||||
let quad_scale_transform = Transform3DF32::from_scale(
|
||||
self.scene_metadata.view_box.size().x(),
|
||||
self.scene_metadata.view_box.size().y(),
|
||||
1.0,
|
||||
);
|
||||
|
||||
let scene_transform_matrix = scene_transform
|
||||
.perspective
|
||||
.post_mul(&scene_transform.modelview_to_eye)
|
||||
.post_mul(&modelview_transform.to_transform())
|
||||
.post_mul(&quad_scale_transform);
|
||||
|
||||
let eye_transform = &eye_transforms[render_scene_index as usize];
|
||||
let eye_transform_matrix = eye_transform
|
||||
.perspective
|
||||
.post_mul(&eye_transform.modelview_to_eye)
|
||||
.post_mul(&modelview_transform.to_transform())
|
||||
.post_mul(&quad_scale_transform);
|
||||
|
||||
debug!(
|
||||
"eye transform({}).modelview_to_eye={:?}",
|
||||
render_scene_index, eye_transform.modelview_to_eye
|
||||
);
|
||||
debug!(
|
||||
"eye transform_matrix({})={:?}",
|
||||
render_scene_index, eye_transform_matrix
|
||||
);
|
||||
debug!("---");
|
||||
|
||||
self.renderer.reproject_texture(
|
||||
scene_texture,
|
||||
&scene_transform_matrix.transform,
|
||||
&eye_transform_matrix.transform,
|
||||
);
|
||||
}
|
||||
|
||||
// Draws the ground, if applicable.
|
||||
fn draw_environment(&self) {
|
||||
let frame = &self.current_frame.as_ref().unwrap();
|
||||
|
||||
let perspective = match frame.transform {
|
||||
RenderTransform::Transform2D(..) => return,
|
||||
RenderTransform::Perspective(perspective) => perspective,
|
||||
};
|
||||
|
||||
if self.ui.background_color == BackgroundColor::Transparent {
|
||||
return;
|
||||
}
|
||||
|
||||
let ground_scale = self.scene_metadata.view_box.max_x() * 2.0;
|
||||
|
||||
let mut base_transform = perspective.transform;
|
||||
base_transform = base_transform.post_mul(&Transform3DF32::from_translation(
|
||||
-0.5 * self.scene_metadata.view_box.max_x(),
|
||||
self.scene_metadata.view_box.max_y(),
|
||||
-0.5 * ground_scale,
|
||||
));
|
||||
|
||||
// Fill ground.
|
||||
let mut transform = base_transform;
|
||||
transform =
|
||||
transform.post_mul(&Transform3DF32::from_scale(ground_scale, 1.0, ground_scale));
|
||||
|
||||
let device = &self.renderer.device;
|
||||
device.bind_vertex_array(&self.ground_vertex_array.vertex_array);
|
||||
device.use_program(&self.ground_program.program);
|
||||
device.set_uniform(
|
||||
&self.ground_program.transform_uniform,
|
||||
UniformData::from_transform_3d(&transform),
|
||||
);
|
||||
device.set_uniform(
|
||||
&self.ground_program.ground_color_uniform,
|
||||
UniformData::Vec4(GROUND_SOLID_COLOR.to_f32().0),
|
||||
);
|
||||
device.set_uniform(
|
||||
&self.ground_program.gridline_color_uniform,
|
||||
UniformData::Vec4(GROUND_LINE_COLOR.to_f32().0),
|
||||
);
|
||||
device.set_uniform(&self.ground_program.gridline_count_uniform,
|
||||
UniformData::Int(GRIDLINE_COUNT));
|
||||
device.draw_arrays(
|
||||
Primitive::TriangleFan,
|
||||
4,
|
||||
&RenderState {
|
||||
depth: Some(DepthState { func: DepthFunc::Less, write: true }),
|
||||
..RenderState::default()
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
fn render_vector_scene(&mut self) {
|
||||
match self.scene_metadata.monochrome_color {
|
||||
None => self.renderer.set_render_mode(RenderMode::Multicolor),
|
||||
Some(fg_color) => {
|
||||
self.renderer.set_render_mode(RenderMode::Monochrome {
|
||||
fg_color: fg_color.to_f32(),
|
||||
bg_color: self.background_color().to_f32(),
|
||||
gamma_correction: self.ui.gamma_correction_effect_enabled,
|
||||
defringing_kernel: if self.ui.subpixel_aa_effect_enabled {
|
||||
// TODO(pcwalton): Select FreeType defringing kernel as necessary.
|
||||
Some(DEFRINGING_KERNEL_CORE_GRAPHICS)
|
||||
} else {
|
||||
None
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
if self.ui.mode == Mode::TwoD {
|
||||
self.renderer.disable_depth();
|
||||
} else {
|
||||
self.renderer.enable_depth();
|
||||
}
|
||||
|
||||
self.renderer.begin_scene();
|
||||
|
||||
// Issue render commands!
|
||||
for command in self.render_command_stream.as_mut().unwrap() {
|
||||
self.renderer.render_command(&command);
|
||||
|
||||
if let RenderCommand::Finish { build_time } = command {
|
||||
self.build_time = Some(build_time);
|
||||
}
|
||||
}
|
||||
|
||||
self.current_frame
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.scene_stats
|
||||
.push(self.renderer.stats);
|
||||
self.renderer.end_scene();
|
||||
}
|
||||
|
||||
pub fn maybe_take_screenshot(&mut self) {
|
||||
let screenshot_path = match self.pending_screenshot_path.take() {
|
||||
None => return,
|
||||
Some(screenshot_path) => screenshot_path,
|
||||
};
|
||||
|
||||
let drawable_size = self.window_size.device_size();
|
||||
let pixels = self
|
||||
.renderer
|
||||
.device
|
||||
.read_pixels_from_default_framebuffer(drawable_size);
|
||||
image::save_buffer(
|
||||
screenshot_path,
|
||||
&pixels,
|
||||
drawable_size.x() as u32,
|
||||
drawable_size.y() as u32,
|
||||
ColorType::RGBA(8),
|
||||
)
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
pub fn draw_debug_ui(&mut self) {
|
||||
if self.options.ui == UIVisibility::None {
|
||||
return;
|
||||
}
|
||||
|
||||
let viewport = self.window.viewport(View::Mono);
|
||||
self.window.make_current(View::Mono);
|
||||
self.renderer.replace_dest_framebuffer(DestFramebuffer::Default {
|
||||
viewport,
|
||||
window_size: self.window_size.device_size(),
|
||||
});
|
||||
|
||||
self.renderer.draw_debug_ui();
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue