use zaplib::*;
static SHADER: Shader = Shader {
build_geom: Some(QuadIns::build_geom),
code_to_concatenate: &[
Cx::STD_SHADER,
code_fragment!(
r#"
uniform rect_size: vec2;
uniform use_screen_space: float;
uniform point_style: float;
uniform vertex_transform: mat4;
geometry geom: vec2;
instance in_pos: vec3;
instance in_color: vec3;
instance in_size: float;
instance in_user_info: vec2;
// Transforms a vertex to clip space, accounting for aspect ratio
fn to_clip_space(v: vec4) -> vec4 {
let w = draw_clip.z - draw_clip.x;
let h = draw_clip.w - draw_clip.y;
let aspect = w / h;
return v / v.w * aspect;
}
fn vertex() -> vec4 {
if use_screen_space == 1. {
let projected_pos = camera_projection * camera_view * vertex_transform * vec4(in_pos, 1.0);
let point_size = in_size * dpi_factor;
let offset = point_size * vec4((geom - vec2(0.5, 0.5))/rect_size, 0, 0);
// When rendering screen space points, we convert the projected point to clip space
// and then apply the offset.
return to_clip_space(projected_pos) + offset;
} else {
let view_pos = camera_view * vertex_transform * vec4(in_pos, 1.0);
let point_size = in_size;
let offset = point_size * vec4(geom - vec2(0.5, 0.5), 0, 0);
// For world space points, we apply the offset in view space so they always
// face to the camera.
return camera_projection * (view_pos + offset);
}
}
fn pixel() -> vec4 {
if point_style == 1. {
let df = Df::viewport(geom);
df.circle(vec2(0.5), 0.5);
df.fill(vec4(in_color, 1.));
return df.result;
} else {
return vec4(in_color, 1.);
}
}"#
),
],
..Shader::DEFAULT
};
#[repr(C)]
#[derive(Debug, Clone)]
pub struct DrawPoints3dInstance {
pub position: Vec3,
pub color: Vec3,
pub size: f32,
pub user_info: Vec2,
}
#[repr(C)]
struct DrawPoints3dUniforms {
rect_size: Vec2,
use_screen_space: f32,
point_style: f32,
vertex_transform: Mat4,
}
#[derive(Debug, Clone)]
pub enum DrawPoints3dStyle {
Quad,
Circle,
}
const POINT_STYLE_QUAD: f32 = 0.0;
const POINT_STYLE_CIRCLE: f32 = 1.0;
pub struct DrawPoints3dOptions {
pub use_screen_space: bool,
pub point_style: DrawPoints3dStyle,
pub vertex_transform: Mat4,
}
impl Default for DrawPoints3dOptions {
fn default() -> Self {
Self { use_screen_space: false, point_style: DrawPoints3dStyle::Quad, vertex_transform: Mat4::identity() }
}
}
pub struct DrawPoints3d {}
impl DrawPoints3d {
pub fn draw(cx: &mut Cx, data: &[DrawPoints3dInstance], options: DrawPoints3dOptions) -> Area {
let area = cx.add_instances(&SHADER, data);
let rect = cx.get_box_rect();
area.write_user_uniforms(
cx,
DrawPoints3dUniforms {
rect_size: rect.size,
use_screen_space: if options.use_screen_space { 1. } else { 0. },
point_style: match options.point_style {
DrawPoints3dStyle::Quad => POINT_STYLE_QUAD,
DrawPoints3dStyle::Circle => POINT_STYLE_CIRCLE,
},
vertex_transform: options.vertex_transform,
},
);
area
}
}