use crate::core::*;
use crate::renderer::*;
pub struct Sprites {
context: Context,
position_buffer: VertexBuffer,
uv_buffer: VertexBuffer,
center_buffer: InstanceBuffer,
transformation: Mat4,
direction: Option<Vec3>,
}
impl Sprites {
pub fn new(context: &Context, centers: &[Vec3], direction: Option<Vec3>) -> Self {
let position_buffer = VertexBuffer::new_with_data(
context,
&[
vec3(-1.0, -1.0, 0.0),
vec3(1.0, -1.0, 0.0),
vec3(1.0, 1.0, 0.0),
vec3(1.0, 1.0, 0.0),
vec3(-1.0, 1.0, 0.0),
vec3(-1.0, -1.0, 0.0),
],
);
let uv_buffer = VertexBuffer::new_with_data(
context,
&[
vec2(0.0, 0.0),
vec2(1.0, 0.0),
vec2(1.0, 1.0),
vec2(1.0, 1.0),
vec2(0.0, 1.0),
vec2(0.0, 0.0),
],
);
Self {
context: context.clone(),
position_buffer,
uv_buffer,
center_buffer: InstanceBuffer::new_with_data(context, centers),
transformation: Mat4::identity(),
direction,
}
}
pub fn transformation(&self) -> Mat4 {
self.transformation
}
pub fn set_transformation(&mut self, transformation: Mat4) {
self.transformation = transformation;
}
pub fn set_direction(&mut self, direction: Option<Vec3>) {
self.direction = direction;
}
pub fn set_centers(&mut self, centers: &[Vec3]) {
self.center_buffer.fill(centers);
}
fn draw(&self, program: &Program, render_states: RenderStates, camera: &Camera) {
program.use_uniform("eye", camera.position());
program.use_uniform("viewProjection", camera.projection() * camera.view());
program.use_uniform("transformation", self.transformation);
program.use_vertex_attribute("position", &self.position_buffer);
program.use_vertex_attribute("uv_coordinate", &self.uv_buffer);
program.use_instance_attribute("center", &self.center_buffer);
program.use_uniform("direction", self.direction.unwrap_or(vec3(0.0, 0.0, 0.0)));
program.draw_arrays_instanced(
render_states,
camera.viewport(),
6,
self.center_buffer.instance_count(),
)
}
}
impl<'a> IntoIterator for &'a Sprites {
type Item = &'a dyn Geometry;
type IntoIter = std::iter::Once<&'a dyn Geometry>;
fn into_iter(self) -> Self::IntoIter {
std::iter::once(self)
}
}
impl Geometry for Sprites {
fn draw(
&self,
camera: &Camera,
program: &Program,
render_states: RenderStates,
attributes: FragmentAttributes,
) {
if !attributes.uv {
todo!()
}
if attributes.normal || attributes.tangents {
todo!()
}
self.draw(program, render_states, camera);
}
fn vertex_shader_source(&self, _required_attributes: FragmentAttributes) -> String {
include_str!("shaders/sprites.vert").to_owned()
}
fn id(&self, _required_attributes: FragmentAttributes) -> u16 {
0b1u16 << 15 | 0b100u16
}
fn render_with_material(
&self,
material: &dyn Material,
camera: &Camera,
lights: &[&dyn Light],
) {
render_with_material(&self.context, camera, &self, material, lights);
}
fn render_with_effect(
&self,
material: &dyn Effect,
camera: &Camera,
lights: &[&dyn Light],
color_texture: Option<ColorTexture>,
depth_texture: Option<DepthTexture>,
) {
render_with_effect(
&self.context,
camera,
self,
material,
lights,
color_texture,
depth_texture,
)
}
fn aabb(&self) -> AxisAlignedBoundingBox {
AxisAlignedBoundingBox::INFINITE
}
}