Skip to content

Texture

A GPU texture resource. Public API wrapper that holds a shareable reference to the internal TextureObject and a numeric handle used by uniforms.

  • Construct via Renderer::create_texture(input). input accepts bytes, (bytes, [w, h]), (bytes, format), a path, a URL, a KTX2 container, or a prepared chain.
  • Bind to a shader with shader.set("key", &texture).
  • The texture owns its sampler; tweak filtering and wrapping via set_sampler_options.

Create a Texture and set it on a Shader

1 collapsed line
async fn run() -> Result<(), Box<dyn std::error::Error>> {
use fragmentcolor::{Renderer, Shader, Size};
let renderer = Renderer::new();
let shader = Shader::new(r#"
@group(0) @binding(0) var my_texture: texture_2d<f32>;
@group(0) @binding(1) var my_sampler: sampler;
@vertex fn vs_main(@builtin(vertex_index) i: u32) -> @builtin(position) vec4<f32> {
let p = array<vec2<f32>,3>(vec2f(-1.,-1.), vec2f(3.,-1.), vec2f(-1.,3.));
return vec4f(p[i], 0., 1.);
}
@fragment fn main() -> @location(0) vec4<f32> { return vec4f(1.,1.,1.,1.); }
"#)?;
// 1x1 white pixel. Passing a size tells create_texture to read the bytes
// as raw pixels; the default format is Rgba (sRGB-aware).
let pixels: &[u8] = &[255, 255, 255, 255];
let texture = renderer.create_texture((pixels, [1, 1])).await?;
// Bind the texture to the uniform name declared in WGSL.
shader.set("my_texture", &texture)?;
4 collapsed lines
_ = shader;
Ok(())
}
fn main() -> Result<(), Box<dyn std::error::Error>> { pollster::block_on(run()) }

Return the stable TextureId for this texture. The id is valid within the Renderer that created it and is the handle uniforms use to refer to the texture, so you can keep one around to bind, look up, or unregister the texture without holding the full Texture value.

1 collapsed line
async fn run() -> Result<(), Box<dyn std::error::Error>> {
use fragmentcolor::{Renderer, TextureFormat};
let renderer = Renderer::new();
let texture = renderer.create_storage_texture(([64, 64], TextureFormat::Rgba)).await?;
let id = *texture.id();
3 collapsed lines
Ok(())
}
fn main() -> Result<(), Box<dyn std::error::Error>> { pollster::block_on(run()) }

Return the texture’s dimensions as a Size (width, height, and an optional depth for 3D or array textures). The size reflects the allocated GPU resource and is constant for the lifetime of the texture.

1 collapsed line
async fn run() -> Result<(), Box<dyn std::error::Error>> {
use fragmentcolor::{Renderer, Size};
let renderer = Renderer::new();
let pixels: &[u8] = &[255,255,255,255];
let tex = renderer.create_texture((pixels, [1, 1])).await?;
let sz = tex.size();
4 collapsed lines
assert_eq!([sz.width, sz.height], [1, 1]);
Ok(())
}
fn main() -> Result<(), Box<dyn std::error::Error>> { pollster::block_on(run()) }

Return the texture’s width / height as f32. Useful for setting up projection matrices or laying out a sprite without recomputing the ratio on every frame.

1 collapsed line
async fn run() -> Result<(), Box<dyn std::error::Error>> {
use fragmentcolor::{Renderer, Size};
let renderer = Renderer::new();
// 1x1 RGBA (white) raw pixel bytes
let pixels: &[u8] = &[255,255,255,255];
let tex = renderer.create_texture((pixels, [1, 1])).await?;
let a = tex.aspect();
4 collapsed lines
assert!(a > 0.0);
Ok(())
}
fn main() -> Result<(), Box<dyn std::error::Error>> { pollster::block_on(run()) }

Update the texture sampler options (filtering, wrapping, etc.).

smooth: true (the default) uses linear filtering for both magnification and minification, including trilinear interpolation between mip levels when the texture has a mipmap chain (created automatically for source images). smooth: false uses nearest-neighbor for everything.

Note: changes take effect on next bind; the renderer recreates the sampler as needed.

1 collapsed line
async fn run() -> Result<(), Box<dyn std::error::Error>> {
use fragmentcolor::{Renderer, Size, SamplerOptions};
let renderer = Renderer::new();
// 1x1 RGBA (white) raw pixel bytes
let pixels: &[u8] = &[255,255,255,255];
let texture = renderer.create_texture((pixels, [1, 1])).await?;
let opts = SamplerOptions { repeat_x: true, repeat_y: true, smooth: true, compare: None };
texture.set_sampler_options(opts);
3 collapsed lines
Ok(())
}
fn main() -> Result<(), Box<dyn std::error::Error>> { pollster::block_on(run()) }

Efficiently upload raw pixel data into an existing texture. Ideal for video playback or any per-frame dynamic image updates.

  • Whole texture updates: use Texture.write(&bytes).
  • Sub-rectangle updates or explicit data layout: use Texture.write_region(&bytes, region).
  • Bytes per row must be a multiple of 256. When unspecified, compute it from the pixel stride and align up.
  • Supported formats initially: Rgba8Unorm, Rgba8UnormSrgb, Bgra8Unorm, Bgra8UnormSrgb, and other 4-bytes-per-pixel formats. Unsupported formats return an error.
  • The texture must have COPY_DST usage.
1 collapsed line
async fn run() -> Result<(), Box<dyn std::error::Error>> {
use fragmentcolor::{Renderer, TextureFormat};
let renderer = Renderer::new();
let texture = renderer.create_storage_texture(([64, 64], TextureFormat::Rgba)).await?;
let frame_bytes = vec![0u8; 64 * 64 * 4];
texture.write(&frame_bytes)?;
3 collapsed lines
Ok(())
}
fn main() -> Result<(), Box<dyn std::error::Error>> { pollster::block_on(run()) }

Same as Texture::write, but writes into a sub-region of the texture and/or with explicit source data layout.

The region argument accepts anything convertible into a TextureRegion:

  • [w, h] / (w, h) — full size, origin (0, 0, 0)
  • [x, y, w, h] / (x, y, w, h) — 2D rectangle
  • [x, y, z, w, h, d] — 3D box (for layered or 3D textures)
  • A TextureRegion constructed explicitly with .with_stride(...) / .with_rows(...) for advanced data-layout control
  • See Texture::write for format and alignment details.
  • bytes_per_row (set via .with_stride(...)) must be a multiple of 256 when provided.
  • rows_per_image (set via .with_rows(...)) defaults to the region height.
1 collapsed line
async fn run() -> Result<(), Box<dyn std::error::Error>> {
use fragmentcolor::{Renderer, TextureFormat, TextureRegion};
let renderer = Renderer::new();
let texture = renderer.create_storage_texture(([64, 32], TextureFormat::Rgba)).await?;
let bytes = vec![0u8; 64 * 32 * 4];
// Simple sub-rectangle update.
texture.write_region(&bytes, [0, 0, 64, 32])?;
// Explicit data layout (advanced — when source rows are padded).
let region = TextureRegion::from([0, 0, 64, 32])
.with_stride(256)
.with_rows(32);
texture.write_region(&bytes, region)?;
3 collapsed lines
Ok(())
}
fn main() -> Result<(), Box<dyn std::error::Error>> { pollster::block_on(run()) }

Read back the mip-0 contents of this texture as tightly-packed bytes in the texture’s native format.

  • Works on native and on the web; the call awaits the GPU readback mapping.
  • For multi-layer textures, layers come first in the byte layout (layer-major).
  • The texture must have COPY_SRC usage. Creation helpers like create_storage_texture enable it by default.
1 collapsed line
async fn run() -> Result<(), Box<dyn std::error::Error>> {
use fragmentcolor::{Renderer, TextureFormat};
let renderer = Renderer::new();
let texture = renderer.create_storage_texture(([64, 64], TextureFormat::Rgba)).await?;
texture.write(&vec![0u8; 64 * 64 * 4])?;
let bytes = texture.get_image().await?;
4 collapsed lines
assert_eq!(bytes.len(), 64 * 64 * 4);
Ok(())
}
fn main() -> Result<(), Box<dyn std::error::Error>> { pollster::block_on(run()) }