Skip to main content

ShaderEffect

Struct ShaderEffect 

Source
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 with nearest_sampler or linear_sampler;
  • history_tex: texture_2d<f32> - the stage’s previous output (see ShaderEffect::with_history; otherwise the input again);
  • post: PostGlobals - the uniform with size, canvas_size, window_size, canvas_origin, canvas_extent, time and frame (see PostGlobals);
  • struct VsOut { @builtin(position) pos: vec4<f32>, @location(0) uv: vec2<f32> } and the vertex shader;
  • bayer4(p) / bayer8(p) ordered-dithering thresholds (see BAYER_WGSL);
  • indices_tex: texture_2d<f32> - with indexed colour, the canvas’s palette indices before the lookup, at canvas size (see PostPass::indices); read them with index_at(canvas_px) or index_in(textureLoad(indices_tex, ..)). post.indexed is 1u when they are there; otherwise indices_tex is the input again;
  • source_tex: texture_2d<f32> - the effect’s own source texture, set with ShaderEffect::with_source (a frame the game uploads, a lookup table); post.source is 1u when it is bound, otherwise source_tex is 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

Source

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.

Source

pub fn with_params<T>( gfx: &Graphics, label: &str, wgsl: &str, params: &T, ) -> ShaderEffect
where 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.

Source

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);
Source

pub fn set_source(&mut self, source: Option<TextureId>)

Change or (None) drop the source texture; see Self::with_source.

Source

pub fn source(&self) -> Option<TextureId>

The source texture set with Self::with_source or Self::set_source.

Source

pub fn with_history(self) -> ShaderEffect

Bind the stage’s previous output as history_tex (otherwise it is the input again).

Source

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

Source§

fn apply(&mut self, pass: &mut PostPass<'_>)

Read PostPass::input and write every pixel of PostPass::output. Both are PostPass::size pixels in PostPass::format.
Source§

fn uses_history(&self) -> bool

Return true to get PostPass::history: the stage’s final output from the previous frame, for afterglow and other temporal effects.

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<T> Downcast for T
where T: Any,

Source§

fn into_any(self: Box<T>) -> Box<dyn Any>

Convert 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>

Convert 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)

Convert &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)

Convert &mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot generate &mut Any’s vtable from &mut Trait’s.
Source§

impl<T> Downcast<T> for T

Source§

fn downcast(&self) -> &T

Source§

impl<T> DowncastSync for T
where T: Any + Send + Sync,

Source§

fn into_any_arc(self: Arc<T>) -> Arc<dyn Any + Sync + Send> ⓘ

Convert Arc<Trait> (where Trait: Downcast) to Arc<Any>. Arc<Any> can then be further downcast into Arc<ConcreteType> where ConcreteType implements Trait.
Source§

impl<S, T> Duplex<S> for T
where T: FromSample<S> + ToSample<S>,

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<S> FromSample<S> for S

Source§

fn from_sample_(s: S) -> S

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self> ⓘ

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self> ⓘ

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<F, T> IntoSample<T> for F
where T: FromSample<F>,

Source§

fn into_sample(self) -> T

Source§

impl<T> Read<Exclusive, BecauseExclusive> for T
where T: ?Sized,

Source§

impl<T, U> ToSample<U> for T
where U: FromSample<T>,

Source§

fn to_sample_(self) -> U

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> Upcast<T> for T

Source§

fn upcast(&self) -> Option<&T>

Source§

impl<T> WasmNotSend for T
where T: Send,

Source§

impl<T> WasmNotSendSync for T

Source§

impl<T> WasmNotSync for T
where T: Sync,

Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more