pub struct ShaderEffect { /* private fields */ }Expand description
A post effect made of one WGSL fragment shader, run as a full-screen pass.
The toolkit prepends SHADER_PRELUDE, which declares:
input_tex: texture_2d<f32>- the image so far, sampled withnearest_samplerorlinear_sampler;history_tex: texture_2d<f32>- the stage’s previous output (seeShaderEffect::with_history; otherwise the input again);post: PostGlobals- the uniform withsize,canvas_size,window_size,canvas_origin,canvas_extent,timeandframe(seePostGlobals);struct VsOut { @builtin(position) pos: vec4<f32>, @location(0) uv: vec2<f32> }and the vertex shader;bayer4(p)/bayer8(p)ordered-dithering thresholds (seeBAYER_WGSL);indices_tex: texture_2d<f32>- with indexed colour, the canvas’s palette indices before the lookup, at canvas size (seePostPass::indices); read them withindex_at(canvas_px)orindex_in(textureLoad(indices_tex, ..)).post.indexedis1uwhen they are there; otherwiseindices_texis the input again;source_tex: texture_2d<f32>- the effect’s own source texture, set withShaderEffect::with_source(a frame the game uploads, a lookup table);post.sourceis1uwhen it is bound, otherwisesource_texis the input again.
Your source must define @fragment fn fs_main(in: VsOut) -> @location(0) vec4<f32>. With
ShaderEffect::with_params, it must also declare its parameter block as
@group(1) @binding(0) var<uniform> params: YourParams; matching the Rust struct you pass
to ShaderEffect::set_params. Colours are linear (textures are sRGB, decoded on sample).
let invert = ShaderEffect::new(&ctx.gfx, "invert", r#"
@fragment fn fs_main(in: VsOut) -> @location(0) vec4<f32> {
let c = textureSample(input_tex, nearest_sampler, in.uv);
return vec4<f32>(1.0 - c.rgb, c.a);
}
"#);
ctx.gfx.add_post_effect(PostStage::Canvas, invert);Implementations§
Source§impl ShaderEffect
impl ShaderEffect
Sourcepub fn new(gfx: &Graphics, label: &str, wgsl: &str) -> ShaderEffect
pub fn new(gfx: &Graphics, label: &str, wgsl: &str) -> ShaderEffect
Compile wgsl (see the type docs for what it must define) for gfx’s frame format.
Shader errors surface as wgpu validation errors, like any other pipeline.
Sourcepub fn with_params<T>(
gfx: &Graphics,
label: &str,
wgsl: &str,
params: &T,
) -> ShaderEffectwhere
T: Pod,
pub fn with_params<T>(
gfx: &Graphics,
label: &str,
wgsl: &str,
params: &T,
) -> ShaderEffectwhere
T: Pod,
Like ShaderEffect::new, with a uniform parameter block initialised to params
at @group(1) @binding(0). Mind WGSL’s uniform layout rules: pad the Rust struct to
a multiple of 16 bytes and align vec3/vec4 members to 16.
Sourcepub fn with_source(self, source: TextureId) -> ShaderEffect
pub fn with_source(self, source: TextureId) -> ShaderEffect
Bind painter texture source as source_tex, besides the scene in input_tex: an
emulated screen or video frame the game uploads every frame with
Graphics::update_texture_rgba, a colour lookup table. It is looked up on every run,
so it follows update_texture_rgba and hot reloads. Sample it with linear_sampler or
nearest_sampler; in the Window stage map a fragment to its
place in the canvas with (in.pos.xy - post.canvas_origin) / post.canvas_extent.
let screen = ctx.gfx.create_texture_rgba(320, 200, &pixels, Some("screen"));
let beam = ShaderEffect::new(&ctx.gfx, "beam", BEAM_WGSL).with_source(screen);
ctx.gfx.add_post_effect(PostStage::Window, beam);
// every frame: ctx.gfx.update_texture_rgba(screen, &pixels);Sourcepub fn set_source(&mut self, source: Option<TextureId>)
pub fn set_source(&mut self, source: Option<TextureId>)
Change or (None) drop the source texture; see Self::with_source.
Sourcepub fn source(&self) -> Option<TextureId>
pub fn source(&self) -> Option<TextureId>
The source texture set with Self::with_source or Self::set_source.
Sourcepub fn with_history(self) -> ShaderEffect
pub fn with_history(self) -> ShaderEffect
Bind the stage’s previous output as history_tex (otherwise it is the input again).
Sourcepub fn set_params<T>(&mut self, params: &T)where
T: Pod,
pub fn set_params<T>(&mut self, params: &T)where
T: Pod,
Replace the parameter block; uploaded before the next run. Ignored (with a warning) for an effect created without params or with params of another type.
Trait Implementations§
Source§impl PostEffect for ShaderEffect
impl PostEffect for ShaderEffect
Source§fn apply(&mut self, pass: &mut PostPass<'_>)
fn apply(&mut self, pass: &mut PostPass<'_>)
PostPass::input and write every pixel of PostPass::output. Both are
PostPass::size pixels in PostPass::format.Source§fn uses_history(&self) -> bool
fn uses_history(&self) -> bool
true to get PostPass::history: the stage’s final output from the
previous frame, for afterglow and other temporal effects.Auto Trait Implementations§
impl !RefUnwindSafe for ShaderEffect
impl !UnwindSafe for ShaderEffect
impl Forget for ShaderEffect
impl Freeze for ShaderEffect
impl Send for ShaderEffect
impl Sync for ShaderEffect
impl Unpin for ShaderEffect
impl UnsafeUnpin for ShaderEffect
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
Source§impl<T> Downcast for Twhere
T: Any,
impl<T> Downcast for Twhere
T: Any,
Source§fn into_any(self: Box<T>) -> Box<dyn Any>
fn into_any(self: Box<T>) -> Box<dyn Any>
Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>. Box<dyn Any> can
then be further downcast into Box<ConcreteType> where ConcreteType implements Trait.Source§fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
Rc<Trait> (where Trait: Downcast) to Rc<Any>. Rc<Any> can then be
further downcast into Rc<ConcreteType> where ConcreteType implements Trait.Source§fn as_any(&self) -> &(dyn Any + 'static)
fn as_any(&self) -> &(dyn Any + 'static)
&Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &Any’s vtable from &Trait’s.Source§fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
&mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &mut Any’s vtable from &mut Trait’s.