Skip to main content

LitOptions

Struct LitOptions 

Source
pub struct LitOptions {
    pub shader: Option<LitShader>,
    pub unlit: bool,
    pub srgb_to_linear_output: bool,
    pub base_color: BaseColorChannels,
    pub alpha_cutoff: bool,
    pub expanded: bool,
    pub texture_filtering: bool,
    pub primitive: PrimitiveState,
    pub depth_stencil: DepthStencilPolicy,
    pub blend: Option<BlendState>,
    pub write_mask: ColorWrites,
}
Expand description

The policy a caller decides about a built-in lit pipeline.

Everything a draw resolves is absent: the vertex channels, whether the draw samples a material, whether its mesh morphs, the render target and the device’s array path are facts a family folds into an LitVariant when it resolves a draw, not choices a caller can make. The target owns the color format, the sample count and whether there is a depth attachment at all; what is left is what a caller actually picks.

LitOptions::standard is the usual starting point: back-face culling, a filtering base-color texture binding and reverse-z depth.

Fields§

§shader: Option<LitShader>

The entry shader this policy draws with, or None for the built-in lit.wesl.

A caller’s snippets extend the built-in source and nothing else: the layouts, vertex streams and entry-point names stay the variant’s. See LitShader.

§unlit: bool

Whether the fragment stage returns its base color unchanged instead of multiplying it by the frame’s lights.

An unlit variant declares none of the lighting bindings, so the lights a source clusters cost it nothing; a lit one reads the light records, the cell array, the polygon vertices and the cluster uniform from the global group. Lighting is the common case, so this states the exception and Self::standard leaves it off.

§srgb_to_linear_output: bool

The color target is sRGB-aware: it encodes the values written to it, so the fragment converts them from sRGB to linear first.

The shader multiplies the caller’s colors in whichever space they arrive in — premultiplied sRGB for a user-interface pass, say — and a target that encodes sRGB would otherwise encode them a second time. Alpha is coverage rather than color, so it never converts.

§base_color: BaseColorChannels

How a sampled base-color texel expands into the fragment’s color.

Only meaningful for a variant that samples a base-color texture: without one there is no texel to expand.

§alpha_cutoff: bool

Discard a fragment whose alpha is below the instance’s cutoff.

The cutoff itself rides the instance stream rather than the material group: it is per-instance state, and this switch only selects a code path. An instance that carries no cutoff leaves the value at zero, which no alpha falls below, so the path costs a compare and nothing else.

An untextured fragment can be cut off too: its alpha is the instance color’s, and the cutoff is explicit per instance either way.

§expanded: bool

Push every vertex out along its normal by the instance’s hull width.

This is the geometry half of the inverted-hull outline: a mesh drawn with this variant expands into a shell, and a mesh drawn behind it with the ordinary front-facing variant covers the shell except where it pokes out past the silhouette, which is the line. Both halves draw the same mesh with the same buffers — the shell reads the very same vertex and index streams — so an outline costs one extra draw and no second mesh.

The width rides the instance stream (MeshInstance::hull_width), so two instances of one mesh can be shells of different thicknesses, and a mesh that is not a hull carries zero. A variant with this set reads the mesh’s normals and declares the HULL_WIDTH attribute, which a mesh with no normal channel cannot supply — without a normal there is no direction to expand along.

Expansion happens in the vertex stage, so it moves the clip position, the world position the lights are addressed from and the shading normal together. Which faces are drawn is the primitive state’s business: LitOptions::inverted_hull culls the front and writes no depth, which is what leaves the ordinary variant’s nearer surface in front.

§texture_filtering: bool

Whether the base-color texture binding is filterable.

A filtering binding accepts a sampler that interpolates between texels and a texture whose format is filterable — the usual case, and what Self::standard leaves. Clearing it declares the binding unfilterable instead, which is what a texture sampled with nearest-only filters has to bind to on a device that cannot filter that format: Rgba32Float, say, is filterable only where FLOAT32_FILTERABLE is present, and is still bindable without it through an unfilterable binding.

The two declare different bind-group layouts, so this is part of what distinguishes one variant from another: a pipeline built for one cannot bind a material built for the other.

§primitive: PrimitiveState

How the pipeline assembles and culls primitives, including the strip index format a strip topology requires.

Self::standard leaves strip_index_format at its default, and the built-in lit family fills it from the mesh’s index buffer, so the field is a caller’s concern only for a pipeline a mesh does not describe.

§depth_stencil: DepthStencilPolicy

How the pipeline tests and writes the depth attachment, for a target that has one.

A target without a depth attachment runs the pipeline without a depth-stencil state at all, whatever this field says, because wgpu rejects a pipeline that declares one against a pass that has none. The format is the attachment’s own, which the options cannot know: it is the target’s word, and the variant carries the target.

Self::standard states the renderer’s reverse-z convention: depth is cleared to the far plane, so nearer geometry carries the greater value.

§blend: Option<BlendState>

The blend state the fragment output composites with, or None to write it unblended.

§write_mask: ColorWrites

Which color channels the pipeline writes to the target.

Implementations§

Source§

impl LitOptions

Source

pub fn standard() -> Self

The usual starting point: the full compressed mesh variant — positions, UVs, vertex colors, a base-color texture and per-instance transforms — with reverse-z depth.

The policy names no attachment format: the target the variant is specialized for does. Back faces are culled, because the geometry this variant is for is closed meshes wound counter-clockwise, whose insides are never meant to show.

Source

pub fn inverted_hull() -> Self

The outline shell that goes behind a mesh drawn with Self::standard.

The inverted-hull trick draws the same mesh twice: once as itself, and once expanded along its normals, with its front faces culled and its backwards-facing surface — which is now the outside of a slightly larger copy — drawn where the real mesh does not cover it. What shows is a band the width of the expansion, all the way around the silhouette, including the silhouette’s own inner folds, which a per-triangle line cannot find.

The returned options differ from the standard ones in what makes the shell a shell rather than a copy:

  • Self::expanded is set, so the vertex stage pushes each vertex out along its normal by the instance’s hull width.
  • The front faces are culled, so the far side of the shell is what covers the near side of the mesh.
  • Depth is not written, so the shell leaves the depth buffer to the meshes drawn around it — the surface it belongs to still occludes and is occluded exactly as if the shell were not there.
  • It is unlit, so the band is one flat color rather than a shaded copy of the mesh, and it declares none of the lighting bindings.

The expansion width and the band’s color are per-instance values, so these options cannot hold them: the shell entity carries them as its MeshInstance::hull_width and its base color, which is the same record every other instance is packed from.

Both options hash into the same LitPipelineKey, so the pair compiles to two pipelines and needs no family of its own, no second mesh and no second pass: the two draws sort against each other by depth like any others, and the shell’s unwritten depth is what keeps the order between them stable.

Source

pub fn material_bind_group_layout(&self, device: &Device) -> BindGroupLayout

The material bind-group layout this policy’s variants declare.

The layout holds the base-color texture and its sampler; whether a variant actually declares it is the draw’s answer (LitVariant::base_color_texture), so this is only the shape of the group. Building it here rather than from a variant lets a caller allocate a material without having resolved a draw first.

Trait Implementations§

Source§

impl Clone for LitOptions

Source§

fn clone(&self) -> Self

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for LitOptions

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Eq for LitOptions

Source§

impl Hash for LitOptions

Source§

fn hash<__H: Hasher>(&self, state: &mut __H)

Feeds this value into the given Hasher. Read more
1.3.0 · Source§

fn hash_slice<H>(data: &[Self], state: &mut H)
where H: Hasher, Self: Sized,

Feeds a slice of this type into the given Hasher. Read more
Source§

impl PartialEq for LitOptions

Source§

fn eq(&self, other: &Self) -> bool

Equality operator ==. Read more
1.0.0 (const: unstable) · Source§

fn ne(&self, other: &Rhs) -> bool

Inequality operator !=. Read more
Source§

impl StructuralPartialEq for LitOptions

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
§

impl<T> AsId for T
where T: Hash + Debug,

§

impl<T> AsIdSalt for T
where T: Hash + Debug,

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
§

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

§

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

Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
§

impl<T> Downcast<T> for T

§

fn downcast(&self) -> &T

§

impl<Q, K> Equivalent<K> for Q
where Q: Eq + ?Sized, K: Borrow<Q> + ?Sized,

§

fn equivalent(&self, key: &K) -> bool

Compare self to key and return true if they are equal.
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

§

impl<T> Instrument for T

§

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

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

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<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
§

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

§

impl<T> SerializableAny for T
where T: 'static + Any + Clone + for<'a> Send + Sync,

§

impl<T, S> SimdFrom<T, S> for T
where S: Simd,

§

fn simd_from(_simd: S, value: T) -> T

§

impl<F, T, S> SimdInto<T, S> for F
where T: SimdFrom<F, S>, S: Simd,

§

fn simd_into(self, simd: S) -> T

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
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.
§

impl<T> Upcast<T> for T

§

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

§

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

§

impl<T> WasmNotSendSync for T
where T: WasmNotSend + WasmNotSync,

§

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

§

impl<T> WithSubscriber for T

§

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
§

fn with_current_subscriber(self) -> WithDispatch<Self> ⓘ

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