-
-
Notifications
You must be signed in to change notification settings - Fork 1
Creating custom drawable objects
Ethan Almloff edited this page Jun 1, 2024
·
3 revisions
This is not necessary to do, the default drawables that come with the library should be enough for most. However, if you have a solid understanding of OpenGL here is how you make a custom drawable.
use glium::uniform;
use glium::Surface;
use lumenpyx::drawable_object::Drawable;
use lumenpyx::LumenpyxProgram;
use lumenpyx::Transform;
use lumenpyx::Vertex;
// put your glsl shader in a file and reference it here
// if you don't do this the shader won't be including in the binary and it will panic
const GENERATE_CIRCLE_VERTEX_SHADER_SRC: &str =
include_str!(r"..\shaders\primitives\circle_ahr_shader.vert");
const GENERATE_CIRCLE_FRAGMENT_SHADER_SRC: &str =
include_str!(r"..\shaders\primitives\circle_ahr_shader.frag");
pub struct Circle {
color: [f32; 4],
radius: f32,
transform: Transform,
}
impl Drawable for Circle {
fn draw_albedo(
&self,
program: &LumenpyxProgram,
transform: &Transform,
albedo_framebuffer: &mut glium::framebuffer::SimpleFrameBuffer,
) {
let color = self.color;
let radius = self.radius;
let transform = self.transform;
let display = &program.display;
let indices = &program.indices;
// attempt to load the shader
// as long as the load_shaders function was setup correctly, this shouldn't panic
let shader = program.get_shader("circle_ahr_shader").unwrap();
// this is a whole screen shape
let shape = lumenpyx::shaders::FULL_SCREEN_QUAD;
let vertex_buffer = glium::VertexBuffer::new(display, &shape).unwrap();
// these are setup by name in the glsl shader file at the top of the file
// ex.
// ```glsl
// uniform vec4 circle color
// ```
let uniforms = &uniform! {
circle_color: color,
radius_squared: radius.powi(2),
matrix: transform.get_matrix(), // notice we use the transform passed in, not the one in the struct (the one passed in is correctly scaled and positioned based on the camera)
};
albedo_framebuffer
.draw(
&vertex_buffer,
indices,
&shader,
uniforms,
&Default::default(),
)
.unwrap();
}
// there are virtually identical functions for the other framebuffers (height, normal, and roughness)
// this is called every frame, so make sure to check if the shader is already loaded
fn try_load_shaders(&self, program: &mut LumenpyxProgram) {
// check if the shader is loaded
if program.get_shader("circle_ahr_shader").is_none() {
// if not we create the shader
let shader = glium::Program::from_source(
&program.display,
GENERATE_CIRCLE_VERTEX_SHADER_SRC,
GENERATE_CIRCLE_FRAGMENT_SHADER_SRC,
None,
)
.unwrap();
// then we add the shader to the program to be accessed later
program.add_shader(shader, "circle_ahr_shader");
}
}
// this is so that objects scale properly with camera movement and dimensions
fn get_transform(&self) -> Transform {
self.transform
}
fn set_transform(&mut self, transform: Transform) {
self.transform = transform;
}
}