Add some ground to the 3D scene, no depth buffer yet
This commit is contained in:
parent
0983812b90
commit
e4803cfddf
Binary file not shown.
After Width: | Height: | Size: 973 B |
Binary file not shown.
After Width: | Height: | Size: 879 B |
Binary file not shown.
After Width: | Height: | Size: 868 B |
|
@ -0,0 +1,21 @@
|
|||
#version 330
|
||||
|
||||
// pathfinder/demo/resources/shaders/demo_ground.fs.glsl
|
||||
//
|
||||
// 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.
|
||||
|
||||
precision highp float;
|
||||
|
||||
uniform vec4 uColor;
|
||||
|
||||
out vec4 oFragColor;
|
||||
|
||||
void main() {
|
||||
oFragColor = uColor;
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
#version 330
|
||||
|
||||
// pathfinder/demo/resources/shaders/demo_ground.vs.glsl
|
||||
//
|
||||
// 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.
|
||||
|
||||
precision highp float;
|
||||
|
||||
uniform mat4 uTransform;
|
||||
|
||||
in vec2 aPosition;
|
||||
|
||||
void main() {
|
||||
gl_Position = uTransform * vec4(aPosition.x * 800.0, -30.0, aPosition.y * 800.0, 1.0);
|
||||
}
|
434
demo/src/main.rs
434
demo/src/main.rs
|
@ -13,11 +13,14 @@
|
|||
use crate::ui::{DemoUI, UIAction, UIEvent};
|
||||
use clap::{App, Arg};
|
||||
use euclid::Size2D;
|
||||
use gl::types::GLsizei;
|
||||
use jemallocator;
|
||||
use pathfinder_geometry::basic::point::{Point2DF32, Point2DI32, Point3DF32};
|
||||
use pathfinder_geometry::basic::rect::RectF32;
|
||||
use pathfinder_geometry::basic::transform2d::Transform2DF32;
|
||||
use pathfinder_geometry::basic::transform3d::{Perspective, Transform3DF32};
|
||||
use pathfinder_gl::device::{Buffer, BufferTarget, BufferUploadMode, Program, Uniform};
|
||||
use pathfinder_gl::device::{VertexArray, VertexAttr};
|
||||
use pathfinder_gl::renderer::Renderer;
|
||||
use pathfinder_renderer::builder::{RenderOptions, RenderTransform, SceneBuilder};
|
||||
use pathfinder_renderer::gpu_data::BuiltScene;
|
||||
|
@ -56,11 +59,15 @@ const CAMERA_SCALE_SPEED_2D: f32 = 2.0;
|
|||
// How much the scene is scaled when a zoom button is clicked.
|
||||
const CAMERA_ZOOM_AMOUNT_2D: f32 = 0.1;
|
||||
|
||||
const BACKGROUND_COLOR: ColorU = ColorU { r: 32, g: 32, b: 32, a: 255 };
|
||||
const BACKGROUND_COLOR: ColorU = ColorU { r: 32, g: 32, b: 32, a: 255 };
|
||||
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 WORLD_SCALE: f32 = 1.0 / 800.0;
|
||||
const WORLD_SCALE: f32 = 800.0;
|
||||
const GROUND_SCALE: f32 = 2.0;
|
||||
const GRIDLINE_COUNT: u8 = 10;
|
||||
|
||||
mod ui;
|
||||
|
||||
|
@ -90,6 +97,11 @@ struct DemoApp {
|
|||
ui: DemoUI,
|
||||
scene_thread_proxy: SceneThreadProxy,
|
||||
renderer: Renderer,
|
||||
|
||||
device: DemoDevice,
|
||||
ground_program: GroundProgram,
|
||||
ground_solid_vertex_array: GroundSolidVertexArray,
|
||||
ground_line_vertex_array: GroundLineVertexArray,
|
||||
}
|
||||
|
||||
impl DemoApp {
|
||||
|
@ -121,11 +133,18 @@ impl DemoApp {
|
|||
let drawable_size = Size2D::new(drawable_width, drawable_height);
|
||||
|
||||
let base_scene = load_scene(&options.input_path);
|
||||
let renderer = Renderer::new(&drawable_size);
|
||||
let scene_thread_proxy = SceneThreadProxy::new(base_scene, options.clone());
|
||||
update_drawable_size(&window, &scene_thread_proxy);
|
||||
|
||||
let camera = if options.threed { Camera::three_d() } else { Camera::two_d() };
|
||||
|
||||
let grid_vertex_positions = create_grid_vertex_positions();
|
||||
let ground_program = GroundProgram::new();
|
||||
let ground_solid_vertex_array =
|
||||
GroundSolidVertexArray::new(&ground_program, &renderer.quad_vertex_positions_buffer());
|
||||
let ground_line_vertex_array = GroundLineVertexArray::new(&ground_program);
|
||||
|
||||
DemoApp {
|
||||
window,
|
||||
sdl_context,
|
||||
|
@ -144,7 +163,12 @@ impl DemoApp {
|
|||
|
||||
ui: DemoUI::new(options),
|
||||
scene_thread_proxy,
|
||||
renderer: Renderer::new(&drawable_size),
|
||||
renderer,
|
||||
|
||||
device: DemoDevice,
|
||||
ground_program,
|
||||
ground_solid_vertex_array,
|
||||
ground_line_vertex_array,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -165,31 +189,14 @@ impl DemoApp {
|
|||
|
||||
fn build_scene(&mut self) {
|
||||
let (drawable_width, drawable_height) = self.window.drawable_size();
|
||||
let drawable_size = Size2D::new(drawable_width, drawable_height);
|
||||
let drawable_size = Point2DI32::new(drawable_width as i32, drawable_height as i32);
|
||||
|
||||
let render_transform = match self.camera {
|
||||
Camera::ThreeD { ref mut position, velocity, yaw, pitch } => {
|
||||
let rotation = Transform3DF32::from_rotation(-yaw, -pitch, 0.0);
|
||||
|
||||
if !velocity.is_zero() {
|
||||
*position = *position + rotation.transform_point(velocity);
|
||||
Camera::ThreeD { ref mut transform, ref mut velocity } => {
|
||||
if transform.offset(*velocity) {
|
||||
self.dirty = true;
|
||||
}
|
||||
|
||||
let aspect = drawable_size.width as f32 / drawable_size.height as f32;
|
||||
let mut transform =
|
||||
Transform3DF32::from_perspective(FRAC_PI_4, aspect, 0.025, 100.0);
|
||||
|
||||
transform = transform.post_mul(&Transform3DF32::from_scale(WORLD_SCALE,
|
||||
WORLD_SCALE,
|
||||
WORLD_SCALE));
|
||||
transform = transform.post_mul(&Transform3DF32::from_rotation(yaw, pitch, 0.0));
|
||||
let translation = position.scale(-1.0);
|
||||
transform = transform.post_mul(&Transform3DF32::from_translation(translation.x(),
|
||||
translation.y(),
|
||||
translation.z()));
|
||||
|
||||
RenderTransform::Perspective(Perspective::new(&transform, &drawable_size))
|
||||
RenderTransform::Perspective(transform.to_perspective(drawable_size, true))
|
||||
}
|
||||
Camera::TwoD(transform) => RenderTransform::Transform2D(transform),
|
||||
};
|
||||
|
@ -242,10 +249,9 @@ impl DemoApp {
|
|||
ui_event = UIEvent::MouseDown(point);
|
||||
}
|
||||
Event::MouseMotion { xrel, yrel, .. } if self.mouselook_enabled => {
|
||||
if let Camera::ThreeD { ref mut yaw, ref mut pitch, .. } =
|
||||
self.camera {
|
||||
*yaw += xrel as f32 * MOUSELOOK_ROTATION_SPEED;
|
||||
*pitch -= yrel as f32 * MOUSELOOK_ROTATION_SPEED;
|
||||
if let Camera::ThreeD { ref mut transform, .. } = self.camera {
|
||||
transform.yaw += xrel as f32 * MOUSELOOK_ROTATION_SPEED;
|
||||
transform.pitch += yrel as f32 * MOUSELOOK_ROTATION_SPEED;
|
||||
self.dirty = true;
|
||||
}
|
||||
}
|
||||
|
@ -315,105 +321,155 @@ impl DemoApp {
|
|||
fn draw_scene(&mut self, render_msg: SceneToMainMsg, mut ui_event: UIEvent) {
|
||||
let SceneToMainMsg::Render { built_scene, tile_time } = render_msg;
|
||||
|
||||
unsafe {
|
||||
gl::BindFramebuffer(gl::FRAMEBUFFER, 0);
|
||||
gl::ClearColor(BACKGROUND_COLOR.r as f32 / 255.0,
|
||||
BACKGROUND_COLOR.g as f32 / 255.0,
|
||||
BACKGROUND_COLOR.b as f32 / 255.0,
|
||||
BACKGROUND_COLOR.a as f32 / 255.0);
|
||||
gl::Clear(gl::COLOR_BUFFER_BIT);
|
||||
self.device.clear();
|
||||
self.draw_environment();
|
||||
self.render_vector_scene(&built_scene);
|
||||
|
||||
if self.ui.gamma_correction_effect_enabled {
|
||||
self.renderer.enable_gamma_correction(BACKGROUND_COLOR);
|
||||
} else {
|
||||
self.renderer.disable_gamma_correction();
|
||||
let rendering_time = self.renderer.shift_timer_query();
|
||||
self.renderer.debug_ui.add_sample(tile_time, rendering_time);
|
||||
self.renderer.debug_ui.draw();
|
||||
|
||||
if !ui_event.is_none() {
|
||||
self.dirty = true;
|
||||
}
|
||||
|
||||
let mut ui_action = UIAction::None;
|
||||
self.ui.update(&mut self.renderer.debug_ui, &mut ui_event, &mut ui_action);
|
||||
self.handle_ui_action(&mut ui_action);
|
||||
|
||||
// Switch camera mode (2D/3D) if requested.
|
||||
//
|
||||
// FIXME(pcwalton): This mess should really be an MVC setup.
|
||||
match (&self.camera, self.ui.threed_enabled) {
|
||||
(&Camera::TwoD { .. }, true) => self.camera = Camera::three_d(),
|
||||
(&Camera::ThreeD { .. }, false) => self.camera = Camera::two_d(),
|
||||
_ => {}
|
||||
}
|
||||
|
||||
match ui_event {
|
||||
UIEvent::MouseDown(_) if self.camera.is_3d() => {
|
||||
// If nothing handled the mouse-down event, toggle mouselook.
|
||||
self.mouselook_enabled = !self.mouselook_enabled;
|
||||
}
|
||||
|
||||
if self.ui.subpixel_aa_effect_enabled {
|
||||
self.renderer.enable_subpixel_aa(&DEFRINGING_KERNEL_CORE_GRAPHICS);
|
||||
} else {
|
||||
self.renderer.disable_subpixel_aa();
|
||||
}
|
||||
|
||||
self.renderer.render_scene(&built_scene);
|
||||
|
||||
let rendering_time = self.renderer.shift_timer_query();
|
||||
self.renderer.debug_ui.add_sample(tile_time, rendering_time);
|
||||
self.renderer.debug_ui.draw();
|
||||
|
||||
if !ui_event.is_none() {
|
||||
self.dirty = true;
|
||||
}
|
||||
|
||||
let mut ui_action = UIAction::None;
|
||||
self.ui.update(&mut self.renderer.debug_ui, &mut ui_event, &mut ui_action);
|
||||
|
||||
// Handle UI actions.
|
||||
match ui_action {
|
||||
UIAction::None => {}
|
||||
UIAction::OpenFile(path) => {
|
||||
let scene = load_scene(&path);
|
||||
self.scene_thread_proxy.load_scene(scene);
|
||||
update_drawable_size(&self.window, &self.scene_thread_proxy);
|
||||
self.dirty = true;
|
||||
}
|
||||
UIAction::ZoomIn => {
|
||||
if let Camera::TwoD(ref mut transform) = self.camera {
|
||||
let scale = Point2DF32::splat(1.0 + CAMERA_ZOOM_AMOUNT_2D);
|
||||
let center = center_of_window(&self.window);
|
||||
*transform = transform.post_translate(-center)
|
||||
.post_scale(scale)
|
||||
.post_translate(center);
|
||||
self.dirty = true;
|
||||
}
|
||||
}
|
||||
UIAction::ZoomOut => {
|
||||
if let Camera::TwoD(ref mut transform) = self.camera {
|
||||
let scale = Point2DF32::splat(1.0 - CAMERA_ZOOM_AMOUNT_2D);
|
||||
let center = center_of_window(&self.window);
|
||||
*transform = transform.post_translate(-center)
|
||||
.post_scale(scale)
|
||||
.post_translate(center);
|
||||
self.dirty = true;
|
||||
}
|
||||
}
|
||||
UIAction::Rotate(theta) => {
|
||||
if let Camera::TwoD(ref mut transform) = self.camera {
|
||||
let old_rotation = transform.rotation();
|
||||
let center = center_of_window(&self.window);
|
||||
*transform = transform.post_translate(-center)
|
||||
.post_rotate(theta - old_rotation)
|
||||
.post_translate(center);
|
||||
}
|
||||
UIEvent::MouseDragged { relative_position, .. } => {
|
||||
if let Camera::TwoD(ref mut transform) = self.camera {
|
||||
*transform = transform.post_translate(relative_position.to_f32());
|
||||
}
|
||||
}
|
||||
|
||||
// Switch camera mode (2D/3D) if requested.
|
||||
//
|
||||
// FIXME(pcwalton): This mess should really be an MVC setup.
|
||||
match (&self.camera, self.ui.threed_enabled) {
|
||||
(&Camera::TwoD { .. }, true) => self.camera = Camera::three_d(),
|
||||
(&Camera::ThreeD { .. }, false) => self.camera = Camera::two_d(),
|
||||
_ => {}
|
||||
}
|
||||
|
||||
match ui_event {
|
||||
UIEvent::MouseDown(_) if self.camera.is_3d() => {
|
||||
// If nothing handled the mouse-down event, toggle mouselook.
|
||||
self.mouselook_enabled = !self.mouselook_enabled;
|
||||
}
|
||||
UIEvent::MouseDragged { relative_position, .. } => {
|
||||
if let Camera::TwoD(ref mut transform) = self.camera {
|
||||
*transform = transform.post_translate(relative_position.to_f32());
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
self.window.gl_swap_window();
|
||||
self.frame_counter += 1;
|
||||
}
|
||||
|
||||
fn draw_environment(&self) {
|
||||
let transform = match self.camera {
|
||||
Camera::TwoD(..) => return,
|
||||
Camera::ThreeD { ref transform, .. } => *transform,
|
||||
};
|
||||
|
||||
let (drawable_width, drawable_height) = self.window.drawable_size();
|
||||
let drawable_size = Point2DI32::new(drawable_width as i32, drawable_height as i32);
|
||||
let perspective = transform.to_perspective(drawable_size, false);
|
||||
|
||||
unsafe {
|
||||
let mut transform = perspective.transform;
|
||||
transform =
|
||||
transform.post_mul(&Transform3DF32::from_scale(GROUND_SCALE, 1.0, GROUND_SCALE));
|
||||
gl::BindVertexArray(self.ground_solid_vertex_array.vertex_array.gl_vertex_array);
|
||||
gl::UseProgram(self.ground_program.program.gl_program);
|
||||
gl::UniformMatrix4fv(self.ground_program.transform_uniform.location,
|
||||
1,
|
||||
gl::FALSE,
|
||||
transform.as_ptr());
|
||||
let color = GROUND_SOLID_COLOR.to_f32();
|
||||
gl::Uniform4f(self.ground_program.color_uniform.location,
|
||||
color.r(),
|
||||
color.g(),
|
||||
color.b(),
|
||||
color.a());
|
||||
gl::Disable(gl::BLEND);
|
||||
gl::DrawArrays(gl::TRIANGLE_FAN, 0, 4);
|
||||
|
||||
let mut transform = perspective.transform;
|
||||
let gridline_scale = GROUND_SCALE / GRIDLINE_COUNT as f32;
|
||||
transform = transform.post_mul(&Transform3DF32::from_scale(gridline_scale,
|
||||
1.0,
|
||||
gridline_scale));
|
||||
gl::BindVertexArray(self.ground_line_vertex_array.vertex_array.gl_vertex_array);
|
||||
gl::UseProgram(self.ground_program.program.gl_program);
|
||||
gl::UniformMatrix4fv(self.ground_program.transform_uniform.location,
|
||||
1,
|
||||
gl::FALSE,
|
||||
transform.as_ptr());
|
||||
let color = GROUND_LINE_COLOR.to_f32();
|
||||
gl::Uniform4f(self.ground_program.color_uniform.location,
|
||||
color.r(),
|
||||
color.g(),
|
||||
color.b(),
|
||||
color.a());
|
||||
gl::Disable(gl::BLEND);
|
||||
gl::DrawArrays(gl::LINES, 0, (GRIDLINE_COUNT as GLsizei + 1) * 4);
|
||||
}
|
||||
}
|
||||
|
||||
fn render_vector_scene(&mut self, built_scene: &BuiltScene) {
|
||||
if self.ui.gamma_correction_effect_enabled {
|
||||
self.renderer.enable_gamma_correction(BACKGROUND_COLOR);
|
||||
} else {
|
||||
self.renderer.disable_gamma_correction();
|
||||
}
|
||||
|
||||
if self.ui.subpixel_aa_effect_enabled {
|
||||
self.renderer.enable_subpixel_aa(&DEFRINGING_KERNEL_CORE_GRAPHICS);
|
||||
} else {
|
||||
self.renderer.disable_subpixel_aa();
|
||||
}
|
||||
|
||||
self.renderer.render_scene(&built_scene);
|
||||
}
|
||||
|
||||
fn handle_ui_action(&mut self, ui_action: &mut UIAction) {
|
||||
match ui_action {
|
||||
UIAction::None => {}
|
||||
UIAction::OpenFile(ref path) => {
|
||||
let scene = load_scene(&path);
|
||||
self.scene_thread_proxy.load_scene(scene);
|
||||
update_drawable_size(&self.window, &self.scene_thread_proxy);
|
||||
self.dirty = true;
|
||||
}
|
||||
UIAction::ZoomIn => {
|
||||
if let Camera::TwoD(ref mut transform) = self.camera {
|
||||
let scale = Point2DF32::splat(1.0 + CAMERA_ZOOM_AMOUNT_2D);
|
||||
let center = center_of_window(&self.window);
|
||||
*transform = transform.post_translate(-center)
|
||||
.post_scale(scale)
|
||||
.post_translate(center);
|
||||
self.dirty = true;
|
||||
}
|
||||
}
|
||||
UIAction::ZoomOut => {
|
||||
if let Camera::TwoD(ref mut transform) = self.camera {
|
||||
let scale = Point2DF32::splat(1.0 - CAMERA_ZOOM_AMOUNT_2D);
|
||||
let center = center_of_window(&self.window);
|
||||
*transform = transform.post_translate(-center)
|
||||
.post_scale(scale)
|
||||
.post_translate(center);
|
||||
self.dirty = true;
|
||||
}
|
||||
}
|
||||
UIAction::Rotate(theta) => {
|
||||
if let Camera::TwoD(ref mut transform) = self.camera {
|
||||
let old_rotation = transform.rotation();
|
||||
let center = center_of_window(&self.window);
|
||||
*transform = transform.post_translate(-center)
|
||||
.post_rotate(*theta - old_rotation)
|
||||
.post_translate(center);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct SceneThreadProxy {
|
||||
|
@ -598,7 +654,7 @@ fn center_of_window(window: &Window) -> Point2DF32 {
|
|||
|
||||
enum Camera {
|
||||
TwoD(Transform2DF32),
|
||||
ThreeD { position: Point3DF32, velocity: Point3DF32, yaw: f32, pitch: f32 },
|
||||
ThreeD { transform: CameraTransform3D, velocity: Point3DF32 },
|
||||
}
|
||||
|
||||
impl Camera {
|
||||
|
@ -607,15 +663,143 @@ impl Camera {
|
|||
}
|
||||
|
||||
fn three_d() -> Camera {
|
||||
Camera::ThreeD {
|
||||
position: Point3DF32::new(500.0, 500.0, 3000.0, 1.0),
|
||||
velocity: Point3DF32::new(0.0, 0.0, 0.0, 1.0),
|
||||
yaw: 0.0,
|
||||
pitch: 0.0,
|
||||
}
|
||||
Camera::ThreeD { transform: CameraTransform3D::new(), velocity: Point3DF32::default() }
|
||||
}
|
||||
|
||||
fn is_3d(&self) -> bool {
|
||||
match *self { Camera::ThreeD { .. } => true, Camera::TwoD { .. } => false }
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
struct CameraTransform3D {
|
||||
position: Point3DF32,
|
||||
yaw: f32,
|
||||
pitch: f32,
|
||||
}
|
||||
|
||||
impl CameraTransform3D {
|
||||
fn new() -> CameraTransform3D {
|
||||
CameraTransform3D {
|
||||
position: Point3DF32::new(500.0, 500.0, 3000.0, 1.0),
|
||||
yaw: 0.0,
|
||||
pitch: 0.0,
|
||||
}
|
||||
}
|
||||
|
||||
fn offset(&mut self, vector: Point3DF32) -> bool {
|
||||
let update = !vector.is_zero();
|
||||
if update {
|
||||
let rotation = Transform3DF32::from_rotation(-self.yaw, -self.pitch, 0.0);
|
||||
self.position = self.position + rotation.transform_point(vector);
|
||||
}
|
||||
update
|
||||
}
|
||||
|
||||
fn to_perspective(&self, drawable_size: Point2DI32, flip_y: bool) -> Perspective {
|
||||
let aspect = drawable_size.x() as f32 / drawable_size.y() as f32;
|
||||
let mut transform = Transform3DF32::from_perspective(FRAC_PI_4, aspect, 0.025, 100.0);
|
||||
|
||||
let scale_inv = 1.0 / WORLD_SCALE;
|
||||
transform = transform.post_mul(&Transform3DF32::from_rotation(self.yaw, self.pitch, 0.0));
|
||||
transform = transform.post_mul(&Transform3DF32::from_uniform_scale(scale_inv));
|
||||
transform = transform.post_mul(&Transform3DF32::from_translation(-self.position.x(),
|
||||
-self.position.y(),
|
||||
-self.position.z()));
|
||||
|
||||
if flip_y {
|
||||
transform = transform.post_mul(&Transform3DF32::from_scale(1.0, -1.0, 1.0));
|
||||
transform =
|
||||
transform.post_mul(&Transform3DF32::from_translation(0.0, -WORLD_SCALE, 0.0));
|
||||
}
|
||||
|
||||
let drawable_size = Size2D::new(drawable_size.x() as u32, drawable_size.y() as u32);
|
||||
Perspective::new(&transform, &drawable_size)
|
||||
}
|
||||
}
|
||||
|
||||
struct DemoDevice;
|
||||
|
||||
impl DemoDevice {
|
||||
fn clear(&self) {
|
||||
let color = BACKGROUND_COLOR.to_f32();
|
||||
unsafe {
|
||||
gl::BindFramebuffer(gl::FRAMEBUFFER, 0);
|
||||
gl::ClearColor(color.r(), color.g(), color.b(), color.a());
|
||||
gl::Clear(gl::COLOR_BUFFER_BIT);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct GroundProgram {
|
||||
program: Program,
|
||||
transform_uniform: Uniform,
|
||||
color_uniform: Uniform,
|
||||
}
|
||||
|
||||
impl GroundProgram {
|
||||
fn new() -> GroundProgram {
|
||||
let program = Program::new("demo_ground");
|
||||
let transform_uniform = Uniform::new(&program, "Transform");
|
||||
let color_uniform = Uniform::new(&program, "Color");
|
||||
GroundProgram { program, transform_uniform, color_uniform }
|
||||
}
|
||||
}
|
||||
|
||||
struct GroundSolidVertexArray {
|
||||
vertex_array: VertexArray,
|
||||
}
|
||||
|
||||
impl GroundSolidVertexArray {
|
||||
fn new(ground_program: &GroundProgram, quad_vertex_positions_buffer: &Buffer)
|
||||
-> GroundSolidVertexArray {
|
||||
let vertex_array = VertexArray::new();
|
||||
unsafe {
|
||||
let position_attr = VertexAttr::new(&ground_program.program, "Position");
|
||||
|
||||
gl::BindVertexArray(vertex_array.gl_vertex_array);
|
||||
gl::UseProgram(ground_program.program.gl_program);
|
||||
gl::BindBuffer(gl::ARRAY_BUFFER, quad_vertex_positions_buffer.gl_buffer);
|
||||
position_attr.configure_float(2, gl::UNSIGNED_BYTE, false, 0, 0, 0);
|
||||
}
|
||||
|
||||
GroundSolidVertexArray { vertex_array }
|
||||
}
|
||||
}
|
||||
|
||||
struct GroundLineVertexArray {
|
||||
vertex_array: VertexArray,
|
||||
grid_vertex_positions_buffer: Buffer,
|
||||
}
|
||||
|
||||
impl GroundLineVertexArray {
|
||||
fn new(ground_program: &GroundProgram) -> GroundLineVertexArray {
|
||||
let grid_vertex_positions_buffer = Buffer::new();
|
||||
grid_vertex_positions_buffer.upload(&create_grid_vertex_positions(),
|
||||
BufferTarget::Vertex,
|
||||
BufferUploadMode::Static);
|
||||
|
||||
let vertex_array = VertexArray::new();
|
||||
unsafe {
|
||||
let position_attr = VertexAttr::new(&ground_program.program, "Position");
|
||||
|
||||
gl::BindVertexArray(vertex_array.gl_vertex_array);
|
||||
gl::UseProgram(ground_program.program.gl_program);
|
||||
gl::BindBuffer(gl::ARRAY_BUFFER, grid_vertex_positions_buffer.gl_buffer);
|
||||
position_attr.configure_float(2, gl::UNSIGNED_BYTE, false, 0, 0, 0);
|
||||
}
|
||||
|
||||
GroundLineVertexArray { vertex_array, grid_vertex_positions_buffer }
|
||||
}
|
||||
}
|
||||
|
||||
fn create_grid_vertex_positions() -> Vec<(u8, u8)> {
|
||||
let mut positions = vec![];
|
||||
for index in 0..(GRIDLINE_COUNT + 1) {
|
||||
positions.extend_from_slice(&[
|
||||
(0, index), (GRIDLINE_COUNT, index),
|
||||
(index, 0), (index, GRIDLINE_COUNT),
|
||||
]);
|
||||
}
|
||||
positions
|
||||
}
|
||||
|
|
|
@ -232,7 +232,7 @@ impl Sub<Point2DI32> for Point2DI32 {
|
|||
}
|
||||
|
||||
/// 3D homogeneous points.
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Default)]
|
||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||
pub struct Point3DF32(pub F32x4);
|
||||
|
||||
impl Point3DF32 {
|
||||
|
@ -350,3 +350,12 @@ impl Mul<Point3DF32> for Point3DF32 {
|
|||
Point3DF32(self.0 * other.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for Point3DF32 {
|
||||
#[inline]
|
||||
fn default() -> Point3DF32 {
|
||||
let mut point = F32x4::default();
|
||||
point.set_w(1.0);
|
||||
Point3DF32(point)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@ use std::ops::{Add, Neg};
|
|||
///
|
||||
/// In column-major order.
|
||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||
#[repr(C)]
|
||||
pub struct Transform3DF32 {
|
||||
c0: F32x4,
|
||||
c1: F32x4,
|
||||
|
@ -64,6 +65,11 @@ impl Transform3DF32 {
|
|||
0.0, 0.0, 0.0, 1.0)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn from_uniform_scale(factor: f32) -> Transform3DF32 {
|
||||
Transform3DF32::from_scale(factor, factor, factor)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn from_translation(x: f32, y: f32, z: f32) -> Transform3DF32 {
|
||||
Transform3DF32::row_major(1.0, 0.0, 0.0, x,
|
||||
|
@ -229,6 +235,11 @@ impl Transform3DF32 {
|
|||
self.c2.approx_eq(other.c2, epsilon) &&
|
||||
self.c3.approx_eq(other.c3, epsilon)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn as_ptr(&self) -> *const f32 {
|
||||
(&self.c0) as *const F32x4 as *const f32
|
||||
}
|
||||
}
|
||||
|
||||
impl Add<Matrix2x2F32> for Matrix2x2F32 {
|
||||
|
@ -261,7 +272,10 @@ impl Perspective {
|
|||
|
||||
#[inline]
|
||||
pub fn transform_point_2d(&self, point: &Point2DF32) -> Point2DF32 {
|
||||
let point = self.transform.transform_point(point.to_3d()).perspective_divide().to_2d();
|
||||
let point = self.transform
|
||||
.transform_point(point.to_3d())
|
||||
.perspective_divide()
|
||||
.to_2d() * Point2DF32::new(1.0, -1.0);
|
||||
let window_size = self.window_size.to_f32();
|
||||
let size_scale = Point2DF32::new(window_size.width * 0.5, window_size.height * 0.5);
|
||||
(point + Point2DF32::splat(1.0)) * size_scale
|
||||
|
|
|
@ -18,6 +18,30 @@ use std::io::Read;
|
|||
use std::mem;
|
||||
use std::ptr;
|
||||
|
||||
pub struct VertexArray {
|
||||
pub gl_vertex_array: GLuint,
|
||||
}
|
||||
|
||||
impl Drop for VertexArray {
|
||||
#[inline]
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
gl::DeleteVertexArrays(1, &mut self.gl_vertex_array);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl VertexArray {
|
||||
#[inline]
|
||||
pub fn new() -> VertexArray {
|
||||
unsafe {
|
||||
let mut array = VertexArray { gl_vertex_array: 0 };
|
||||
gl::GenVertexArrays(1, &mut array.gl_vertex_array);
|
||||
array
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct VertexAttr {
|
||||
attr: GLuint,
|
||||
}
|
||||
|
|
|
@ -10,9 +10,9 @@
|
|||
|
||||
use crate::debug::DebugUI;
|
||||
use crate::device::{Buffer, BufferTarget, BufferUploadMode, Framebuffer, Program, Texture};
|
||||
use crate::device::{TimerQuery, Uniform, VertexAttr};
|
||||
use crate::device::{TimerQuery, Uniform, VertexArray, VertexAttr};
|
||||
use euclid::Size2D;
|
||||
use gl::types::{GLfloat, GLint, GLuint};
|
||||
use gl::types::{GLfloat, GLint};
|
||||
use pathfinder_renderer::gpu_data::{Batch, BuiltScene, SolidTileScenePrimitive};
|
||||
use pathfinder_renderer::paint::{ColorU, ObjectShader};
|
||||
use pathfinder_renderer::post::DefringingKernel;
|
||||
|
@ -39,7 +39,6 @@ pub struct Renderer {
|
|||
solid_tile_program: SolidTileProgram,
|
||||
mask_tile_program: MaskTileProgram,
|
||||
area_lut_texture: Texture,
|
||||
#[allow(dead_code)]
|
||||
quad_vertex_positions_buffer: Buffer,
|
||||
fill_vertex_array: FillVertexArray,
|
||||
mask_tile_vertex_array: MaskTileVertexArray,
|
||||
|
@ -186,6 +185,11 @@ impl Renderer {
|
|||
self.postprocess_options.gamma_correction_bg_color = Some(bg_color);
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn quad_vertex_positions_buffer(&self) -> &Buffer {
|
||||
&self.quad_vertex_positions_buffer
|
||||
}
|
||||
|
||||
fn upload_shaders(&mut self, shaders: &[ObjectShader]) {
|
||||
let size = Size2D::new(FILL_COLORS_TEXTURE_WIDTH, FILL_COLORS_TEXTURE_HEIGHT);
|
||||
let mut fill_colors = vec![0; size.width as usize * size.height as usize * 4];
|
||||
|
@ -221,7 +225,7 @@ impl Renderer {
|
|||
gl::ClearColor(0.0, 0.0, 0.0, 0.0);
|
||||
gl::Clear(gl::COLOR_BUFFER_BIT);
|
||||
|
||||
gl::BindVertexArray(self.fill_vertex_array.gl_vertex_array);
|
||||
gl::BindVertexArray(self.fill_vertex_array.vertex_array.gl_vertex_array);
|
||||
gl::UseProgram(self.fill_program.program.gl_program);
|
||||
gl::Uniform2f(self.fill_program.framebuffer_size_uniform.location,
|
||||
MASK_FRAMEBUFFER_WIDTH as GLfloat,
|
||||
|
@ -244,7 +248,7 @@ impl Renderer {
|
|||
self.bind_draw_framebuffer();
|
||||
self.set_main_viewport();
|
||||
|
||||
gl::BindVertexArray(self.mask_tile_vertex_array.gl_vertex_array);
|
||||
gl::BindVertexArray(self.mask_tile_vertex_array.vertex_array.gl_vertex_array);
|
||||
gl::UseProgram(self.mask_tile_program.program.gl_program);
|
||||
gl::Uniform2f(self.mask_tile_program.framebuffer_size_uniform.location,
|
||||
self.main_framebuffer_size.width as GLfloat,
|
||||
|
@ -275,7 +279,7 @@ impl Renderer {
|
|||
self.bind_draw_framebuffer();
|
||||
self.set_main_viewport();
|
||||
|
||||
gl::BindVertexArray(self.solid_tile_vertex_array.gl_vertex_array);
|
||||
gl::BindVertexArray(self.solid_tile_vertex_array.vertex_array.gl_vertex_array);
|
||||
gl::UseProgram(self.solid_tile_program.program.gl_program);
|
||||
gl::Uniform2f(self.solid_tile_program.framebuffer_size_uniform.location,
|
||||
self.main_framebuffer_size.width as GLfloat,
|
||||
|
@ -300,7 +304,7 @@ impl Renderer {
|
|||
gl::BindFramebuffer(gl::FRAMEBUFFER, 0);
|
||||
self.set_main_viewport();
|
||||
|
||||
gl::BindVertexArray(self.postprocess_vertex_array.gl_vertex_array);
|
||||
gl::BindVertexArray(self.postprocess_vertex_array.vertex_array.gl_vertex_array);
|
||||
gl::UseProgram(self.postprocess_program.program.gl_program);
|
||||
gl::Uniform2f(self.postprocess_program.framebuffer_size_uniform.location,
|
||||
self.main_framebuffer_size.width as GLfloat,
|
||||
|
@ -406,14 +410,13 @@ struct PostprocessOptions {
|
|||
}
|
||||
|
||||
struct FillVertexArray {
|
||||
gl_vertex_array: GLuint,
|
||||
vertex_array: VertexArray,
|
||||
vertex_buffer: Buffer,
|
||||
}
|
||||
|
||||
impl FillVertexArray {
|
||||
fn new(fill_program: &FillProgram, quad_vertex_positions_buffer: &Buffer) -> FillVertexArray {
|
||||
let vertex_buffer = Buffer::new();
|
||||
let mut gl_vertex_array = 0;
|
||||
let (vertex_array, vertex_buffer) = (VertexArray::new(), Buffer::new());
|
||||
unsafe {
|
||||
let tess_coord_attr = VertexAttr::new(&fill_program.program, "TessCoord");
|
||||
let from_px_attr = VertexAttr::new(&fill_program.program, "FromPx");
|
||||
|
@ -422,8 +425,7 @@ impl FillVertexArray {
|
|||
let to_subpx_attr = VertexAttr::new(&fill_program.program, "ToSubpx");
|
||||
let tile_index_attr = VertexAttr::new(&fill_program.program, "TileIndex");
|
||||
|
||||
gl::GenVertexArrays(1, &mut gl_vertex_array);
|
||||
gl::BindVertexArray(gl_vertex_array);
|
||||
gl::BindVertexArray(vertex_array.gl_vertex_array);
|
||||
gl::UseProgram(fill_program.program.gl_program);
|
||||
gl::BindBuffer(gl::ARRAY_BUFFER, quad_vertex_positions_buffer.gl_buffer);
|
||||
tess_coord_attr.configure_float(2, gl::UNSIGNED_BYTE, false, 0, 0, 0);
|
||||
|
@ -435,29 +437,19 @@ impl FillVertexArray {
|
|||
tile_index_attr.configure_int(1, gl::UNSIGNED_SHORT, FILL_INSTANCE_SIZE, 6, 1);
|
||||
}
|
||||
|
||||
FillVertexArray { gl_vertex_array, vertex_buffer }
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for FillVertexArray {
|
||||
#[inline]
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
gl::DeleteVertexArrays(1, &mut self.gl_vertex_array);
|
||||
}
|
||||
FillVertexArray { vertex_array, vertex_buffer }
|
||||
}
|
||||
}
|
||||
|
||||
struct MaskTileVertexArray {
|
||||
gl_vertex_array: GLuint,
|
||||
vertex_array: VertexArray,
|
||||
vertex_buffer: Buffer,
|
||||
}
|
||||
|
||||
impl MaskTileVertexArray {
|
||||
fn new(mask_tile_program: &MaskTileProgram, quad_vertex_positions_buffer: &Buffer)
|
||||
-> MaskTileVertexArray {
|
||||
let vertex_buffer = Buffer::new();
|
||||
let mut gl_vertex_array = 0;
|
||||
let (vertex_array, vertex_buffer) = (VertexArray::new(), Buffer::new());
|
||||
unsafe {
|
||||
let tess_coord_attr = VertexAttr::new(&mask_tile_program.program, "TessCoord");
|
||||
let tile_origin_attr = VertexAttr::new(&mask_tile_program.program, "TileOrigin");
|
||||
|
@ -466,8 +458,7 @@ impl MaskTileVertexArray {
|
|||
|
||||
// NB: The object must be of type short, not unsigned short, to work around a macOS
|
||||
// Radeon driver bug.
|
||||
gl::GenVertexArrays(1, &mut gl_vertex_array);
|
||||
gl::BindVertexArray(gl_vertex_array);
|
||||
gl::BindVertexArray(vertex_array.gl_vertex_array);
|
||||
gl::UseProgram(mask_tile_program.program.gl_program);
|
||||
gl::BindBuffer(gl::ARRAY_BUFFER, quad_vertex_positions_buffer.gl_buffer);
|
||||
tess_coord_attr.configure_float(2, gl::UNSIGNED_BYTE, false, 0, 0, 0);
|
||||
|
@ -477,29 +468,19 @@ impl MaskTileVertexArray {
|
|||
object_attr.configure_int(2, gl::SHORT, MASK_TILE_INSTANCE_SIZE, 6, 1);
|
||||
}
|
||||
|
||||
MaskTileVertexArray { gl_vertex_array, vertex_buffer }
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for MaskTileVertexArray {
|
||||
#[inline]
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
gl::DeleteVertexArrays(1, &mut self.gl_vertex_array);
|
||||
}
|
||||
MaskTileVertexArray { vertex_array, vertex_buffer }
|
||||
}
|
||||
}
|
||||
|
||||
struct SolidTileVertexArray {
|
||||
gl_vertex_array: GLuint,
|
||||
vertex_array: VertexArray,
|
||||
vertex_buffer: Buffer,
|
||||
}
|
||||
|
||||
impl SolidTileVertexArray {
|
||||
fn new(solid_tile_program: &SolidTileProgram, quad_vertex_positions_buffer: &Buffer)
|
||||
-> SolidTileVertexArray {
|
||||
let vertex_buffer = Buffer::new();
|
||||
let mut gl_vertex_array = 0;
|
||||
let (vertex_array, vertex_buffer) = (VertexArray::new(), Buffer::new());
|
||||
unsafe {
|
||||
let tess_coord_attr = VertexAttr::new(&solid_tile_program.program, "TessCoord");
|
||||
let tile_origin_attr = VertexAttr::new(&solid_tile_program.program, "TileOrigin");
|
||||
|
@ -507,8 +488,7 @@ impl SolidTileVertexArray {
|
|||
|
||||
// NB: The object must be of type short, not unsigned short, to work around a macOS
|
||||
// Radeon driver bug.
|
||||
gl::GenVertexArrays(1, &mut gl_vertex_array);
|
||||
gl::BindVertexArray(gl_vertex_array);
|
||||
gl::BindVertexArray(vertex_array.gl_vertex_array);
|
||||
gl::UseProgram(solid_tile_program.program.gl_program);
|
||||
gl::BindBuffer(gl::ARRAY_BUFFER, quad_vertex_positions_buffer.gl_buffer);
|
||||
tess_coord_attr.configure_float(2, gl::UNSIGNED_BYTE, false, 0, 0, 0);
|
||||
|
@ -517,16 +497,7 @@ impl SolidTileVertexArray {
|
|||
object_attr.configure_int(1, gl::SHORT, SOLID_TILE_INSTANCE_SIZE, 4, 1);
|
||||
}
|
||||
|
||||
SolidTileVertexArray { gl_vertex_array, vertex_buffer }
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for SolidTileVertexArray {
|
||||
#[inline]
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
gl::DeleteVertexArrays(1, &mut self.gl_vertex_array);
|
||||
}
|
||||
SolidTileVertexArray { vertex_array, vertex_buffer }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -638,32 +609,22 @@ impl PostprocessProgram {
|
|||
}
|
||||
|
||||
struct PostprocessVertexArray {
|
||||
gl_vertex_array: GLuint,
|
||||
vertex_array: VertexArray,
|
||||
}
|
||||
|
||||
impl PostprocessVertexArray {
|
||||
fn new(postprocess_program: &PostprocessProgram, quad_vertex_positions_buffer: &Buffer)
|
||||
-> PostprocessVertexArray {
|
||||
let mut gl_vertex_array = 0;
|
||||
let vertex_array = VertexArray::new();
|
||||
unsafe {
|
||||
let position_attr = VertexAttr::new(&postprocess_program.program, "Position");
|
||||
|
||||
gl::GenVertexArrays(1, &mut gl_vertex_array);
|
||||
gl::BindVertexArray(gl_vertex_array);
|
||||
gl::BindVertexArray(vertex_array.gl_vertex_array);
|
||||
gl::UseProgram(postprocess_program.program.gl_program);
|
||||
gl::BindBuffer(gl::ARRAY_BUFFER, quad_vertex_positions_buffer.gl_buffer);
|
||||
position_attr.configure_float(2, gl::UNSIGNED_BYTE, false, 0, 0, 0);
|
||||
}
|
||||
|
||||
PostprocessVertexArray { gl_vertex_array }
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for PostprocessVertexArray {
|
||||
#[inline]
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
gl::DeleteVertexArrays(1, &mut self.gl_vertex_array);
|
||||
}
|
||||
PostprocessVertexArray { vertex_array }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
|
||||
//! How a path is to be filled.
|
||||
|
||||
use pathfinder_simd::default::F32x4;
|
||||
use std::fmt::{self, Debug, Formatter};
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
|
||||
|
@ -38,6 +39,12 @@ impl ColorU {
|
|||
a: 255,
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn to_f32(&self) -> ColorF {
|
||||
let color = F32x4::new(self.r as f32, self.g as f32, self.b as f32, self.a as f32);
|
||||
ColorF(color * F32x4::splat(1.0 / 255.0))
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for ColorU {
|
||||
|
@ -55,6 +62,30 @@ impl Debug for ColorU {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct ColorF(pub F32x4);
|
||||
|
||||
impl ColorF {
|
||||
#[inline]
|
||||
pub fn r(&self) -> f32 {
|
||||
self.0[0]
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn g(&self) -> f32 {
|
||||
self.0[1]
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn b(&self) -> f32 {
|
||||
self.0[2]
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn a(&self) -> f32 {
|
||||
self.0[3]
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||
pub struct ShaderId(pub u16);
|
||||
|
|
Loading…
Reference in New Issue