143 lines
3.7 KiB
Rust
143 lines
3.7 KiB
Rust
use glow::HasContext;
|
|
|
|
use super::shader::Shader;
|
|
use super::snippets::{CodeType, Snippet};
|
|
use crate::graphics::transforms::{viewport::Viewport, Transform};
|
|
|
|
#[derive(Debug)]
|
|
pub struct Program {
|
|
version: &'static str,
|
|
vertex: Shader,
|
|
fragment: Shader,
|
|
|
|
geometry: Option<Shader>,
|
|
pub native_program: Option<<glow::Context as HasContext>::Program>,
|
|
}
|
|
|
|
impl Program {
|
|
pub fn new(
|
|
vertex: Shader,
|
|
fragment: Shader,
|
|
geometry: Option<Shader>,
|
|
version: &'static str,
|
|
) -> Self {
|
|
let res = Self {
|
|
version,
|
|
vertex,
|
|
fragment,
|
|
geometry,
|
|
native_program: None,
|
|
};
|
|
|
|
res
|
|
}
|
|
|
|
pub fn vertex(&self) -> &Shader {
|
|
&self.vertex
|
|
}
|
|
|
|
pub fn fragment(&self) -> &Shader {
|
|
&self.fragment
|
|
}
|
|
|
|
pub fn set_hook(&mut self, hook: &str, code: &Snippet) {
|
|
self.vertex.set_hook(hook, code);
|
|
self.fragment.set_hook(hook, code);
|
|
}
|
|
|
|
pub fn set_transform<T: Transform>(&mut self, value: &T) {
|
|
self.set_hook("transform", value.snippet());
|
|
}
|
|
|
|
pub fn set_viewport(&mut self, viewport: &Viewport) {
|
|
self.set_hook("viewport", viewport.snippet());
|
|
}
|
|
|
|
pub fn compile(&mut self, gl: &glow::Context) -> crate::errors::Result<()> {
|
|
use crate::errors::Error;
|
|
unsafe {
|
|
// let vertex_array = gl
|
|
// .create_vertex_array()
|
|
// .expect("Cannot create vertex array");
|
|
|
|
let program = gl.create_program().map_err(|e| Error::InvalidProgram(e))?;
|
|
|
|
let vertex_shader =
|
|
self.create_shader(gl, &self.vertex.to_string(),self.version, glow::VERTEX_SHADER);
|
|
let fragment_shader =
|
|
self.create_shader(gl, &self.fragment.to_string(),self.version, glow::FRAGMENT_SHADER);
|
|
|
|
gl.link_program(program);
|
|
if !gl.get_program_link_status(program) {
|
|
return Err(Error::InvalidProgram(gl.get_program_info_log(program)));
|
|
}
|
|
|
|
gl.detach_shader(program, vertex_shader);
|
|
gl.detach_shader(program, fragment_shader);
|
|
|
|
self.native_program = Some(program);
|
|
}
|
|
|
|
Ok(())
|
|
}
|
|
|
|
fn create_shader(
|
|
&self,
|
|
gl: &glow::Context,
|
|
code: &str,
|
|
version: &'static str,
|
|
shader_type: u32,
|
|
) -> <glow::Context as HasContext>::Shader {
|
|
let shader = unsafe {
|
|
let shader = gl
|
|
.create_shader(glow::VERTEX_SHADER)
|
|
.expect("Cannot create shader");
|
|
gl.shader_source(
|
|
shader,
|
|
&format!("{}\n{}", &format!("#version {}", self.version), code),
|
|
);
|
|
gl.compile_shader(shader);
|
|
if !gl.get_shader_compile_status(shader) {
|
|
panic!("{}", gl.get_shader_info_log(shader))
|
|
}
|
|
shader
|
|
};
|
|
shader
|
|
}
|
|
|
|
pub fn destroy(&self, gl: &glow::Context) {
|
|
unsafe {
|
|
self.native_program.map(|p| gl.delete_program(p));
|
|
}
|
|
}
|
|
|
|
pub fn render(&self, gl: &glow::Context) {
|
|
unsafe {
|
|
gl.clear_color(0.05, 0.05, 0.1, 1.0);
|
|
gl.clear(glow::COLOR_BUFFER_BIT);
|
|
gl.use_program(self.native_program);
|
|
}
|
|
}
|
|
}
|
|
|
|
mod test {
|
|
use super::*;
|
|
|
|
#[test]
|
|
fn test_program() {
|
|
let vertex = Shader::new(
|
|
glow::VERTEX_SHADER,
|
|
CodeType::<&'static str>::Path("agg-fast-path.vert".into()),
|
|
)
|
|
.unwrap();
|
|
|
|
let fragment = Shader::new(
|
|
glow::FRAGMENT_SHADER,
|
|
CodeType::<&'static str>::Path("agg-fast-path.frag".into()),
|
|
)
|
|
.unwrap();
|
|
|
|
let program = Program::new(vertex, fragment, None, "330 core");
|
|
}
|
|
}
|