luminance has
been having lots of activity lately. I’ve been working (hard) on
making it to the 1.0 release for months now and came
to a very important realization: lots of changes have been done
and I’m still not ready to release it. I’ve kind of lost myself in
the process.
This article is about two main topics:
If you don’t care about the changes, feel free to go read this to know how you can learn about luminance and graphics programming in general.
Lately, luminance has
received a wide range of feature additions, bug fixes and design
ideas. I’ve been wanting to release all those changes as part of
the 1.0 release but the thing is: among all the
changes, some have been around on the master branch
for months without a proper release on crates.io… because the
1.0 milestone was not reached. People have been
moving towards luminance more and
more and some provided feedback about using luminance. Happy but
indecisive about what to do, I faced a dilemma:
1.0
but eventually block people from using all the cool
features of luminance because
the last release on crates.io is months old.1.0 for
everything and 0.31 for all the new candies.I have decided to go with the second option.
Just before writing this article, the last luminance
version was 0.30 — just for the record, that
version is eleven months old, ~200 commits behind
master. The new and most recent version is thus
0.31 and crates got updated:
#[derive(..)] construct.Lot of work has been accomplished and I received several contributions from people all around the globe, including PRs and issues. I’d like to remind that I appreciate both and you are really encouraged to contribute in any way you want to. Special thanks fly to:
About that last point, my Reddit and Twitter interactions about luminance have been very interesting because I got to test the water about how people feel about luminance, especially when compared to (not so) similar crates, such as [gfx], glium or even gl. I came to the realization, after reading people and what they would love to have as a graphics crate, that luminance can have the role of the easy crate, that is not necessarily the fastest but fast enough to be quickly productive. I cannot help it but keep thinking about a simple question: if some people can make games in Java or C# with a garbage collector or using old tech like OpenGL 2.1 (yes, some people still make pretty good games with that), why would one need a perfect zero-cost abstraction down-to-the-metal unsafe ultra-optimized crate to write something? See, I went round and squares about that topic, because I’ve already used luminance in several projects of mine (mostly demoscene purposes), and it just does the job. So, yes, luminance doesn’t have that cool, new and modern Vulkan-type API, I must confess. But it has its own API, which is very functional-based (see the History section of luminance for further details about that) and, to me, modern enough so that people don’t get frustrated with the overall design being too clunky.
So, yeah. I gave up on the idea of introducing backends in luminance. I really changed my mind several times about that topic and it’s actually when I read comments on Reddit about people getting confused about the direction of the crate that I made up my mind: luminance must remain simple. Having a system of backends that can be hot-switched, concurrent etc. is just going to make things hard for people to use it — and maintain it! It’s likely that I will introduce, however, feature-gates to allow to compile luminance on WebAssembly via WebGL, OpenGL ES or even Vulkan at some point, but the difference is that no backend will be implemented. That means that those feature-flags aren’t likely to be summable at first. But all of this will be done in future releases; stay tuned.
The current blog post brings a description of all the changes
of luminance-0.31.
It should be the last 0.*.* version before hitting
the 1.0 release. To the question:
Why not releasing
1.0directly?
I answer that the 1.0 milestone has a backlog with
two major changes that will take time to implement and I think it
would be a pity to postpone a lot of great changes that are
already available because of two features that are yet to be
implemented. The concept of versions is to allow releasing
features in a structured way without having to wait too much. So
here we are.
This post also show cases a small tutorial about how to get started with luminance. The very first steps you should have would be to have a look at the examples/ directory and try to play with all of the samples.
Disclaimer: the following section of this article is based on luminance’s changelog.
panic! and attributeless
renders.Format::R and
Format::RG when querying a texture’s texels.GTup. No code was using it
and it was not really elegant.uniform_interface! macro and replace
it with the UniformInterface procedural derive
macro.mut operation.
That is required to lock-in the mapped slices and prevent
to generate new ones, which would be an undefined behavior in most
graphics backends such as OpenGL.Texture<..> type anymore, as a type family is
now used to ease the generation of color and depth slots).Vertex trait is implemented.
Vertex::vertex_format method has been renamed
Vertex::vertex_desc.VertexFormat, that method
now returns a VertexDesc. Where a
VertexFormat was a set of
VertexComponentFormat, a VertexDesc is a
set of VertexBufferDesc.VertexBufferDesc is a new type that didn’t exist
back then in 0.30. It provides new data and information
about how a vertex attribute will be spread in a GPU buffer.
Especially, it has:
VertexAttribDesc, the new name of
VertexComponentFormat.VertexComponentFormat was renamed
VertexAttribDesc.VertexAttribType’s integral
variants.VertexAttrib. Such a
trait is used to map a type to a
VertexAttribDesc.Vertex has zero implementor instead of several
ones in 0.30. The reason for that is that
VertexBufferDesc is application-driven and depends on
the vertex semantics in place in the application or
library.Semantics trait. Implementing
directly Semantics is possible, even though not
recommended. Basically, Semantics provides
information such as the index and name of a
given semantics as long as the list of all possible semantics,
encoded by SemanticsDesc.Vertex
and Semantics proc-macro derive in the
[luminance-derive] crate.Tess type to make it easier to work
with.
Tess::new and
Tess::attributeless functions were removed.TessBuilder type was added and replace both
the above function.a ..= b operator, allowing to slice a
Tess with inclusive closed bounds...= b operator, allowing to slice a
Tess with inclusive bounds open on the left
side.Tess::new associated function
expected indices to be a slice of u32. This new
release allows to use any type that implements the
TessIndex trait (mapping a type to a
TessIndexType. Currently, you have u8,
u16 and u32 available.Tess::{as_index_slice,as_index_slice_mut}.
Those now enable you to conditionally slice-map the index
buffer of a Tess, if it exists.SamplerType trait, used as constraint on the
Pixel::SamplerType associated type.Floating texture without caring about the actual
type. That is especially true as you typically use
sampler2D in a shader and not
sampler2DRGB32F.layout (location = _) is correctly set to the right
value regarding what you have in your Tess’ vertex
buffers. That was both unsafe and terribly misleading
(and not very elegant). The new situation, which relies on
vertex semantics, completely gets rid of vertex
locations worries, which get overrided by luminance when a
shader program gets linked.enums — such as
DepthTest — variants from Enabled /
Disabled to On / Off or
Yes / No, depending on the
situation.swap_buffers from
GraphicsContext to Surface in
[luminance-windowing].GenMipmaps instead of bool
to encode whether mipmaps should be generated in texture code.
That change is a readability enhancement when facing texture
creation code.Dimensionable::zero_offset() a constant,
Dimensionable::ZERO_OFFSET.bool
to CursorMode.unsafe can be
implemented in a safe way with that crate, so you should
definitely try to use it.#[derive(Vertex)]: derive the Vertex
trait for a struct.#[derive(Semantics)]: derive the
Semantics trait for an enum.#[derive(UniformInterface)]: derive the
UniformInterface trait for a
struct.Program<_, _, ()> and
still set uniform values by querying the uniforms dynamically.
This feature also fully benefits from the strongly typed interface
of Uniform<_>, so you will get
TypeMismatch runtime error if you try to trick the
type system.std feature gate, allowing to compile
with the standard library – this is enabled by default. The
purpose of this feature is to allow people to use
default-features = false to compile without the
standard library. This feature is currently very experimental and
shouldn’t be used in any production releases so far – expect
breakage / undefined behaviors as this feature hasn’t been quite
intensively tested yet.R11FG11FB10F pixel
format.WindowOpt now has support for multisampling.
See the WindowOpt::set_num_samples for further
details.Norm is a normalized pixel format. Such
formats state that the texels are encoded as integers but when
fetched from a shader, they are turned into floating-point number
by normalizing them. For instance, when fetching pixels from a
texture encoded with R8UI, you get integers ranging
in [0; 255] but when fetching pixels from a texture
encoded with NormR8UI, even though texels are still
stored as 8-bit unsigned integers, when fetched, you get
floating-point numbers comprised in [0; 1].std::mem::uninitialized references, as it
is now on deprecation path. Fortunately, the codes that were using
that function got patched with safe Rust (!) and/or simpler
constructs. It’s a win-win.#[repr(C)] annotation on vertex types in
examples. That is a bit unfortunate because such an annotation is
very likely to be mandatory when sending data to the GPU and it
should be done automatically instead of requiring the user to do
it. That situation will be fixed in a next release.cargo run --example command. Read more here.#![deny(missing_docs)]. The situation is still not
perfect and patch versions will be released to fix and update the
documentation. Step by step.11-query-texture-texels example, which
showcases how to query a texture’s texels and drop it on the
filesystem.irc.freenode.net#luminanceI also spent quite a lot of time and energy working on two ways to learn luminance:
So far, I’m writing articles and the wiki is going to be updated let’s say, every week, if I find enough spare time. You can also tell me what kind of stuff you’d like to learn and do.
The official documentation is up to date but is not as good as I expect it to be. I will be adding patches versions to 0.31 to update it.
I hope you like luminance and will make a good use of it. And of course, keep the vibes!