Skip to content

Commit

Permalink
Finished: Introduction
Browse files Browse the repository at this point in the history
  • Loading branch information
ShenCiao committed Sep 24, 2023
1 parent 1b7e990 commit d0201fb
Show file tree
Hide file tree
Showing 14 changed files with 258 additions and 92 deletions.
26 changes: 15 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,31 +1,35 @@
# Brush Stroke Tutorial

This is the code repository for "Brush Stroke Tutorial," powered by [Docusaurus](https://docusaurus.io/).
We may change the host and domain. Remember to star this code repository instead of bookmark the website.
Remember to star this code repository instead of bookmark the website since the host and domain might be changed.

The website will be WIP for a long time since rendering brush strokes with GPU is a newly emerged research topic.
Shen Ciao continuously update tutorials on (potentially) influential research works.
I (Shen Ciao) will continuously update tutorials on (potentially) influential research works.

## Be critical
The most contents come from Shen Ciao and Li-yi Wei's research *[Ciallo: The next generation vector paint program][Ciallo]*.

The most contents come from Shen Ciao and Li-yi Wei's research _[Ciallo: The next generation vector paint program][Ciallo]_.
It's impossible to create a perfect tutorial in the first place, so we eagerly need critiques and suggestions.
We would be grateful for creating issues or pull requests to fix typos, correct facto mistakes, and revise terrible terminology naming in this tutorial.
You can create issues or pull requests to fix typos, correct facto mistakes, and revise terrible terminology naming in this tutorial.

## Build and Develop
The textual contents on the website are written in markdown, you can easily modify them without extra web development skills.

The textual contents are written in markdown, you can easily modify them without extra web development skills.

Follow the guidance in [Docusaurus's documentation](https://docusaurus.io/docs/installation) for further development.

The project is built with javascript libraries include:

- React
- Threejs: WebGL wrapper
- monaco-edtior/react: Code editor
- monaco-editor/react: Code editor

While creating this tutorial, shen has just started learning these JavaScript libraries.
If you are familiar with these libraries and have some engineering suggestions, please raise them in the issue.
Welcome any helps to improve the code editor.

## Citation

@inproceedings{Ciallo,
author = {Ciao, Shen and Wei, Li-Yi},
title = {Ciallo: The next-Generation Vector Paint Program},
Expand All @@ -44,19 +48,19 @@ Welcome any helps to improve the code editor.
}

## License

Shield: [![CC BY-SA 4.0][cc-by-sa-shield]][cc-by-sa]

This work is licensed under a
[Creative Commons Attribution-ShareAlike 4.0 International License][cc-by-sa].

[![CC BY-SA 4.0][cc-by-sa-image]][cc-by-sa]

[cc-by-sa]: http://creativecommons.org/licenses/by-sa/4.0/
[cc-by-sa-image]: https://licensebuttons.net/l/by-sa/4.0/88x31.png
[cc-by-sa-shield]: https://img.shields.io/badge/License-CC%20BY--SA%204.0-lightgrey.svg

Feel free to use the code, algorithms and demo images in your academic or commercial project, but you cannot state them are original.

The project will change into a copyleft license after updating the content about the 3D stroke.

[Ciallo]: https://github.com/ShenCiao/Ciallo
[cc-by-sa]: http://creativecommons.org/licenses/by-sa/4.0/
[cc-by-sa-image]: https://licensebuttons.net/l/by-sa/4.0/88x31.png
[cc-by-sa-shield]: https://img.shields.io/badge/License-CC%20BY--SA%204.0-lightgrey.svg
[Ciallo]: https://github.com/ShenCiao/Ciallo
2 changes: 1 addition & 1 deletion docs/Appendix/Vector-fill/Vector-fill.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,4 @@ algorithms to locate a point better than the naive solution.
To dive deeper, you may try using the [CGAL 2D arrangement library](https://doc.cgal.org/latest/Arrangement_on_surface_2/index.html)
and learn the arrangement constructed from 2D polylines, which is slightly different with a naive polygon mesh.

I hope the "2D mesh metaphor" will help you better understand the problems and solutions. Wish you happy learning!
I hope this "2D mesh metaphor" will help you better understand the problems.
6 changes: 1 addition & 5 deletions docs/Basics/Vanilla.mdx
Original file line number Diff line number Diff line change
@@ -1,7 +1,3 @@
---
position: 1
sidebar_position: 1
---

import {ArticulatedLine2D, pencilBrushUniforms} from "../../src/components/ArticulatedLine2D";

<ArticulatedLine2D uniforms={pencilBrushUniforms}/>
47 changes: 34 additions & 13 deletions docs/Introduction/Introduction.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -24,16 +24,15 @@ But time has changed, now we have modern GPU hardware crafted for graphics and p
and directly accessing a GPU framebuffer from a CPU can significantly hurt the performance.
So old algorithms may not satisfy your needs for real-time rendering.

In this tutorial, you will learn about the brush stroke rendering (or brush rendering, stroke rendering for abbreviation)
algorithms designed for the GPU graphics pipeline.
We (I and my mentor [Liyi-Wei](https://www.liyiwei.org/)) name these algorithms as _Articulated_ in our paper (mainly because they look like drawing an articulated arm).
In this tutorial, you will learn about the brush stroke rendering algorithms designed for the GPU graphics pipeline.
We (I and my mentor [Liyi-Wei](https://www.liyiwei.org/)) call these algorithms _Articulated_ in our paper, because they look like drawing an articulated arm.
I assume our readers are already familiar with a graphics API like OpenGL or D3D.
This tutorial will concentrate more on the high-level algorithms than the implementation details.

Although graphics APIs provide us line primitives, including `LINES`, `LINE_STRIP`, and `LINE_LOOP`,
there are several well-known issues when using these primitives directly.
Check out Matt Deslauries' article [_Drawing Lines is Hard_](https://mattdesl.svbtle.com/drawing-lines-is-hard#line-primitives_1) if you know nothing about them.
As for the brush rendering, the most significant issue is the limitation on the maximum line width or stroke radius.
As for our brush rendering, the most significant issue is the limitation on the maximum line width or stroke radius (half width).
We must be able to fully control the radius values when rendering brush strokes.

## Brush strokes
Expand All @@ -45,12 +44,12 @@ If you're unfamiliar with tablets and styluses, you can watch the video below fo

[![Tablet](https://img.youtube.com/vi/83BRMfjJXIk/maxresdefault.jpg)](https://www.youtube.com/watch?app=desktop&v=83BRMfjJXIk)

While you may recognize a brush stroke by its stylization, another crucial property could be ignored: the mutable (varying) radius along the stroke.
While you may recognize a brush stroke by its stylization, another crucial property could be ignored: the variable radius along the stroke.
(I ignored it in my paper too.)
The radii are typically generated from the pressure values as a stylus presses and moves on a tablet.
For experienced artists after installing a painting program, one of the highest priorities is to configure the mapping function from pen pressure to brush radius.

In this tutorial, you will learn to render a stroke with mutable radius, and the most popular way to stylize it called "Stamp."
In this tutorial, you will learn to render a stroke with variable radius, and the most popular way to stylize it called "Stamp."
More than 90 percent of brushes in popular paint software are the stamp brushes.
Additionally, GPU brush stroke rendering a newly emerged topic.
Researchers will develop more novel methods in the future.
Expand All @@ -59,27 +58,48 @@ Make sure to star our [code repository] for easy access to the latest updates.

## Vector curves

Mutable radius is imperative for the most artists working on digital painting,
but it's not defined in public vector standards like SVG.
Variable radius is imperative for the most artists working on digital painting,
but it's not included in public vector standards like [SVG](https://www.w3.org/Graphics/SVG/WG/wiki/Proposals/Variable_width_stroke).
And since that, configuring the variable width value of vector lines is commonly underdeveloped in popular graphics design software.
This limitation is one of the primary reasons that lots of digital artists don't use vector workflow.
(Another one is filling color.)

To support the mutable radius, we will render a unique type of vector curve:
To support the variable radius, we will render a unique type of vector curve:
An ordered list of points (polyline) with radius values assigned to each point.
As a stylus is pressed and moved on a tablet, the program generate a sequence of points to record the trace of movement.
Additionally, the pen pressure is transformed into the radius value assigned to each point.

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` value in the code editor below to see how the stroke changes.
Feel free to change any other parts of the code as long as the function return the `position` and `radius` array correctly.

import { ArticulatedLine2D } from "../../src/components/ArticulatedLine2D";

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

:::info code editor & canvas

The development environment is inspired by [_The Book of Shader_].
You can watch the rendering result in real time after modifying the code.

When hovering your mouse on the canvas you can:

- **Pan**: Left-click and drag the mouse.
- **Zoom**: Scroll or drag the mouse wheel.

If there are bugs for common usages, tell me in the [issue](https://github.com/ShenCiao/brush-stroke-tutorial/issues) page.

:::

## Structure

Although the algorithms are very straightforward, I know how hard it could be to learn and replicate a research work.
That's why I created this tutorial, designed with a smooth learning curve and providing seamless coding environments.
That's why I created this tutorial, designed with a smooth learning curve and providing the seamless development environment.

You should start with the Basic part, which covers the basics of the rendering methods.
Remember to read the articles in the Basic part in its original order, or you may miss something important.
Next, select your favorite topics to learn.
I will list the extra prerequisites at the very beginning of each article.
I will list extra prerequisites at the very beginning of each article.

Wish you happy learning!

Expand All @@ -106,14 +126,15 @@ Wish you happy learning!

:::note Research Tip

To demonstrate your research work about brush rendering, select vector drawings have mutable radius or pen pressure data.
To demonstrate your research work about brush rendering, select vector drawings have variable radius or pen pressure data.
Regular vector drawing datasets don't contain them.

- Zeyu Wang's work: [Paper](https://dl.acm.org/doi/10.1145/3450626.3459819) | [Dataset](https://github.com/zachzeyuwang/tracing-vs-freehand)
- [Blender Grease Pencil](https://cloud.blender.org/p/gallery/5b642e25bf419c1042056fc6)
- Tell me more...
- ... Tell me more in the [discussion](https://github.com/ShenCiao/brush-stroke-tutorial/discussions/1).

:::

[code repository]: https://github.com/ShenCiao/BrushStrokeTutorial
[Ciallo]: https://github.com/ShenCiao/Ciallo
[_The Book of Shader_]: https://thebookofshaders.com/
32 changes: 32 additions & 0 deletions docs/Tessellation/Tessellation.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
---
sidebar_position: 4
sidebar_label: Tessellation
title: Tessellation-based Rendering
---

There were works trying to tessellate a stroke and render it with GPU.
You can find them in several papers and online articles.

<details>
<summary>Paper and article list</summary>

- [Polar Stroking: New Theory and Methods for Stroking Paths](https://dl.acm.org/doi/abs/10.1145/3386569.3392458) (Very Hard)
- [Drawing Lines is Hard](https://mattdesl.svbtle.com/drawing-lines-is-hard)
- Instanced Line Rendering: [part1](https://wwwtyro.net/2019/11/18/instanced-lines.html) | [part2](https://wwwtyro.net/2021/10/01/instanced-lines-part-2.html)
- ... Tell me more tutorials in the [discussion](https://github.com/ShenCiao/brush-stroke-tutorial/discussions/2)

</details>

To begin with, I would recommend Rye Terrell's [Instanced Line Rendering](https://wwwtyro.net/2019/11/18/instanced-lines.html) to learn
several simple tessellation methods.
They may inspire some approaches to optimize the performance of the articulated algorithms.

In this article, I will compare the tessellation-based algorithms with articulated algorithms in detail.

_TODO_

:::note spoiler

The key benefit of the articulated is its self-overlapping in acute angle, which is critical for brush strokes and digital painting.

:::
59 changes: 46 additions & 13 deletions docs/toc.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -5,43 +5,76 @@ sidebar_position: 1
slug: /
---

This tutorial will teach you how to render brush strokes with the modern GPU graphics pipeline.
import {
ArticulatedLine2D,
pencilBrushUniforms,
airBrushUniforms,
dotBrushUniforms,
} from "../src/components/ArticulatedLine2D";

If you like this tutorial, please star the [code repository] instead of bookmark the website since the domain might be changed.
<div className="row row--no-gutters margin-left--xs">
<div className="col col--6">
<ArticulatedLine2D />
<center>
<em> Vanilla </em>
</center>
</div>
<div className="col col--6">
<ArticulatedLine2D uniforms={pencilBrushUniforms} />
<center>
<em> Pencil </em>
</center>
</div>
</div>

<p></p>

This tutorial series will teach you how to render brush strokes with the modern GPU graphics pipeline.
If you like it, please star the [code repository] instead of bookmark this website since the domain might be changed.

## Table of Contents

- [Introduction](./introduction)
- Basics
- [Vanilla](./Basics/Vanilla)
- Vanilla with mutable radius
- Vanilla with variable radius
- Stamp
- Stamp with mutable radius 1
- Stamp with mutable radius 2
- Stamp with variable radius 1
- Stamp with variable radius 2
- An interleave

## Future Contents

### Airbrush

<ArticulatedLine2D uniforms={airBrushUniforms} />

Airbrush is a special type of stamp brush.
Learn the mathematical derivation from discrete to continuous stamp to get a "continuous airbrush".
Here I'm demonstrating a "continuous airbrush".
You will learn the mathematical derivation of stamp brush from discrete to continuous.

### Stamp density and "ratio-distance"

Control stamp density along the polyline and render a critical stamp placing pattern called ratio-distance.
Very important for a serious project.
<ArticulatedLine2D uniforms={dotBrushUniforms} />

You can see dots are adjacent to each other consecutively instead of equidistantly
distributed. The pattern is achieved by setting the intervals between dots to twice
of their radii. You will learn how to freely control stamp density along a stamp
stroke. Very important for a serious project.

### 3D stroke

Learn how to extend the algorithms to 3D space.

I'm integrating it into the Blender Grease Pencil:

<iframe width="100%" height="500" src="https://www.youtube.com/embed/Q7_3IhgHOZM?start=30"
title="Blender Grease Pencil Stamp Brush Demo"
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"
allowFullScreen>
</iframe>
<iframe
width="100%"
height="500"
src="https://www.youtube.com/embed/Q7_3IhgHOZM?start=30"
title="Blender Grease Pencil Stamp Brush Demo"
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"
allowFullScreen
></iframe>

[code repository]: https://github.com/ShenCiao/BrushStrokeTutorial
1 change: 1 addition & 0 deletions docusaurus.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ const config = {
themeConfig:
/** @type {import('@docusaurus/preset-classic').ThemeConfig} */
({
colorMode: {disableSwitch: true},
// Replace with your project's social card
image: 'img/vanilla-stroke.png',
navbar: {
Expand Down
Loading

0 comments on commit d0201fb

Please sign in to comment.