1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360
//! # A simple, type-safe and opinionated graphics crate
//!
//! luminance is an effort to make graphics rendering simple and elegant. It is a _low-level_
//! and opinionated graphics API, highly typed (type-level computations, refined types, etc.)
//! which aims to be simple and performant. Instead of providing users with as many low-level
//! features as possible, luminance provides you with _some ways_ to do rendering. That has
//! both advantages and drawbacks:
//!
//! - On one side, because the API is opinionated, some dynamic branching and decisions are
//! completely removed / optimized. Some operations breaking state mutations or invariant
//! violation are not statically constructible, ensuring safety. Because strong typing is
//! used, lots of runtime checks are also not needed, helping with performance.
//! - On the other side, if you want to do something very specific and very low-level, you
//! will find luminance not to be friendly as it doesn’t like, most of the time, exposing
//! its internal design to the outer world — mostly for runtime safety reason.
//!
//! > A note on _safety_: here, _safety_ is not used as with the Rust definiton, but most in
//! > terms of undefined behavior and unwanted behavior. If something can lead to a weird
//! > behavior, a crash, a panic or a black screen, it’s considered `unsafe`. That definition
//! > obviously includes the Rust definiton of safety — memory safety.
//!
//! # Feature flags
//!
//! None so far.
//!
//! # What’s included?
//!
//! luminance is a rendering crate, not a 3D engine nor a video game framework. As so, it doesn’t
//! include specific concepts, such as lights, materials, asset management nor scene description. It
//! only provides a rendering library you can plug in whatever you want to.
//!
//! > There are several so-called 3D-engines out there on [crates.io](https://crates.io). Feel free
//! > to have a look around.
//!
//! However, luminance comes with several interesting features:
//!
//! - **Buffers**: buffers are ways to communicate with the GPU; they represent regions of memory
//! you can write to and read from. There’re several kinds of buffers you can create, among
//! *vertex and index buffers*, *uniform buffers*, and so on and so forth…. They look like
//! regular array but have some differences you might be aware of. Most of the time, you will
//! use them to customize behaviors in shader stages.
//! - **Framebuffers**: framebuffers are used to hold renders. Each time you want to perform a
//! render, you need to perform it into a framebuffer. Framebuffers can then be combined with
//! each other to produce effects and design render layers — this is called compositing.
//! - **Shaders**: luminance supports five kinds of shader stages:
//! - Vertex shaders.
//! - Tessellation control shaders.
//! - Tessellation evaluation shaders.
//! - Geometry shaders.
//! - Fragment shaders.
//! - **Vertices, indices, primitives and tessellations**: those are used to define a shape you
//! can render into a framebuffer with a shader. They are mandatory when it comes to rendering.
//! Even if you don’t need vertex data, you still need tessellations to issue draw calls.
//! - **Textures**: textures represent information packed into arrays on the GPU, and can be used
//! to customize a visual aspect or pass information around in shaders. They come in several
//! flavours — e.g. 1D, 2D, cube maps, etc.
//! - **Control on the render state**: the render state is a set of capabilities you can tweak
//! to draw frames. It includes:
//! - The blending equation and factors. Blending is the process of taking two colors from two
//! framebuffers and mixing them.
//! - Whether we should have a depth test performed.
//! - Face culling.
//! - Etc.
//! - And a lot of other cool things like *GPU commands*, *pipelines*, *uniform interfaces* and so
//! on…
//!
//! # How to dig in?
//!
//! luminance is written to be fairly simple. There are several ways to learn how to use luminance:
//!
//! - The [online documentation](https://docs.rs/luminance) is a mandatory start for newcomers.
//! - The [“Learn luminance” book](https://rust-tutorials.github.io/learn-luminance). Ideal for
//! newcomers as well as people already used to luminance, as it’s always updated to the latest
//! version — you might learn new things!
//! - The [luminance-examples](https://github.com/phaazon/luminance-rs/tree/master/luminance-examples)
//! project. It contains lots of examples describing how to do specifics things. Not adapted for
//! newcomers, you will likely want to consult those examples if you’re already familiar with
//! graphics programing and to look for how to do a specific thing.
//!
//! # Implementation and architecture
//!
//! **luminance** has been originally designed around the OpenGL 3.3 and OpenGL 4.5 APIs. However,
//! it has mutated to adapt to new technologies and modern graphics programming. Even though its API
//! is _not_ meant to converge towards something like Vulkan, it’s changing over time to meet
//! better design decisions and performance implications.
//!
//! The current state of luminance comprises several crates:
//!
//! - A “core” crate, [luminance], which is about all the
//! abstract, common and interface code.
//! - A set of _backend implementation_ crates, implementing the [luminance] crate.
//! - A set of _windowing_ crates, executing your code written with the core and backend crate.
//! - A special crate, [luminance-front], a special _backend_ crate that allows to combine
//! several “official” crates to provide a cross-platform experience without having to pick
//! several backend crates — the crate does it for you. This crate is mainly designed for end-user
//! crates.
//!
//! ## The core crate
//!
//! The luminance crate gathers all the logic and rendering abstractions necessary to write code
//! over various graphics technologies. It contains parametric types and functions that depend on
//! the actual _implementation type_ — as a convention, the type variable `B` (for backend) is
//! used. For instance, the type `Buffer<B, u8>` is an 8-bit unsigned integer buffer for which the
//! implementation is provided via the `B` type.
//!
//! Backend types — i.e. `B` — are not provided by [luminance] directly. They are typically
//! provided by crates containing the name of the technology as suffix, such as luminance-gl,
//! luminance-webgl, luminance-vk, etc. The interface between those backend crates and
//! luminance is specified in [luminance::backend].
//!
//! On a general note, `Buffer<ConcreteType, u8>` is a monomorphic type that will be usable
//! **only** with code working over the `ConcreteType` backend. If you want to write a function
//! that accepts an 8-bit integer buffer without specifying a concrete type, you will have to
//! write something along the lines of:
//!
//! ```
//! use luminance::backend::buffer::Buffer as BufferBackend;
//! use luminance::buffer::Buffer;
//!
//! fn work<B>(b: &Buffer<B, u8>) where B: BufferBackend<u8> {
//! todo!();
//! }
//! ```
//!
//! This kind of code is intented for people writing libraries with luminance. For the special case
//! of using the [luminance-front] crate, you will end up writing something like:
//!
//! ```ignore
//! use luminance_front::buffer::Buffer;
//!
//! fn work(b: &Buffer<u8>) {
//! todo()!;
//! }
//! ```
//!
//! > In [luminance-front], the backend type is selected at compile and link time. This is often
//! > what people want, but keep in mind that [luminance-front] doesn’t allow to have several
//! > backend types at the same time, which might be something you would like to use, too.
//!
//! ## Backend implementations
//!
//! Backends implement the [luminance::backend] traits and provide, mostly, a single type for each
//! implementation. It’s important to understand that a backend crate can provide several backends
//! (for instance, [luminance-gl] can provide one backend — so one type — for each supported OpenGL
//! version). That backend type will be used throughout the rest of the ecosystem to deduce subsequent
//! implementors and associated types.
//!
//! If you want to implement a backend, you don’t have to push any code to any `luminance` crate.
//! `luminance-*` crates are _official_ ones, but you can write your own backend as well. The
//! interface is highly `unsafe`, though, and based mostly on `unsafe impl` on `unsafe trait`. For
//! more information, feel free to read the documentation of the [luminance::backend] module.
//!
//! ## Windowing
//!
//! luminance doesn’t know anything about the context it executes in. That means that it doesn’t
//! know whether it’s used within SDL, GLFW, glutin, Qt, a web canvas or an embedded specific hardware such as
//! the Nintendo Switch. That is actually powerful, because it allows luminance to be
//! completely agnostic of the execution platform it’s running on: one problem less. However, there
//! is an important point to take into account: a single backend type can be used with several windowing
//! crates / implementations. That allows to re-use a backend with several windowing
//! implementations. The backend will typically explain what are the conditions to create it (like,
//! in OpenGL, the windowing crate must set some specific flags when creating the OpenGL context).
//!
//! luminance does not provide a way to create windows because it’s important that it not depend
//! on windowing libraries – so that end-users can use whatever they like. Furthermore, such
//! libraries typically implement windowing and events features, which have nothing to do with our
//! initial purpose.
//!
//! A windowing crate supporting luminance will typically provide native types by re-exporting
//! symbols (types, functions, etc.) from a windowing crate and the necessary code to make it
//! compatible with luminance. That means providing a way to access a backend type, which
//! implements the [luminance::backend] interface.
//!
//! ## luminance-derive
//!
//! If you are compiling against the `"derive"` feature, you get access to [`luminance-derive`] automatically, which
//! provides a set of _procedural macros_.
//!
//! ### `Vertex`
//!
//! The [`Vertex`] derive proc-macro.
//!
//! That proc-macro allows you to create custom vertex types easily without having to care about
//! implementing the required traits for your types to be usable with the rest of the crate.
//!
//! The [`Vertex`] trait must be implemented if you want to use a type as vertex (passed-in via
//! slices to [`Tess`]). Either you can decide to implement it on your own, or you could just let
//! this crate do the job for you.
//!
//! > Important: the [`Vertex`] trait is `unsafe`, which means that all of its implementors must be
//! > as well. This is due to the fact that vertex formats include information about raw-level
//! > GPU memory and a bad implementation can have undefined behaviors.
//!
//! You can derive the [`Vertex`] trait if your type follows these conditions:
//!
//! - It must be a `struct` with named fields. This is just a temporary limitation that will get
//! dropped as soon as the crate is stable enough.
//! - Its fields must have a type that implements [`VertexAttrib`]. This is mandatory so that the
//! backend knows enough about the types used in the structure to correctly align memory, pick
//! the right types, etc.
//! - Its fields must have a type that implements [`HasSemantics`] as well. This trait is just a
//! type family that associates a single constant (i.e. the semantics) that the vertex attribute
//! uses.
//! - Each field's type must be different.
//!
//! Once all those requirements are met, you can derive [`Vertex`] pretty easily.
//!
//! > Note: feel free to look at the [`Semantics`] proc-macro as well, that provides a way
//! > to generate semantics types in order to completely both implement [`Semantics`] for an
//! > `enum` of your choice, but also generate *field* types you can use when defining your vertex
//! > type.
//!
//! The syntax is the following:
//!
//! ```rust
//! # use luminance_derive::{Vertex, Semantics};
//!
//! // visit the Semantics proc-macro documentation for further details
//! #[derive(Clone, Copy, Debug, PartialEq, Semantics)]
//! pub enum Semantics {
//! #[sem(name = "position", repr = "[f32; 3]", wrapper = "VertexPosition")]
//! Position,
//! #[sem(name = "color", repr = "[f32; 4]", wrapper = "VertexColor")]
//! Color
//! }
//!
//! #[derive(Clone, Copy, Debug, PartialEq, Vertex)] // just add Vertex to the list of derived traits
//! #[vertex(sem = "Semantics")] // specify the semantics to use for this type
//! struct MyVertex {
//! position: VertexPosition,
//! color: VertexColor
//! }
//! ```
//!
//! > Note: the `Semantics` enum must be public because of the implementation of [`HasSemantics`]
//! > trait.
//!
//! Besides the `Semantics`-related code, this will:
//!
//! - Create a type called `MyVertex`, a struct that will hold a single vertex.
//! - Implement `Vertex for MyVertex`.
//!
//! The proc-macro also supports an optional `#[vertex(instanced = "<bool>")]` struct attribute.
//! This attribute allows you to specify whether the fields are to be instanced or not. For more
//! about that, have a look at [`VertexInstancing`].
//!
//! ### `Semantics`
//!
//! The [`Semantics`] derive proc-macro.
//!
//! ### `UniformInterface`
//!
//! The [`UniformInterface`] derive proc-macro.
//!
//! The procedural macro is very simple to use. You declare a struct as you would normally do:
//!
//! ```
//! # use luminance::shader::Uniform;
//! # use luminance_derive::UniformInterface;
//!
//! #[derive(Debug, UniformInterface)]
//! struct MyIface {
//! time: Uniform<f32>,
//! resolution: Uniform<[f32; 4]>
//! }
//! ```
//!
//! The effect of this declaration is declaring the `MyIface` struct along with an effective
//! implementation of `UniformInterface` that will try to get the `"time"` and `"resolution"`
//! uniforms in the corresponding shader program. If any of the two uniforms fails to map (inactive
//! uniform, for instance), the whole struct cannot be generated, and an error is arisen (see
//! `UniformInterface::uniform_interface`’s documentation for further details).
//!
//! If you don’t use a parameter in your shader, you might not want the whole interface to fail
//! building if that parameter cannot be mapped. You can do that via the `#[unbound]` field
//! attribute:
//!
//! ```
//! # use luminance::shader::Uniform;
//! # use luminance_derive::UniformInterface;
//!
//! #[derive(Debug, UniformInterface)]
//! struct MyIface {
//! #[uniform(unbound)]
//! time: Uniform<f32>, // if this field cannot be mapped, it’ll be ignored
//! resolution: Uniform<[f32; 4]>
//! }
//! ```
//!
//! You can also change the default mapping with the `#[uniform(name = "string_mapping")]`
//! attribute. This changes the name that must be queried from the shader program for the mapping
//! to be complete:
//!
//! ```
//! # use luminance::shader::Uniform;
//! # use luminance_derive::UniformInterface;
//!
//! #[derive(Debug, UniformInterface)]
//! struct MyIface {
//! time: Uniform<f32>,
//! #[uniform(name = "res")]
//! resolution: Uniform<[f32; 4]> // maps "res" from the shader program
//! }
//! ```
//!
//! Finally, you can mix both attributes if you want to change the mapping and have an unbound
//! uniform if it cannot be mapped:
//!
//! ```
//! # use luminance::shader::Uniform;
//! # use luminance_derive::UniformInterface;
//!
//! #[derive(Debug, UniformInterface)]
//! struct MyIface {
//! time: Uniform<f32>,
//! #[uniform(name = "res", unbound)]
//! resolution: Uniform<[f32; 4]> // must map "res" from the shader program and ignored otherwise
//! }
//! ```
//!
//!
//! [luminance]: https://crates.io/crates/luminance
//! [luminance-gl]: https://crates.io/crates/luminance-gl
//! [luminance-front]: https://crates.io/crates/luminance-front
//! [luminance::backend]: crate::backend
//! [`Semantics`]: https://docs.rs/luminance/latest/luminance/vertex/trait.Semantics.html
//! [`HasSemantics`]: https://docs.rs/luminance/latest/luminance/vertex/trait.HasSemantics.html
//! [`Tess`]: https://docs.rs/luminance/latest/luminance/tess/struct.Tess.html
//! [`Vertex`]: https://docs.rs/luminance/latest/luminance/vertex/trait.Vertex.html
//! [`VertexAttrib`]: https://docs.rs/luminance/latest/luminance/vertex/trait.VertexAttrib.html
//! [`VertexInstancing`]: https://docs.rs/luminance/latest/luminance/vertex/enum.VertexInstancing.html
//! [`UniformInterface`]: https://docs.rs/luminance/latest/luminance/shader/program/trait.UniformInterface.html
#![doc(
html_logo_url = "https://github.com/phaazon/luminance-rs/blob/master/docs/imgs/luminance_alt.svg"
)]
#![deny(missing_docs)]
#[cfg(feature = "derive")]
pub use luminance_derive::*;
pub mod backend;
pub mod blending;
pub mod buffer;
pub mod context;
pub mod depth_test;
pub mod face_culling;
pub mod framebuffer;
pub mod pipeline;
pub mod pixel;
pub mod query;
pub mod render_gate;
pub mod render_state;
pub mod scissor;
pub mod shader;
pub mod shading_gate;
pub mod tess;
pub mod tess_gate;
pub mod texture;
pub mod vertex;