three_d/renderer/
effect.rs

1//!
2//! A collection of effects implementing the [Effect] trait.
3//!
4
5macro_rules! impl_effect_body {
6    ($inner:ident) => {
7        fn fragment_shader_source(
8            &self,
9            lights: &[&dyn Light],
10            color_texture: Option<ColorTexture>,
11            depth_texture: Option<DepthTexture>,
12        ) -> String {
13            self.$inner()
14                .fragment_shader_source(lights, color_texture, depth_texture)
15        }
16
17        fn id(
18            &self,
19            color_texture: Option<ColorTexture>,
20            depth_texture: Option<DepthTexture>,
21        ) -> EffectMaterialId {
22            self.$inner().id(color_texture, depth_texture)
23        }
24
25        fn use_uniforms(
26            &self,
27            program: &Program,
28            viewer: &dyn Viewer,
29            lights: &[&dyn Light],
30            color_texture: Option<ColorTexture>,
31            depth_texture: Option<DepthTexture>,
32        ) {
33            self.$inner()
34                .use_uniforms(program, viewer, lights, color_texture, depth_texture)
35        }
36
37        fn render_states(&self) -> RenderStates {
38            self.$inner().render_states()
39        }
40    };
41}
42
43mod fog;
44#[doc(inline)]
45pub use fog::*;
46
47mod copy;
48#[doc(inline)]
49pub use copy::*;
50
51mod full_screen;
52#[doc(inline)]
53pub use full_screen::*;
54
55mod fxaa;
56#[doc(inline)]
57pub use fxaa::*;
58
59mod water;
60#[doc(inline)]
61pub use water::*;
62
63pub(crate) mod lighting_pass;
64
65use crate::renderer::*;
66use std::ops::Deref;
67
68///
69/// Similar to [Material], the difference is that an effect needs the rendered color texture and/or depth texture of the scene to be applied.
70/// Therefore an effect is always applied one at a time and after the scene has been rendered with the regular [Material].
71///
72pub trait Effect {
73    ///
74    /// Returns the fragment shader source for this effect.
75    ///
76    fn fragment_shader_source(
77        &self,
78        lights: &[&dyn Light],
79        color_texture: Option<ColorTexture>,
80        depth_texture: Option<DepthTexture>,
81    ) -> String;
82
83    ///
84    /// Returns a unique ID for each variation of the shader source returned from [Effect::fragment_shader_source].
85    ///
86    /// **Note:** The first 16 bits are reserved to internally implemented effects, so if implementing the [Effect] trait
87    /// outside of this crate, always return an id in the public use range as defined by [EffectMaterialId].
88    ///
89    fn id(
90        &self,
91        color_texture: Option<ColorTexture>,
92        depth_texture: Option<DepthTexture>,
93    ) -> EffectMaterialId;
94
95    ///
96    /// Sends the uniform data needed for this effect to the fragment shader.
97    ///
98    fn use_uniforms(
99        &self,
100        program: &Program,
101        viewer: &dyn Viewer,
102        lights: &[&dyn Light],
103        color_texture: Option<ColorTexture>,
104        depth_texture: Option<DepthTexture>,
105    );
106
107    ///
108    /// Returns the render states needed to render with this effect.
109    ///
110    fn render_states(&self) -> RenderStates;
111}
112
113impl<T: Effect + ?Sized> Effect for &T {
114    impl_effect_body!(deref);
115}
116
117impl<T: Effect + ?Sized> Effect for &mut T {
118    impl_effect_body!(deref);
119}
120
121impl<T: Effect> Effect for Box<T> {
122    impl_effect_body!(as_ref);
123}
124
125impl<T: Effect> Effect for std::rc::Rc<T> {
126    impl_effect_body!(as_ref);
127}
128
129impl<T: Effect> Effect for std::sync::Arc<T> {
130    impl_effect_body!(as_ref);
131}
132
133impl<T: Effect> Effect for std::cell::RefCell<T> {
134    impl_effect_body!(borrow);
135}
136
137impl<T: Effect> Effect for std::sync::RwLock<T> {
138    fn fragment_shader_source(
139        &self,
140        lights: &[&dyn Light],
141        color_texture: Option<ColorTexture>,
142        depth_texture: Option<DepthTexture>,
143    ) -> String {
144        self.read()
145            .unwrap()
146            .fragment_shader_source(lights, color_texture, depth_texture)
147    }
148
149    fn id(
150        &self,
151        color_texture: Option<ColorTexture>,
152        depth_texture: Option<DepthTexture>,
153    ) -> EffectMaterialId {
154        self.read().unwrap().id(color_texture, depth_texture)
155    }
156
157    fn use_uniforms(
158        &self,
159        program: &Program,
160        viewer: &dyn Viewer,
161        lights: &[&dyn Light],
162        color_texture: Option<ColorTexture>,
163        depth_texture: Option<DepthTexture>,
164    ) {
165        self.read()
166            .unwrap()
167            .use_uniforms(program, viewer, lights, color_texture, depth_texture)
168    }
169
170    fn render_states(&self) -> RenderStates {
171        self.read().unwrap().render_states()
172    }
173}