How a Diffusion Transformer Generates Shapes from Text

An interactive guide to Diffusion Transformers and Flow Matching, using a simple model that turns random dots into shapes.

Image models like Stable Diffusion 3 and FLUX rely on a Diffusion Transformer (DiT) paired with Flow Matching. This article uses a simple DiT model to illustrate the core mechanics behind these systems.

Given a prompt like circle on triangle, generation begins with 24 random points. The model moves them step by step. In the end, the points form the outlines of the scene described in the prompt.

Demo

Prompts can name a single shape, like circle, or combine two shapes with a spatial relation, like circle on square.

Every prompt is composed of up to 4 tokens, drawn from a 12-word vocabulary:

  • Shapes: dot, circle, triangle, square
  • Relations: on, above, under, below, left, right, of
  • Padding: PAD (fills unused slots)
Shift
0.30
Steps
100

Input
Attention
Output

Architecture

The model works in three stages: embedding, attention, and projection.

Diffusion Transformer (DiT) architecture

Diffusion Transformer (DiT) architecture

The model receives three types of inputs. Each is mapped to a 64-dimensional vector:

  • 1 Timestep: Tells the model where it is on the path from noise to shape. Encoded with sinusoidal encoding.
  • 4 Text tokens: Contain the prompt words. Encoded with learned word embeddings and positional encodings.
  • 24 Coordinate points: Represent the (x, y) positions at the current timestep. Projected using a linear layer.

The model merges these vectors into a single 29-token sequence and passes them through 2 transformer layers. Each layer runs self-attention with 2 heads, followed by an MLP.

The output layer turns each of the 24 point tokens into a velocity, the direction from shape to noise. The points are moved slightly in the opposite direction. Repeating this process forms the shape.

Timestep Embedding

To predict the direction, the model must know where the points are on their path from noise to shape. The timestep tt indicates this progress as it decreases from 1 to 0. The value is encoded with sine and cosine waves, called sinusoidal encoding. Most waves barely move over such a small range, so tt is scaled by 100 first. The result is a 64-dimensional vector:

ek(t)=(sin⁡100 ωkt,  cos⁡100 ωkt),ωk=1b2k/D\mathbf{e}_k(t) = (\sin 100\,\omega_k t, \; \cos 100\,\omega_k t), \qquad \omega_k = \frac{1}{b^{2k / D}}

Here, D = 64 is the dimension, k runs from 0 to 31 for each sine-cosine pair, and base b = 500 sets the frequency range.

Shift
0.30
Steps
100
Timestep Embeddings
t=1.00
[-0.51, 0.62, …, 0.97]

Plotted in 3D, the components form a landscape of waves across time. The sliders show how the base and the dimension reshape it:

Dim
D = 64
Base
b = 500

Sinusoidal encoding. Each ridge shows how an individual component changes over 100 timesteps.

Close timesteps should get close vectors. In vector space, similarity is measured with the dot product. Pairing sine with cosine makes this similarity depend only on the time difference. Consider two 2D encodings a=(sin⁡t1, cos⁡t1)\mathbf{a} = (\sin t_1, \, \cos t_1) and b=(sin⁡t2, cos⁡t2)\mathbf{b} = (\sin t_2, \, \cos t_2), in this case with ω=1\omega = 1. Their dot product simplifies via the angle difference identity:

a⋅b=sin⁡t1sin⁡t2+cos⁡t1cos⁡t2=cos⁡(t1−t2)\mathbf{a} \cdot \mathbf{b} = \sin t_1 \sin t_2 + \cos t_1 \cos t_2 = \cos(t_1 - t_2)

Both vectors have length 1, so the dot product is their cosine similarity. While a single wave repeats every few steps, combining 32 frequencies makes the similarity fall as the timesteps move apart.

The encoding works like a clock with 32 hands. Each sine and cosine pair sets the position of one hand. Just as humans use hours, minutes, and seconds instead of counting only seconds, the network processes time more easily when split across multiple frequencies.

Dim
D = 64
Base
b = 500
t0.00
cosSim(t0.00, t)t010.00
1.00

Shorter hands represent high frequencies and spin quickly, while longer hands represent low frequencies and turn slowly.

Text Embedding

The model uses the prompt to know which shapes to draw and where to place them. Each prompt has a fixed length of 4 tokens from a 12-word vocabulary. A learned embedding table maps each token to a 64-dimensional vector. Unused slots are filled with PAD.

text
embedding table
text embeddings
PAD
circle
square
triangle
dot
on
above
under
below
left
right
of

A positional encoding is added to each vector so the model can tell the difference between triangle on circle and circle on triangle.

Instead of learned positional embeddings (as in How a Transformer Plays Tic-Tac-Toe), the model follows the original Attention Is All You Need paper and uses sinusoidal encoding (with base b = 10).

Coordinate Projection

The third input is the (x,y)(x, y) coordinates of 24 points at timestep tt. A learned linear layer with weights and biases projects each coordinate pair into a 64-dimensional vector:

t = -.--
Wpos
xWpos+bposx W_{\text{pos}} + b_{\text{pos}}
coordinates
coordinate embeddings
→

Note: Matrix multiplications visualized as a row–column diagram. Rows are separated to show each token is processed independently.

Attention Patterns

Attention is where tokens exchange information. The mechanics of queries (Q), keys (K), and values (V) are covered in How a Transformer Plays Tic-Tac-Toe.

The model has 2 layers with 2 heads each, a width of D = 64, and a context length of 29 tokens. Every point can attend to all other points, the prompt words, and the timestep. The only mask hides the empty PAD slots in the prompt.

In the last steps of generation, the second layer shows a distinct role for each head:

  • Head 1 assigns points to shapes. Points attending to "triangle" form the triangle on the canvas, while points attending to "circle" form the circle.
  • Head 2 tracks neighboring points. Each row shows three or four activations: the point itself on the diagonal, plus its left and right neighbors along the outline.
Shift
0.30
Steps
100

Layer 1
Layer 2
Run model to see attention matrix

Click inside the green box to highlight where the corresponding points are located.

Velocity Projection

The timestep and prompt tokens have conditioned the points in attention and are no longer needed. The model keeps only the 24 point vectors.

A final linear layer with learned weights and biases projects each point vector to a 2D velocity: the direction from the shape toward noise.

t = -.--
Wout
hWout+bouth W_{\text{out}} + b_{\text{out}}
hidden states
predicted velocity
→

Each point then moves the opposite way, from noise toward the shape, and the timestep tt decreases. The model runs again on the updated points and timestep. The loop repeats until t=0t = 0.

Flow Matching

Flow Matching connects clean shapes and random noise with straight lines. The forward process moves from shape to noise and is used in training. The reverse process moves from noise to shape and is used in generation. Both processes are described by the same formula:

xt=(1−t) x0+t ϵx_t = (1 - t)\,x_0 + t\,\epsilon

Here, x0x_0 is the clean shape, ϵ\epsilon is random noise, and xtx_t represents the points at timestep tt.

Forward Process

In the forward process, time tt runs from 0 to 1. As tt increases, the shape signal scales by (1−t)(1 - t) while the noise contribution scales by tt.

xt=x_t =
(1−t) x0(1 - t)\,x_0
++
t ϵt\,\epsilon

Solid black dots represent the current points, while faint gray circles show their destination noise positions.

The points move in straight lines. The model learns to predict the direction of these lines, called the velocity:

v=ϵ−x0v = \epsilon - x_0
[-2.24, -0.24]

Arrows represent the velocity vectors, pointing from each shape point to its corresponding noise position.

Reverse Process

The main formula can be rewritten in terms of the velocity vv:

xt=x0+t vx_t = x_0 + t\,v

This formula can be rewritten in recursive form to calculate the position of the points at the previous step, xt−Δtx_{t - \Delta t}:

xt−Δt=xt−Δt vx_{t - \Delta t} = x_t - \Delta t\,v

Generation starts at t=1t = 1, where x1=ϵx_1 = \epsilon is pure noise. The model predicts the velocity vθv_\theta, and the recursive formula calculates the next positions of the points, xt−Δtx_{t - \Delta t}. Repeating this step gradually forms the shape.

Shift
0.30
Steps
100

p0

Move the vertical slider to inspect different trajectories.

Time Shifting

Generation can use any number of steps: more steps trace the path more accurately, while fewer steps run faster.

Early models spaced these steps evenly from 1 to 0. Later systems introduced time shifting to concentrate steps where the model needs the most precision.

A shift factor ss maps the evenly spaced times tt to new times t′t':

t′=s t1+(s−1) tt' = \frac{s\,t}{1 + (s - 1)\,t}

At s=1s = 1, nothing changes. Setting s>1s > 1 puts more steps near noise, while s<1s < 1 puts more steps near the shape.

Shift
0.30
Steps
100
1.00uniform01.00shifted10
1.00

Training

The training set contains 100K samples generated by a script. Each sample pairs a text prompt with the coordinates of 24 points. Half the samples show a single centered shape. The other half pair two shapes using a spatial relation. All prompts that describe a circle on a triangle were excluded on purpose to test generalization.

dot
dot
circle
circle
triangle
triangle
square
square
triangle below square
triangle below square
circle left of triangle
circle left of triangle
dot on square
dot on square
square right of circle
square right of circle

Training samples with single shapes and shape pairs (circle-on-triangle scenes excluded).

Each training step starts with three components: a clean sample x0x_0 from the dataset, a random timestep tt between 0 and 1, and random noise ϵ\epsilon.

The forward formula mixes them into the noisy points xtx_t. The velocity formula gives the target vv from the same x0x_0 and ϵ\epsilon.

The model receives xtx_t, the timestep, and the prompt, and predicts the velocity. The prediction is compared against the target using mean squared error (MSE) loss.

Diffusion Transformer training

N(0,I)\mathcal{N}(0, I) is the standard notation for Gaussian noise with mean 0 and variance 1.

The full training code is available in the Jupyter notebook.

Generalization

Instead of memorizing fixed scenes, the model learns shapes and spatial relations as independent concepts.

For example, the prompt circle on triangle generates the scene correctly, even though the model never saw it during training.

The model can also blend shapes. For instance, the prompt square triangle produces a trapezoid.

Here are some examples not present in the training set:

circle on triangle
circle on triangle
triangle square
triangle square
triangle below circle
triangle below circle
square circle
square circle

Out-of-distribution prompts can be tested in the demo above.

This ability to combine separate concepts is called compositional generalization. It allows real image models to generate scenes never seen during training, like "a pelican riding a bicycle" or "an astronaut riding a horse".

Conclusion

The model in this article uses the same core ideas as text-to-image systems like Stable Diffusion 3 and FLUX: text and time conditioning, transformer attention between image and prompt tokens, and Flow Matching.

Production systems scale these ideas in four main ways:

2-layer DiTProduction systems
Text12-word vocabularyPretrained encoders such as T5 and CLIP turn full text prompts into vectors. They already know language, so the model understands long and detailed prompts.
Images24 points representing shapesAn autoencoder compresses RGB pixel values into a compact latent representation. The model works on the latent, not on raw pixels. This allows high-resolution images.
Architecture2 layers, D = 64, context = 29Over 20 layers, D above 1500, and a context of over 4000 tokens. The added capacity captures more complex image-text relationships.
Data100K synthetic samplesTrained on billions of web images, with descriptions parsed from alt attributes or generated by vision-language models such as CogVLM.

Generation works the same way for real images. The model starts with noise and gradually transforms it into an image that matches the text prompt.

A Visual Introduction to Rectified Flows article goes deeper into the math of Flow Matching. It shows why sampled trajectories curve and how Rectified Flow straightens them. The video by Welch Labs on the 3Blue1Brown channel gives a bigger picture of diffusion models. It covers DDPM and DDIM sampling from early diffusion models, CLIP text-image embeddings, conditioning, and other topics.