radiant_rs/core/
program.rs1use crate::prelude::*;
2use crate::core::{Context, AsUniform, UniformList, Color};
3use crate::core::math::*;
4use crate::backends::backend;
5
6const SPRITE_INC: &'static str = include_str!("../shader/sprite.inc.wgsl");
7const TEXTURE_INC: &'static str = include_str!("../shader/texture.inc.wgsl");
8
9#[derive(Clone)]
14pub struct Program {
15 pub uniforms: UniformList,
16 pub(crate) sprite_program: Option<Arc<backend::Program>>,
17 pub(crate) texture_program: Arc<backend::Program>,
18}
19
20impl Debug for Program {
21 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
22 f.debug_struct("Program")
23 .field("uniforms", &self.uniforms)
24 .finish()
25 }
26}
27
28impl Program {
29 pub fn from_file(context: &Context, file: &str) -> crate::core::Result<Self> {
31 use std::io::Read;
32 let mut source = String::new();
33 let mut f = File::open(file)?;
34 f.read_to_string(&mut source)?;
35 Self::from_string(context, &source)
36 }
37 pub fn from_string(context: &Context, source: &str) -> crate::core::Result<Self> {
46 Self::new(context, source)
47 }
48 pub fn set_uniform<T>(self: &mut Self, name: &str, value: &T) where T: AsUniform {
50 self.uniforms.insert(name, value.as_uniform());
51 }
52 pub fn remove_uniform<T>(self: &mut Self, name: &str) -> bool {
54 self.uniforms.remove(name)
55 }
56 pub(crate) fn new(context: &Context, source: &str) -> crate::core::Result<Program> {
58 let mut uniforms = UniformList::new();
59 uniforms.insert("u_view", Mat4::viewport(1.0, 1.0).as_uniform());
60 uniforms.insert("u_model", Mat4::<f32>::identity().as_uniform());
61 uniforms.insert("_rd_color", Color::WHITE.as_uniform());
62 let context = context.lock();
63 let backend_context = context.backend_context.as_ref().unwrap();
64
65 let combined = if source.contains("@group(0) @binding") {
67 source.to_string()
68 } else if source.contains("SpriteFragmentInput") {
69 format!("{}\n{}", SPRITE_INC, source)
70 } else {
71 format!("{}\n{}", TEXTURE_INC, source)
72 };
73
74 let prog = Arc::new(backend::Program::new(backend_context, &combined)?);
75 let (sprite_program, texture_program) = if matches!(prog.kind, backend::ProgramKind::Sprite) {
76 let default_tex = Arc::new(backend::Program::new_default_texture(backend_context)?);
77 (Some(prog), default_tex)
78 } else {
79 (None, prog)
80 };
81
82 Ok(Program { uniforms, sprite_program, texture_program })
83 }
84 pub(crate) fn new_default(context: &Context) -> crate::core::Result<Program> {
86 let mut uniforms = UniformList::new();
87 uniforms.insert("u_view", Mat4::viewport(1.0, 1.0).as_uniform());
88 uniforms.insert("u_model", Mat4::<f32>::identity().as_uniform());
89 uniforms.insert("_rd_color", Color::WHITE.as_uniform());
90 let context = context.lock();
91 let backend_context = context.backend_context.as_ref().unwrap();
92 let texture_program = Arc::new(backend::Program::new_default_texture(backend_context)?);
93 Ok(Program { uniforms, sprite_program: None, texture_program })
94 }
95}