Skip to content

Commit

Permalink
Change stamp-square.png figure
Browse files Browse the repository at this point in the history
  • Loading branch information
ShenCiao committed Jan 29, 2024
1 parent 1f6ed81 commit 2961be9
Show file tree
Hide file tree
Showing 8 changed files with 47 additions and 25 deletions.
21 changes: 11 additions & 10 deletions docs/Airbrush/Airbrush.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,9 @@ If you've learned the previous chapter, rendering an airbrush is nothing more th
![toairbrush0](to-air0.gif)
![toairbrush1](to-air1.gif)

When artists draw illustrations or animations, airbrush has special usages like coloring, shading, or highlighting an illustration,
while other brushes are typically used for drawing outlines.
When artists draw illustrations or animations, airbrush has special usages.
While other brushes are commonly used for drawing outlines, airbrush is used for coloring or drawing shadow and highlight regions.
As the image below shows, the artist repeatedly stroke on the sphere with airbrushes to draw shadow or highlight.

![shade](shade-highlight.gif)

Expand All @@ -35,29 +36,29 @@ Imagine there are infinite number of stamps on an edge whose length is $L$.
The number of stamps is denoted with $n$, and the interval between stamps is $\Delta L = L/n$.
We continue the idea of "articulated", calculate edges individually and blend them together.
For each pixel whose position is $\pmb p$ invoked by the edge,
its alpha value $\Alpha(\pmb p)$ is equal to blend all the alpha values $\Alpha_s(\pmb p_i)$ from all the stamps on the edge.
The $\pmb{p_i}$ is the vector from stamp $i$ and the current pixel.
its alpha value $\Alpha(\pmb p)$ is equal to blend all the alpha values $\Alpha_s(\pmb d_i)$ from all the stamps on the edge.
The $\pmb d_i$ is the vector from stamp $i$ and the current pixel.

$$
\Alpha(\pmb p) = 1-\prod_{i=1}^n \left(1-\Alpha_s(\pmb p_i)\right)
\Alpha(\pmb p) = 1-\prod_{i=1}^n \left(1-\Alpha_s(\pmb d_i)\right)
$$

We define "alpha density" value, denoted with small alpha $\alpha$.
Let $\Alpha_s(\pmb p_i) = \alpha_s(\pmb p_i) \Delta L$, $\alpha_s(\pmb p_i)$ is called alpha density field and defined by the footprint.
Let $\Alpha_s(\pmb d_i) = \alpha_s(\pmb d_i) \Delta L$, $\alpha_s(\pmb d_i)$ is called alpha density field and defined by the footprint.
Hopefully, the notations remind you of the probability density and probability values
(or uniformly distributed charge on a bar, and we are integrating its electric field).

Replace the $\Alpha_s(\pmb p_i)$ and we get:
Replace the $\Alpha_s(\pmb d_i)$ and we get:

$$
\Alpha(\pmb p) = 1-\prod_{i=1}^n (1-\alpha_s(\pmb p_i) \Delta L)
\Alpha(\pmb p) = 1-\prod_{i=1}^n (1-\alpha_s(\pmb d_i) \Delta L)
$$

So, given any $\alpha_s(\pmb p_i)$ function,
So, given any $\alpha_s(\pmb d_i)$ function,
we can calculate the stamp strokes' continuous form by substituting the function into the formula.

We reuse the old local coordinate, originating at $p_0$, and X and Y axes align to the tangent and normal direction.
So, $\pmb p = (x, y)$ and $\pmb p_i = (x - l_i, y)$ in the coordinate.
So, $\pmb p = (x, y)$ and $\pmb d_i = (x - l_i, y)$ in the coordinate.
The $l_i$ is the X position of stamp i.
As $n\rightarrow \infty$ and $\Delta L \rightarrow 0$, and apply [product integral](https://en.wikipedia.org/wiki/Product_integral) (Volterra Integral) on the formula.

Expand Down
24 changes: 17 additions & 7 deletions docs/Basics/Basics/Basics.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@ title: Problem Statement

![krita](https://gitlab.com/raghukamath/krita-brush-presets/-/raw/master/preview.png)

_Open-source [brush presets by Raghavendra](https://gitlab.com/raghukamath/krita-brush-presets) in Krita._
<figcaption>
Open-source [brush presets by Raghavendra](https://gitlab.com/raghukamath/krita-brush-presets) in Krita.
</figcaption>

In graphics design software such as Photoshop and Krita, you can use a wide range of brushes within the paint tool.
Learning how to render these stylized strokes with GPU is valuable.
Expand All @@ -25,10 +27,14 @@ Knowing how to render a line is very handy when drawing UIs or debugging your 3D
While you may recognize a brush stroke by its stylization, another crucial property could be ignored:
the "variable width" along the stroke.
The property is critical for experienced artists drawing professional illustrations or animations.
For instance, you can tell the difference from the figure below.
The one with variable width on the right has much better appearance.
For instance, you can tell the significant difference from the figure below.
The one with variable width on the right has more expressive appearance.

![bunny](./bunny-compare.png)
![butterfly](./butterfly-compare.png)

<figcaption>
Butterfly by [Qianxi Liu](https://qianxi-folio.vercel.app/index.html).
</figcaption>

The width values are typically generated from the pressure values as a stylus presses and moves on a tablet.
After the artists install a new painting program,
Expand All @@ -53,7 +59,10 @@ Meanwhile, the pen pressure is transformed into the radius value assigned to eac
After rendering the stroke on the polyline, the user feels like drawing on canvas.

![Monkey](./monkey.png)
_The monkey Suzanne in Blender (Grease Pencil), the orange dots on the right side show polylines' points (vertices)._

<figcaption>
The monkey Suzanne in Blender (Grease Pencil), the orange dots on the right side show polylines' points (vertices).
</figcaption>

We can approximate any type of curve by increasing the number of points in a polyline, whether freehand-drawn or mathematically defined.
Try to change the `maxRadius` and `segmentCount` values in the code editor below to see how the vanilla stroke changes.
Expand All @@ -64,5 +73,6 @@ import { ArticulatedLine2D } from "@site/src/components/ArticulatedLine2D";

<ArticulatedLine2D showEditor={[true, false, false]} />

Blender Grease Pencil team has developed a lot of novel tools to edit polylines.
Remember to check out if you were a researcher and want to develop novel techniques for digital painting.
Blender Grease Pencil team has developed many novel tools to edit polylines.
I recommend that everyone researching digital painting techniques learn about them.
https://www.youtube.com/watch?v=nZyB30-xZFs
Binary file added docs/Basics/Basics/butterfly-compare.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
17 changes: 12 additions & 5 deletions docs/Basics/Stamp/Stamp.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,13 @@ Therefore, I will introduce how to place footprints equidistantly along a polyli

## Locate stamps

When rendering with CPU, calculating where to place stamp (stamp positions) on a polyline is pretty straightforward.
When rendering with CPU, calculating where to place footprint (stamp positions) on a polyline is pretty straightforward.
Start from the very first vertex of the polyline,
place the footprint on the canvas,
move along the polyline with the stamp interval to the next stamp position,
loop until reach the end of polyline.
It is trivial for experienced developers to implement the process above.
If we use an image processing library and therefore don't worry about details in placing the footprint,
the whole process can programmed within 10 lines of code.

![pos](./stamp-position.png)

Expand All @@ -45,7 +47,7 @@ The difference only comes to the fragment shader.

We will calculate the stamp positions in the fragment shader.
At each polyline vertex, we compute its distance to the first vertex along the polyline.
The distances represent the cumulative length of the edges, and we calculated them with Prefix Sum algorithm.
The distances represent the cumulative length of the edges, and we calculated them with [Prefix Sum][wiki](https://www.geeksforgeeks.org/prefix-sum-array-implementation-applications-competitive-programming/) algorithm.

![len](./stamp-length.png)

Expand Down Expand Up @@ -156,13 +158,17 @@ But they may hurt the performance and have complex logic to implement.

I will introduce a very tricky approach to rendering the square footprint.
Meanwhile, improve the rendering performance and reduce the complexity of the shader code.
All we have to sacrifice is the "correctness" of geometry, which is trivial for artists.
All we have to sacrifice is the "correctness" of geometry, which is a minor concern for artists.

We place vertices a little bit differently from before.
Instead of offset vertices by $r_0\tan\frac{\theta}{2}$ and $r_1\cot\frac{\theta}{2}$ along the normal direction,
we just offset $r_0$ and $r_1$ value, as the figure below shows.

![square](./stamp-square.png)
<figcaption>
The solid line trapezoid shows the new approach to place vertices.
Dashed grey line trapezoid shows the original approach.
</figcaption>

In the vertex shader or geometry shader, we put the radius value $r_0$ to the left two vertices,
$r_1$ to the right two vertices, and let fragment shader interpolate the values for us.
Expand All @@ -174,4 +180,5 @@ import StampSquare from "./StampSquare";

<StampSquare showEditor={[false, true, true]}/>

I cannot perceive the deformation caused by the trick without careful investigation.
You can find the shader code is simplified because we don't need to compute two roots of the quadratic equation.
I cannot perceive any deformation caused by the trick without careful investigation.
Binary file modified docs/Basics/Stamp/stamp-square.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions docs/Basics/Stamp/stampSquare.frag
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ void main() {
float x1 = pLocal.x - rp;
float x2 = pLocal.x + rp;

// --- The rest of code is exactly same. ---
float index0 = l0/interval;
float startIndex, endIndex;
if (x1 <= 0.0){
Expand Down
3 changes: 0 additions & 3 deletions docs/Basics/Stamp/stampSquare.vert
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,6 @@ precision mediump int;
uniform mat4 modelViewMatrix;
uniform mat4 projectionMatrix;

// Every lines of code are the same, except for the length.
// `length` is the distance from the current vertex to the very first vertex of the polyline
// (the result of prefix sum on edge length).
in float length0;
in float length1;
in float radius0;
Expand Down
6 changes: 6 additions & 0 deletions src/css/custom.css
Original file line number Diff line number Diff line change
Expand Up @@ -37,4 +37,10 @@

.katex-mathml{
font-size: 18px;
}

figcaption{
text-after-overflow: 0;
padding-bottom: 0.5em;
font-style: italic;
}

0 comments on commit 2961be9

Please sign in to comment.