Merge branch 'master' into master

pull/352/head
Patricio Gonzalez Vivo 2 years ago committed by GitHub
commit 44f39fe26d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -22,7 +22,7 @@ Au fil des chapitres, vous découvrirez à quel point les shaders sont efficaces
## A qui s'adresse ce livre ?
Ce livre est écrit pour les *creative coders*, les développeurs de jeux, les ingénieurs et les curieux ayant une expérience evec le code, des connaissances basiques en algèbre linéaire et en trigonométrie et désireux d'améliorer la qualité graphique de leurs productions.
Ce livre est écrit pour les *creative coders*, les développeurs de jeux, les ingénieurs et les curieux ayant une expérience avec le code, des connaissances basiques en algèbre linéaire et en trigonométrie et désireux d'améliorer la qualité graphique de leurs productions.
Si vous n'avez aucune connaissance en programmation, nous vous recommandons vivement de commencer par apprendre le langage [Processing](https://processing.org/) puis de revenir à ce livre lorsque vous vous sentirez plus à l'aise.
Ce livre vous montrera comment utiliser et intégrer des shaders dans vos projets, comment améliorer leurs performances et leur rendu graphique.

@ -12,7 +12,7 @@ Fragment shader cho bạn toàn quyền kiểm soát các điểm ảnh được
![Game Journey của That Game Company](journey.jpg)
Ở các chương tiếp theo, bạn sẽ biết kỹ thuật này nhanh và mạnh kinh khủng tới mức nào, và làm thế nào để áp dụng nó vào công việc.
Ở các chương tiếp theo, bạn sẽ khám phá ra kỹ thuật này nhanh và mạnh kinh khủng tới mức nào, và làm thế nào để áp dụng nó vào công việc.
## Quyển sách này dành cho những ai ?
@ -23,8 +23,7 @@ Quyển sách này sẽ chỉ cho bạn cách dùng các shader và cách áp d
## Nội dung của quyển sách này là gì ?
Quyển sách này sẽ tập trung vào việc sử dụng các pixel shader viết bằng GLSL. Đầu tiên ta sẽ định nghĩa thế nào là shader, rồi mới học cách tạo các hình, mẫu, ảnh bằng Toán học và làm chúng chuyển động bằng shader. Bạn sẽ được học các kiến thức nền tảng của shader và áp dụng chúng vào các chuyên ngành khác như: Xử lý ảnh
(Các phép toán xử lý ảnh, ma trận chập, làm mờ, bộ lọc, bảng quy chiếu và các hiệu ứng khác), mô phỏng (
Mô phỏng tiến trình sống theo phương pháp Conway, mô hình Phản ứng - Khuếch tán của Gray-Scott, các gợn sóng trên mặt nước, hiệu ứng màu nước, nhiễu Voronoi, vân vân ...). Tới cuối quyển sách, ta sẽ nói về các kỹ thuật cao cấp hơn dựa trên thuật toán Dò tia - Ray Marching.
(Các phép toán xử lý ảnh, ma trận chập, làm mờ, bộ lọc, bảng quy chiếu và các hiệu ứng khác), mô phỏng (Mô phỏng tiến trình sống theo phương pháp Conway, mô hình Phản ứng - Khuếch tán của Gray-Scott, các gợn sóng trên mặt nước, hiệu ứng màu nước, nhiễu Voronoi, vân vân ...). Tới cuối quyển sách, ta sẽ nói về các kỹ thuật cao cấp hơn dựa trên thuật toán Dò tia - Ray Marching.
*Tất cả các chương đều có các ví dụ tương tác được để bạn khám phá.* Khi bạn sửa code, bạn sẽ thấy thay đổi ngay lập tức. Các khái niệm có thể hơi trừu tượng và dễ gây nhầm lẫn, nên các ví dụ tương tác được sẽ rất cần thiết để hỗ trợ bạn học. Bạn nắm vững các khái niệm càng nhanh thì bạn học càng dễ.

@ -41,7 +41,7 @@ GLSL 代表 openGL Shading LanguageopenGL 着色语言,这是你在接下
就像蜘蛛侠里的那句名言能力越大责任越大并行计算也是如此GPU 的强大的架构设计也有其限制与不足。
为了能使许多管线并行运行,每一个线程必须与其他的相独立。我们称这些线程对于其他线程在进行的运算是“盲视”的。这个限制就会使得所有数据必须以相同的方向流动。所以就不可能检查其他线程的输出结果,修改输入的数据,或者把一个线程的输出结果输入给另一个线程。如果允许线程到线程的数据流动将使所有的数据面临威胁。
为了能使许多管线并行运行,每一个线程必须与其他的相独立。我们称这些线程对于其他线程在进行的运算是“盲视”的。这个限制就会使得所有数据必须以相同的方向流动。所以就不可能检查其他线程的输出结果,修改输入的数据,或者把一个线程的输出结果输入给另一个线程。允许数据在线程之间线程流动会使数据的整体性面临威胁。
并且 GPU 会让所有并行的微处理器(管道们)一直处在忙碌状态;只要它们一有空闲就会接到新的信息。一个线程不可能知道它前一刻在做什么。它可能是在画操作系统界面上的一个按钮,然后渲染了游戏中的一部分天空,然后显示了一封 email 中的一些文字。每个线程不仅是“盲视”的,而且还是“无记忆”的。同时,它要求编写一个通用的规则,依据像素的不同位置依次输出不同的结果。这种抽象性,和盲视、无记忆的限制使得 shaders 在程序员新手中不是很受欢迎。

@ -49,7 +49,7 @@ Comme dit *Uncle Ben* dans Spiderman: "with great power comes great responsibili
Pour fonctionner en parallèle, il faut que chaque thread soit indépendant des autres. On dit que le thread est *aveugle* à ce que font les autres threads. Cette restriction implique que toutes les données doivent aller dans le même sens. Il est donc impossible de vérifier le résultat dun autre thread, de modifier les données dentrée ou de transmettre le résultat dun thread à un autre. Autoriser la communication entre threads au moment de l'exécution pourrait compromettre l'intégrité des données en cours de traitement.
Il faut également savoir que le GPU s'assure que tous ses microprocesseurs (les tuyaux) sont actifs en permanence; dès qu'un thread a fini son traitement, le GPU lui ré-assigne une opération à traiter. Le thread ne garde aucune trace de ce qu'il faisait la fois précédente. s'il était en train de dessiner un le pixel d'un bouton sur une interface graphique, sa tâche suivante pourra être de rendre un bout du ciel dans un jeu, puis de rendre un bout de texte sur un mail. Donc un thread est non seulement **aveugle** mais aussi **amnésique**. En plus du niveau d'abstraction requis pour coder une fonction générique qui saura rendre une image entière uniquement à partir de la variation d'une position, les deux contraintes des threads, cécité et amnésie, rendent la programmation de shaders assez impopulaire auprès des programmeurs débutants.
Il faut également savoir que le GPU s'assure que tous ses microprocesseurs (les tuyaux) sont actifs en permanence; dès qu'un thread a fini son traitement, le GPU lui ré-assigne une opération à traiter. Le thread ne garde aucune trace de ce qu'il faisait la fois précédente. S'il était en train de dessiner le pixel d'un bouton sur une interface graphique, sa tâche suivante pourra être de rendre un bout du ciel dans un jeu, puis de rendre un bout de texte sur un mail. Donc un thread est non seulement **aveugle** mais aussi **amnésique**. En plus du niveau d'abstraction requis pour coder une fonction générique qui saura rendre une image entière uniquement à partir de la variation d'une position, les deux contraintes des threads, cécité et amnésie, rendent la programmation de shaders assez impopulaire auprès des programmeurs débutants.
Mais n'ayez crainte ! Au cours des chapitres suivants, nous aborderons les problèmes étape par étape et passerons d'un simple shader à des shaders plus avancés. Si vous lisez ceci dans un navigateur récent, vous apprécierez de pouvoir manipuler les exemples interactifs et beaucoup de ce qui vient d'être dit deviendra plus clair. Sans plus attendre, jetons nous dans le vif du sujet.

@ -1,7 +1,7 @@
# Mở đầu
## Fragment shader là gì
## Fragment shader là gì?
Ở chương trước, tôi đã mô tả shader tương đương với cỗ máy in của Gutenberg nhưng cho ngành đồ hoạ. Tại sao ? Và quan trọng hơn: shader là gì ?
Ở chương trước, tôi đã mô tả shader tương đương với cỗ máy in của Gutenberg nhưng cho ngành đồ hoạ. Tại sao? Và quan trọng hơn: shader là gì?
![Từ việc chép-từng-từ-một, Ảnh bên trái của William Blades (1891). Cho tới in-từng-trang-một, Ảnh bên phải của Rolt-Wheeler (1920).](print.png)
@ -11,7 +11,7 @@ Shader cũng là một tập hợp các chỉ dẫn, nhưng các chỉ dẫn đ
![Các khuôn chữ Trung Quốc](typepress.jpg)
## Làm cách nào shader lại chạy nhanh tới vậy ?
## Làm cách nào shader lại chạy nhanh tới vậy?
Để trả lời câu hỏi này, tôi xin giới thiệu với bạn sự kỳ diệu của việc *xử lý song song*.
@ -21,7 +21,7 @@ Hãy tưởng tượng CPU là một dây chuyền công nghiệp lớn, và m
Các trò chơi điện tử và các ứng dụng đồ hoạ cần nhiều năng lực xử lý hơn hẳn các phần mềm khác. Vì các nội dung đồ hoạ của chúng yêu cầu thực hiện rất nhiều phép toán, cho từng điểm ảnh một. Mỗi điểm ảnh trên màn hình đều phải được tính đến, còn trong các trò chơi 3 chiều thì cả các vật thể lẫn các góc camera cũng phải được tính luôn.
Quay trở lại phép so sánh về dây chuyền và tác vụ. Mỗi điểm ảnh trên màn hình đại diện cho 1 tác vụ nhỏ. Bản thân từng tác vụ không phải là vấn đề lớn với CPU, nhưng (vấn đề ở đây là) các tác vụ bé xíu này lại phải được thực thi cho từng điểm ảnh trên cả màn hình. Có nghĩa là trên màn hình cũ có độ phân giải 800x600, có tới 480.000 điểm ảnh cần phải được xử lý mỗi khung hình, tương đương với 14.400.000 phép tính mỗi giây! Đúng thế! Đó chính là điều khiến bộ vi xử lý bị quá tải. Còn ở màn hình retina thời hiện đại có độ phân giải 2880x1800 hiển thị 60 khung hình một giây, thì số phép tính mỗi giây lên tới 311.040.000. Bằng cách nào mà các kỹ sư đồ hoạ giải quyết được vấn đề này ?
Quay trở lại phép so sánh về dây chuyền và tác vụ. Mỗi điểm ảnh trên màn hình đại diện cho 1 tác vụ nhỏ. Bản thân từng tác vụ không phải là vấn đề lớn với CPU, nhưng (vấn đề ở đây là) các tác vụ bé xíu này lại phải được thực thi cho từng điểm ảnh trên cả màn hình. Có nghĩa là trên màn hình cũ có độ phân giải 800x600, có tới 480.000 điểm ảnh cần phải được xử lý mỗi khung hình, tương đương với 14.400.000 phép tính mỗi giây! Đúng thế! Đó chính là điều khiến bộ vi xử lý bị quá tải. Còn ở màn hình retina thời hiện đại có độ phân giải 2880x1800 hiển thị 60 khung hình một giây, thì số phép tính mỗi giây lên tới 311.040.000. Bằng cách nào mà các kỹ sư đồ hoạ giải quyết được vấn đề này?
![](03.jpeg)
@ -29,21 +29,21 @@ Quay trở lại phép so sánh về dây chuyền và tác vụ. Mỗi điểm
![GPU](04.jpeg)
Hình dung hàng loạt các bộ vi xử lý tí hon như các dây chuyền được xếp thành hàng hình chữ nhật, còn dữ liệu của mỗi điểm ảnh là một quả bóng bàn. Nhét 14.400.000 quả bóng bàn trong một giây vào một ống đơn lẻ sẽ rất khó. Nhưng một nhóm nhiều ống xếp thành hàng 800x600 thì có thể đưa 480.000 quả bóng bàn chui qua tới 30 lần một giây một cách dễ dàng. Độ phân giải cao hơn cũng tương tự - phần cứng càng có năng lực xử lý song song thì khối lượng công việc mà nó có thể giải quyết lại lớn hơn.
Hình dung các bộ vi xử lý tí hon là hàng loạt những ống xếp dọc và kết lại với nhau thành một cái bàn, còn dữ liệu của mỗi điểm ảnh là một quả bóng bàn. Nhét 14.400.000 quả bóng bàn vào một ống đơn lẻ trong một giây sẽ rất khó. Nhưng khi rất nhiều ống xếp thành hàng 800x600 thì có thể đưa 480.000 quả bóng bàn chui qua tới 30 lần một giây một cách dễ dàng. Độ phân giải cao hơn cũng tương tự - phần cứng càng có năng lực xử lý song song thì khối lượng công việc mà nó có thể giải quyết lại lớn hơn.
Một "siêu năng lực" khác của GPU là các hàm Toán học được tối ưu bằng phần cứng, nên các phép toán phức tạp sẽ được xử lý trực tiếp trên phần cứng thay vì phần mềm. Điều đó có nghĩa là các phép tính lượng giác và ma trận sẽ được tính cực kỳ nhanh - như điện luôn.
## GLSL là gì?
GLSL là viết tắt của OpenGL Shading Language, là một quy chuẩn để viết các shader mà ta sẽ dùng ở các chương tới. Có nhiều loại shader phụ thuộc vào phần cứng và hệ điều hành. Ở đây chúng ta sẽ sử dụng quy chuẩn của
[Khronos Group](https://www.khronos.org/opengl/). Hiểu về lịch sử hình thành của OpenGL sẽ giúp ích trong việc vượt qua được một số rào cản kỳ lạ của nó, vì thế tôi giới thiệu quyển sách này: [OpenGL là ](http://openglbook.com/chapter-0-preface-what-is-opengl.html)
[Khronos Group](https://www.khronos.org/opengl/). Hiểu về lịch sử hình thành của OpenGL sẽ giúp ích trong việc vượt qua được một số rào cản kỳ lạ của nó, vì thế tôi khuyên bạn nên xem qua: [openglbook.com/chapter-0-preface-what-is-opengl.html](http://openglbook.com/chapter-0-preface-what-is-opengl.html)
## Shader nổi tiếng khó nhằn, sao lại thế ?
## Shader nổi tiếng khó nhằn, sao lại thế?
Như chú Ben nói "Quyền lực càng cao, trách nhiệm càng lớn", và việc tính toán song song cũng tuân thủ quy tắc này; thiết kế kiến trúc rất mạnh mẽ của GPU cũng đi kèm với các ràng buộc và giới hạn.
Như chú Ben (một nhân vật trong phim Spider Man) nói "Quyền lực càng cao, trách nhiệm càng lớn", và việc tính toán song song cũng tuân thủ quy tắc này; thiết kế kiến trúc rất mạnh mẽ của GPU cũng đi kèm với các ràng buộc và giới hạn.
Để các dây chuyền, tức các thread, có thể chạy song song, thì chúng phải độc lập. Có thể nói rằng các thread bị **mù** khi không thể biết được các thread khác đang làm gì. Giới hạn này dẫn tới việc toàn bộ dữ liệu phải đi theo 1 chiều. Nên thread này không thể biết kết quả của thread kia hay thay đổi dữ liệu đầu vào hoặc lấy dữ liệu đầu ra của một thread nọ để chuyển cho một thread khác nữa.
Để các dây chuyền, tức các thread, có thể chạy song song, thì chúng phải độc lập. Có thể nói rằng các thread bị **mù** khi không thể biết được các thread khác đang làm gì. Giới hạn này dẫn tới việc toàn bộ dữ liệu phải đi theo 1 chiều. Nên thread này không thể biết kết quả của thread kia hay thay đổi dữ liệu đầu vào hoặc lấy dữ liệu đầu ra của một thread nọ để chuyển cho một thread khác nữa. Việc cho phép các thread liên thông với nhau (thread-to-thread) sẽ gây rủi ro cho tính toàn vẹn của dữ liệu.
Và GPU cũng luôn khiến cho các bộ vi xử lý (các dây chuyền) của mình phải bận rộn; cứ dây chuyền nào xong việc thì sẽ nhận được thông tin mới để xử lý tiếp. Nên mỗi thread còn chẳng biết nó vừa hoàn thành xong việc gì. Nó có thể vừa mới vẽ xong 1 nút bấm trên giao diện của hệ điều hành, rồi vẽ một phần bầu trời trong 1 trò chơi nào đó, sau đó lại phải hiển thị nội dung của 1 cái email. Mỗi thread không chỉ bị **mù** mà còn **mất trí nhớ** nữa. Bên cạnh việc viết code shader khá trừu tượng do phải viết một hàm dùng chung cho mọi điểm ảnh nhưng kết quả thì phụ thuộc vào vị trí của điểm ảnh đó, thì các ràng buộc về việc bị mù và mất trí nhớ ở trên cũng là nguyên do khiến cho shader không được biết đền nhiều bởi các lập trình viên mới vào nghề.
Nhưng đừng lo! Ở các chương tới, ta sẽ học từng bước một, từ đơn giản tới phức tạp. Nếu bạn đang đọc trên một trình duyệt đời mới, bạn có thể sẽ thích tương tác với các ví dụ. Đừng trì hoãn sự sung sướng nữa mà hãy click nút *Next >>* để nhảy thẳng vào code nào!
Nhưng đừng lo! Ở các chương tới, ta sẽ học từng bước một, từ đơn giản tới phức tạp. Nếu bạn đang đọc trên một trình duyệt đời mới, bạn có thể sẽ thích tương tác với các ví dụ. Đừng trì hoãn sự sung sướng nữa mà hãy click nút *Next >>* để nhảy thẳng vào code nào!

@ -18,7 +18,7 @@
4. 如果我们仔细观察 ```vec4``` 类型,可以推测这四个变元分别响应红,绿,蓝和透明度通道。同时我们也可以看到这些变量是**规范化**的意思是它们的值是从0到1的。之后我们会学习如何规范化变量使得在变量间**map**(映射)数值更加容易。
5. 另一个可以从本例看出来的很重要的类 C 语言特征是,预处理程序的宏指令。宏指令是预编译的一部分。有了宏才可以 ```#define``` (定义)全局变量和进行一些基础的条件运算(通过使用 ```#ifdef``` 和 ```#endif```)。所有的宏都以 ```#``` 开头。预编译会在编译前一刻发生,把所有的命令复制到 ```#defines``` 里,检查```#ifdef``` 条件句是否已被定义, ```#ifndef``` 条件句是否没有被定义。在我们刚刚的“hello world!”的例子中,我们在第2行检查了 ```GL_ES``` 是否被定义,这个通常用在移动端或浏览器的编译中。
5. 另一个可以从本例看出来的很重要的类 C 语言特征是,预处理程序的宏指令。宏指令是预编译的一部分。有了宏才可以 ```#define``` (定义)全局变量和进行一些基础的条件运算(通过使用 ```#ifdef``` 和 ```#endif```)。所有的宏都以 ```#``` 开头。预编译会在编译前一刻发生,把所有的命令复制到 ```#defines``` 里,检查```#ifdef``` 条件句是否已被定义, ```#ifndef``` 条件句是否没有被定义。在我们刚刚的“hello world!”的例子中,如果定义了```GL_ES```这个变量才会插入运行第2行的代码,这个通常用在移动端或浏览器的编译中。
6. ```float```类型在 shaders 中非常重要,所以**精度**非常重要。更低的精度会有更快的渲染速度,但是会以质量为代价。你可以选择每一个浮点值的精度。在第一行(```precision mediump float;```)我们就是设定了所有的浮点值都是中等精度。但我们也可以选择把这个值设为“低”(```precision lowp float;```)或者“高”(```precision highp float;```)。

@ -45,7 +45,7 @@ Vous remarquerez que le programme ne se recompilera pas tant qu'il restera des e
* Essayez de commenter (`//`) la ligne 8, ce qui n'assignera aucune valeur au pixel.
* Essayez de créer une fonction qui retourne une couleur en dehors de `main()` et essayez de l'utiliser pour assigner la valeur de `gl_FragColor` dans `main()`. Pour vous aider, voici le code d'une fonction qui une couleur rouge :
* Essayez de créer une fonction qui retourne une couleur en dehors de `main()` et essayez de l'utiliser pour assigner la valeur de `gl_FragColor` dans `main()`. Pour vous aider, voici le code d'une fonction qui retourne une couleur rouge :
```glsl
vec4 red() {
@ -53,7 +53,7 @@ vec4 red() {
}
```
* On peut construire un `vec4` de plusieurs façons, essayez de découvrir d'autres manières'. Par exemple:
* On peut construire un `vec4` de plusieurs façons, essayez de découvrir d'autres manières. Par exemple:
```glsl
vec4 color = vec4(vec3(1.0,0.0,1.0),1.0);

@ -2,7 +2,7 @@
Thông thường thì ví dụ "Hello World!" sẽ là bước đầu tiên khi học một ngôn ngữ lập trình mới. Đó là một chương trình đơn giản, in ra 1 dòng chữ chào đón.
Ở địa-bàn-của-GPU thì việc vẽ các ký tự chữ số là bước khởi đầu có phần quá phức tạp, thay vào đó chúng tôi chọn sẽ tô một màu tươi sáng lên màn hình để chào đón các bạn nồng nhiệt nhất!
Ở địa-bàn-của-GPU thì việc vẽ các ký tự chữ số là bước khởi đầu có phần quá phức tạp, thay vào đó chúng tôi chọn sẽ tô một màu tươi sáng lên màn hình để chào đón các bạn một cách nồng nhiệt nhất!
<div class="codeAndCanvas" data="hello_world.frag"></div>

@ -50,12 +50,12 @@ Trong shader ta không có nhiều cách để debug lắm bên cạnh việc th
Giờ là lúc để thử xem ta hiểu code tới đâu.
* Bạn có biết toạ độ `(0.0, 0.0)` nằm ở đâu trên canvas không ?
* Bạn có biết toạ độ `(0.0, 0.0)` nằm ở đâu trên canvas không?
* Vậy còn `(1.0, 0.0)`, `(0.0, 1.0)`, `(0.5, 0.5)``(1.0, 1.0)`?
* Hãy tìm cách lấy màu tại vị trí con trỏ chuột khi được click và di chuyển nó đi bất kỳ chỗ nào con trỏ chuột đang ở
* Bạn có thể sử dụng `u_mouse` để lấy giá trị điểm ảnh CHƯA chuẩn hoá *(normalize)*? Bạn có thể dùng nó để thay đổi màu khi di chuyển con trỏ chuột?
* Bạn có tưởng tượng được cách nào để tạo ra các mảng màu hay ho bằng cách sử dụng `u_time``u_mouse` không ?
* Bạn có tưởng tượng được cách nào để tạo ra các mảng màu hay ho bằng cách sử dụng `u_time``u_mouse` không?
Sau khi làm các bài tập này, bạn có thể sẽ thắc mắc mình có thể sử dụng năng-lực-shader mới này của mình ở đâu nữa. Ở chương tới ta sẽ xem làm thế nào để tạo shader bằng three.js, Processing, và openFrameworks.

@ -1,10 +1,42 @@
## 运行你的 shader
现在你可能跃跃欲试,想在你熟悉的平台上小试牛刀了。接下来会有一些比较流行的平台的示例代码,展示如何在这些平台上配置 shader。在这个 [github 仓库](https://github.com/patriciogonzalezvivo/thebookofshaders/tree/master/04) 中有本章的三种平台的示例代码)
我制作了一套工具生态系统,用于创建、显示、分享与使用 shader以此作为本书结构及我艺术实践的一部分。这些工具是跨平台的无需更改代码就能在 Linux、MacOS、Windows、[树莓派](https://www.raspberrypi.org/) 和浏览器上表现一致。
**注释 1**:如果你不想用这些平台来运行 shader且你想在浏览器外使用 shader你可以下载[glslViewer](https://github.com/patriciogonzalezvivo/glslViewer)。这个 MacOS+树莓派程序直接在终端运行,并且是为本书的例子量身打造的。
## 在浏览器上运行你的 shader
**注释2**:如果你想用 WebGL 显示 shader并不关心其他平台你可以用[glslCanvas](https://github.com/patriciogonzalezvivo/glslCanvas) 。这个 web 工具本来是为本书设计的,但是太好用了,所以我常常用在其他项目中。
**显示**: 本书中所有实例都可以用 [glslCanvas](https://github.com/patriciogonzalezvivo/glslCanvas) 来显示,这样一来,运行独立的 shader 程序就变得非常简单.
```html
<canvas class="glslCanvas" data-fragment-url=“yourShader.frag" data-textures=“yourInputImage.png” width="500" height="500"></canvas>
```
如你所见, 只需要创建一个类名为 `class="glslCanvas"``canvas` 元素,并将你的 shader 链接放在 `data-fragment-url` 中. 在 [这里](https://github.com/patriciogonzalezvivo/glslCanvas) 可以了解更多.
你可能会像我一样想要从命令行直接运行 shader那你需要看看 [glslViewer](https://github.com/patriciogonzalezvivo/glslViewer)。这个应用程序可以将 shader 放到 `bash` 脚本或 unix 管道里,并且像 [ImageMagick](http://www.imagemagick.org/script/index.php) 一样使用它。此外,[glslViewer](https://github.com/patriciogonzalezvivo/glslViewer) 也是一个在 [树莓派](https://www.raspberrypi.org/) 上编译 shader 的好办法, 这就是 [openFrame.io](http://openframe.io/) 用它来展示shader 作品的原因。在 [这里](https://github.com/patriciogonzalezvivo/glslViewer) 可以了解该应用程序的更多信息。
```bash
glslViewer yourShader.frag yourInputImage.png —w 500 -h 500 -s 1 -o yourOutputImage.png
```
**创建**: 为了介绍 shader 编码的经验,我制作了在线编辑器 [glslEditor](https://github.com/patriciogonzalezvivo/glslEditor)。本书的实例中内嵌了这个编辑器。这个编辑器有很多好用的小组件,使编写 glsl 代码的体验更加直观。你也可以在 [editor.thebookofshaders.com/](http://editor.thebookofshaders.com/) 上将其作为独立的 Web 应用运行。在 [这里](https://github.com/patriciogonzalezvivo/glslEditor) 了解更多。
![](glslEditor-01.gif)
如果你更喜欢用 [SublimeText](https://www.sublimetext.com/) 离线编程,你可以安装 [package for glslViewer](https://packagecontrol.io/packages/glslViewer)。 在 [这里](https://github.com/patriciogonzalezvivo/sublime-glslViewer) 了解更多.
![](glslViewer.gif)
**分享**: 在线编辑器 ([editor.thebookofshaders.com/](http://editor.thebookofshaders.com/)) 可以分享你的 shader内嵌版和独立版都有导出按钮你可以通过这个按钮获得 shader 的唯一链接。编辑器也可以直接将 shader 导出到 [openFrame.io](http://openframe.io/)。
![](glslEditor-00.gif)
**使用**: 分享代码只是分享 shader 作品的开始!除了导出到 [openFrame.io](http://openframe.io/),我还制作了使用 shader 的工具 [glslGallery](https://github.com/patriciogonzalezvivo/glslGallery),它可以将 shader 放入画廊中,以便嵌入到任何网站. 在 [这里](https://github.com/patriciogonzalezvivo/glslGallery) 了解更多.
![](glslGallery.gif)
## 在你喜欢的框架上运行你的 shader
如果你使用过这些这些框架: [Processing](https://processing.org/), [Three.js](http://threejs.org/), [OpenFrameworks](http://openframeworks.cc/) 或 [SFML](https://www.sfml-dev.org/), 你可能更愿意在你觉得舒服的这些平台上编写 shader。下面将会介绍在这些框架中用本书范式编写 shader 的方法。 (在 [本章节的 GitHub 仓库中](https://github.com/patriciogonzalezvivo/thebookofshaders/tree/master/04), 你能找到这三个框架的完整源码.)
### **Three.js**

@ -34,7 +34,7 @@ Wenn Du lieber offline statt online mit [SublimeText](https://www.sublimetext.co
## Ausführen von Shadern in Deiner bevorzugten Umgebung
Falls Du bereits Erfahrung mit der Programmierung in einer Umgebung wie [Processing](https://processing.org/), [three.js](http://threejs.org/) oder [OpenFrameworks](http://openframeworks.cc/) gesammelt hast, möchtest Du Deine Shader vielleicht in dieser Umgebung ausführen lassen. Die folgenden Codebeispiele zeigen Dir, wie man Shader unter Verwendung der gleichen Uniforms, die wir in diesem Buch verwenden, in diesen Umgebungen ausführen kann. (In der [GitHub-Ablage dieses Kapitels](https://github.com/patriciogonzalezvivo/thebookofshaders/tree/master/04) findest Du den gesamten Sourcecode für die Einbindung von Shadern unter den drei genannten Umgebungen.)
Falls Du bereits Erfahrung mit der Programmierung in einer Umgebung wie [Processing](https://processing.org/), [three.js](http://threejs.org/), [OpenFrameworks](http://openframeworks.cc/) oder [SFML](https://www.sfml-dev.org/) gesammelt hast, möchtest Du Deine Shader vielleicht in dieser Umgebung ausführen lassen. Die folgenden Codebeispiele zeigen Dir, wie man Shader unter Verwendung der gleichen Uniforms, die wir in diesem Buch verwenden, in diesen Umgebungen ausführen kann. (In der [GitHub-Ablage dieses Kapitels](https://github.com/patriciogonzalezvivo/thebookofshaders/tree/master/04) findest Du den gesamten Sourcecode für die Einbindung von Shadern unter den drei genannten Umgebungen.)
### Ausführung unter **three.js**

@ -15,7 +15,7 @@
اگر مثل من هستنید و دوست دارید مستیقا شیدر هارا را روی کنسول اجرا کنید, در اینضورت باید یک نگاهی به [glslViewer](https://github.com/patriciogonzalezvivo/glslViewer) بیاندازید. این برنامه این امکان را به شما می‌دهد که شیدر ها را در روی bash یا unix pipelines به روش مشابه [ImageMagick](http://www.imagemagick.org/script/index.php) استفاده کنید. همچنین [glslViewer](https://github.com/patriciogonzalezvivo/glslViewer) یک روش خوب برای کامپایل شیدر روی [Raspberry Pi](https://www.raspberrypi.org/) است, به همین علت [openFrame.io](http://openframe.io/) از آن برای نمایش شیدر ها استفاده می‌کند. درمورد این نرم افزار بیشتر بدانید در [اینجا](https://github.com/patriciogonzalezvivo/glslViewer).
```bash
glslViewer yourShader.frag yourInputImage.png —w 500 -h 500 -s 1 -o yourOutputImage.png
glslViewer yourShader.frag yourInputImage.png —w 500 -h 500 -E screenshot,yourOutputImage.png
```
**ساخت**: برای تجربه برنامه نویسی شیدر ها، من یک ویرایشگر آنلاین [glslEditor](https://github.com/patriciogonzalezvivo/glslEditor) ساختم. این ویرایشگر در مثال های این کتاب هم تعبیه شده است, این مجموعه ابزارک های مفیدی را هم فراهم می‌کند تا تجربه کار با کد glsl را ملموس تر کند. همچنین آن را بعنوان یک برنامه وب مستقل هم می‌توانید در [editor.thebookofshaders.com/](http://editor.thebookofshaders.com/) استفاده کنید. اطلاعات بیشتر در [اینجا](https://github.com/patriciogonzalezvivo/glslEditor).
@ -35,7 +35,7 @@ glslViewer yourShader.frag yourInputImage.png —w 500 -h 500 -s 1 -o yourOutput
![](glslGallery.gif)
## اجرا کردن شیدر هایتان در فریمورک ها دلخواهتان
اگر تجربه کار با فریمورک هایی مثل: [Processing](https://processing.org/), [Three.js](http://threejs.org/) یا [OpenFrameworks](http://openframeworks.cc/) دارید, برای استفاده از آن ها برای شیدر نویسی هم هیجان زده خواهید شد. در ادامه نمونه هایی از چگونگی تنطیم فریمورک ها برای اجرای شیدر ها با همان چارچوب گفته شده در ان کتاب می‌پردازم. (در [GitHub repository for this chapter](https://github.com/patriciogonzalezvivo/thebookofshaders/tree/master/04) ,سورس کد کامل برای استفاده از این سه فریمورک را می‌یابید.)
اگر تجربه کار با فریمورک هایی مثل: [Processing](https://processing.org/), [Three.js](http://threejs.org/),[OpenFrameworks](http://openframeworks.cc/) یا [SFML](https://www.sfml-dev.org/) دارید, برای استفاده از آن ها برای شیدر نویسی هم هیجان زده خواهید شد. در ادامه نمونه هایی از چگونگی تنطیم فریمورک ها برای اجرای شیدر ها با همان چارچوب گفته شده در ان کتاب می‌پردازم. (در [GitHub repository for this chapter](https://github.com/patriciogonzalezvivo/thebookofshaders/tree/master/04) ,سورس کد کامل برای استفاده از این سه فریمورک را می‌یابید.)
### در **Three.js**

@ -19,7 +19,7 @@ Cette application permet d'incorporer un shader dans un script `bash` ou un pipe
Pour en savoir plus, [cliquez ici](https://github.com/patriciogonzalezvivo/glslViewer).
```bash
glslViewer yourShader.frag yourInputImage.png —w 500 -h 500 -s 1 -o yourOutputImage.png
glslViewer yourShader.frag yourInputImage.png —w 500 -h 500 -E screenshot,yourOutputImage.png
```
**Création** : pour améliorer l'expérience de programmation des shaders, j'ai créé un éditeur disponible ici : [glslEditor](https://github.com/patriciogonzalezvivo/glslEditor).
@ -48,7 +48,7 @@ Il s'appelle [glslGallery](https://github.com/patriciogonzalezvivo/glslGallery),
## Lancer vos shaders depuis votre plateforme favorite
Si vous avez déjà programmé à l'aide de frameworks/APIs comme : [Processing](https://processing.org/), [Three.js](http://threejs.org/) ou [OpenFrameworks](http://openframeworks.cc/),
Si vous avez déjà programmé à l'aide de frameworks/APIs comme : [Processing](https://processing.org/), [Three.js](http://threejs.org/), [OpenFrameworks](http://openframeworks.cc/) ou [SFML](https://www.sfml-dev.org/),
vous êtes sans doute impatients de tester vos shaders dans ces environnements.
Les exemples suivants montrent comment intégrer les shaders sur ces plateformes en conservant les conventions de nommage que nous utiliserons dans ce livre.
Vous retrouverez le code source complet sur le [dépôt GitHub de ce chapitre](https://github.com/patriciogonzalezvivo/thebookofshaders/tree/master/04).

@ -14,7 +14,7 @@ Seperti yang dapat anda lihat, hanya membutuhkan elemen `kanvas` dengan `class="
Jika anda seperti saya, anda mungkin akan menjalankan shader langsung dari kosol, dalam kasus tersebut anda harus melihat [glslViewer](https://github.com/patriciogonzalezvivo/glslViewer). Aplikasi ini memperbolehkan anda untuk menggabungkan shader ke skrip `bash` atau pipeline unix dan menggunakannya sama mirip [ImageMagick](http://www.imagemagick.org/script/index.php). [glslViewer](https://github.com/patriciogonzalezvivo/glslViewer) juga merupakan cara yang bagus untuk menkompilasi shader pada [Raspberry Pi](https://www.raspberrypi.org/), yang mana merupakan alasan [openFrame.io](http://openframe.io/) menggunakan itu untuk menampilkan artwork shader. Pelajari lebih lanjut tentang aplikasi ini [di sini](https://github.com/patriciogonzalezvivo/glslViewer)
```bash
glslViewer yourShader.frag yourInputImage.png —w 500 -h 500 -s 1 -o yourOutputImage.png
glslViewer yourShader.frag yourInputImage.png —w 500 -h 500 -E screenshot,yourOutputImage.png
```
**Membuat**: untuk menerangi pengalaman pengkodean shader, saya membuat editor online bernama [glslEditor](https://github.com/patriciogonzalezvivo/glslEditor). Editor ini disematkan pada contoh langsung buku, ini membawa serangkaian widget praktis untuk membuat pengalaman abstrak bekerja dengan kode glsl lebih nyata. Anda juga dapat menjalankannya sebagai aplikasi web mandiri dari [editor.thebookofshaders.com/](http://editor.thebookofshaders.com/). Pelajari lebih lanjut tentang itu [di sini](https://github.com/patriciogonzalezvivo/glslEditor).
@ -35,7 +35,7 @@ Jika anda memilih untuk mengerjakannya offline menggunakan [SublimeText](https:/
## Menjalankan Shader pada Framework Favoritmu
Dalam kasus kamu mempunyai pengalaman dalam pemrograman pada framework seperti: [Processing](https://processing.org/), [Three.js](http://threejs.org/) or [OpenFrameworks](http://openframeworks.cc/), anda mungkin tertarik untuk mencoba shader pada platform yang nyaman bagi anda. Contoh berikut adalah cara untuk menyetel shader pada beberapa framework terkenal denggan uniform yang sama yag akan kita gunakan di seluruh buku ini, (Dalan [Repositori Bithub Bab ini](https://github.com/patriciogonzalezvivo/thebookofshaders/tree/master/04), anda akan menemukan kode sumber lengkap untuk 3 framework ini).
Dalam kasus kamu mempunyai pengalaman dalam pemrograman pada framework seperti: [Processing](https://processing.org/), [Three.js](http://threejs.org/), [OpenFrameworks](http://openframeworks.cc/) or [SFML](https://www.sfml-dev.org/), anda mungkin tertarik untuk mencoba shader pada platform yang nyaman bagi anda. Contoh berikut adalah cara untuk menyetel shader pada beberapa framework terkenal denggan uniform yang sama yag akan kita gunakan di seluruh buku ini, (Dalan [Repositori Bithub Bab ini](https://github.com/patriciogonzalezvivo/thebookofshaders/tree/master/04), anda akan menemukan kode sumber lengkap untuk 3 framework ini).
### Dan **Three.js**

@ -13,7 +13,7 @@ Come potete vedere, è solo necessario l'elemento ```canvas``` con l'attributo `
Se siete come me, probabilmente vorrete eseguire gli shader direttamente dalla console. In questo caso date un'occhiata a [glslViewer](https://github.com/patriciogonzalezvivo/glslViewer). Questa applicazione consente d'incorporare gli shader nel vostro script ```bash``` o pipelines UNIX e d?utilizzarli in modo simile a [ImageMagick](http://www.imagemagick.org/script/index.php). Anche [glslViewer](https://github.com/patriciogonzalezvivo/glslViewer) è un ottimo modo per compilare gli shader sul [Raspberry Pi](https://www.raspberrypi.org/), motivo per il quale [openFrame.io](http://openframe.io/) lo usa per visualizzare le opere d'arte di tipo shader. Potete trovare ulteriori informazioni su questa applicazione [cliccando qui](https://github.com/patriciogonzalezvivo/glslViewer).
```bash
glslViewer yourShader.frag yourInputImage.png —w 500 -h 500 -s 1 -o yourOutputImage.png
glslViewer yourShader.frag yourInputImage.png —w 500 -h 500 -E screenshot,yourOutputImage.png
```
**Creare**: per migliorare la programmazione degli shader, ho realizzato un editor online chiamato [glslEditor](https://github.com/patriciogonzalezvivo/glslEditor). Questo editor è integrato agli esempi del libro e mette a disposizione una serie di comodi widget per rendere più tangibile il codice astratto GLSL. È anche possibile eseguirlo come un'applicazione standalone web da [editor.thebookofshaders.com/](http://editor.thebookofshaders.com/). Scoprite di più a proposito [cliccando qui](https://github.com/patriciogonzalezvivo/glslEditor).
@ -34,7 +34,7 @@ Se si preferisce lavorare offline utilizzando [SublimeText](https://www.sublimet
## Eseguire i vostri shader nel vostro framework preferito
Nel caso in cui si dispone già di esperienze di programmazione in framework quali: [Processing](https://processing.org/), [Three.js](http://threejs.org/) o [OpenFrameworks](http://openframeworks.cc/), probabilmente sarete ansiosi di provare gli shader sulle piattaforme su cui vi trovate bene. I seguenti sono esempi di come impostare gli shader in alcuni dei framework più popolari con le stesse uniforms che andremo ad utilizzare in questo libro. (Nella [repository GitHub per questo capitolo](https://github.com/patriciogonzalezvivo/thebookofshaders/tree/master/04), troverete il codice sorgente completo per questi tre framework.)
Nel caso in cui si dispone già di esperienze di programmazione in framework quali: [Processing](https://processing.org/), [Three.js](http://threejs.org/), [OpenFrameworks](http://openframeworks.cc/) o [SFML](https://www.sfml-dev.org/), probabilmente sarete ansiosi di provare gli shader sulle piattaforme su cui vi trovate bene. I seguenti sono esempi di come impostare gli shader in alcuni dei framework più popolari con le stesse uniforms che andremo ad utilizzare in questo libro. (Nella [repository GitHub per questo capitolo](https://github.com/patriciogonzalezvivo/thebookofshaders/tree/master/04), troverete il codice sorgente completo per questi tre framework.)
### In **Three.js**

@ -13,7 +13,7 @@
もしあなたが私のような人だったら、コンソールから直接シェーダーを走らせたいと思うでしょう。その場合は[glslViewer](https://github.com/patriciogonzalezvivo/glslViewer)を試してみてください。このアプリケーションを利用すると[ImageMagic](http://www.imagemagick.org/script/index.php)を使うのと同じような方法で、シェーダーをbashスクリプトやUNIXパイプラインで使うことができます。[glslViewer](https://github.com/patriciogonzalezvivo/glslViewer)は[RaspberryPi](https://www.raspberrypi.org/)でシェーダーをコンパイルするのにとても便利なので、[openFrame.io](http://openframe.io/)でもglslViewerをシェーダーによる作品の表示に使っています。詳しくは[こちら](https://github.com/patriciogonzalezvivo/glslViewer)をご覧ください。
```bash
glslViewer yourShader.frag yourInputImage.png —w 500 -h 500 -s 1 -o yourOutputImage.png
glslViewer yourShader.frag yourInputImage.png —w 500 -h 500 -E screenshot,yourOutputImage.png
```
**作成する**: シェーダーのコーディングを簡単にするため、[glslEditor](https://github.com/patriciogonzalezvivo/glslEditor)というオンラインのエディターを用意しました。このエディターはこの本のサンプルにも埋め込まれています。glslEditorには幾つもの便利なウィジェットが備わっていて、直接触って具体的に結果を見ることで、抽象的なglslのコーディングをより理解しやすくしてくれます。[editor.thebookofshaders.com/](http://editor.thebookofshaders.com/)から単体で使うこともできます。詳しくは[こちら](https://github.com/patriciogonzalezvivo/glslEditor)をご覧ください。
@ -36,7 +36,7 @@ glslViewer yourShader.frag yourInputImage.png —w 500 -h 500 -s 1 -o yourOutput
## 好みのフレームワークでシェーダーを実行する
もし[Processing](https://processing.org/)、[Three.js](http://threejs.org/) 、[OpenFrameworks](http://openframeworks.cc/)などのフレームワークを使ったブログラミングの経験があるならば、慣れ親しんだ環境でシェーダーを試してみたいと思うでしょう。下記では人気のあるこれらのフレームワークで、この本で紹介するシェーダーを実行できるように設定する方法をお見せします(この本の[GitHubのリポジトリ](https://github.com/patriciogonzalezvivo/thebookofshaders/tree/master/04)にはこれら3つのフレームワークのためのソースコードが丸ごと置いてあります
もし[Processing](https://processing.org/)、[Three.js](http://threejs.org/)、[OpenFrameworks](http://openframeworks.cc/) 、[SFML](https://www.sfml-dev.org/)などのフレームワークを使ったブログラミングの経験があるならば、慣れ親しんだ環境でシェーダーを試してみたいと思うでしょう。下記では人気のあるこれらのフレームワークで、この本で紹介するシェーダーを実行できるように設定する方法をお見せします(この本の[GitHubのリポジトリ](https://github.com/patriciogonzalezvivo/thebookofshaders/tree/master/04)にはこれら3つのフレームワークのためのソースコードが丸ごと置いてあります
### **Three.js**を使う

@ -13,7 +13,7 @@ Como você pode ver, só precisa de um elemento `canvas` com `class="glslCanvas"
Se você é como eu, provavelmente vai querer rodar shaders diretamente da console, e nesse caso você deveria dar uma olhada no [glslViewer](https://github.com/patriciogonzalezvivo/glslViewer). Esta aplicação lhe permite incorporar shaders em seus scripts `bash` ou pipelines do unix e usá-los de modo similiar ao [ImageMagick](http://www.imagemagick.org/script/index.php). Também, o [glslViewer](https://github.com/patriciogonzalezvivo/glslViewer) é uma boa forma de compilar shaders no seu [Raspberry Pi](https://www.raspberrypi.org/), razão pela qual o [openFrame.io](http://openframe.io/) o utiliza para exibir artes em shader. Aprenda mais sobre essa aplicação [aqui](https://github.com/patriciogonzalezvivo/glslViewer).
```bash
glslViewer yourShader.frag yourInputImage.png —w 500 -h 500 -s 1 -o yourOutputImage.png
glslViewer yourShader.frag yourInputImage.png —w 500 -h 500 -E screenshot,yourOutputImage.png
```
**Criar**: de modo a trazer mais luz para a experiência de codificação de shaders, eu fiz um editor online chamado [glslEditor](https://github.com/patriciogonzalezvivo/glslEditor). Este editor está embutido nos exemplos ao vivo do livro, e traz uma série de widgets bem convenientes para tornar mais tangível a experiência abstrata de trabalhar com código GLSL. Você também pode executá-lo como uma aplicação web standalone no endereço [editor.thebookofshaders.com/](http://editor.thebookofshaders.com/). Saiba mais sobre isso [aqui](https://github.com/patriciogonzalezvivo/glslEditor).
@ -34,7 +34,7 @@ Se você prefere trabalhar offline usando o [SublimeText](https://www.sublimetex
## Rodando seus shaders em seu framework favorito
Para o caso de você já ter experiência em programar em um framework como [Processing](https://processing.org/), [Three.js](http://threejs.org/) ou [OpenFrameworks](http://openframeworks.cc/), você provavelmente está animado para tentar os shaders nessas plataformas que você se sente confortável. Os exemplos a seguir são formas de como configurar os shaders em alguns frameworks populares com os mesmos uniforms que vamos usar ao longo desse livro. (No [Repositório GitHub para esse capítulo](https://github.com/patriciogonzalezvivo/thebookofshaders/tree/master/04), você encontra o código completo para esses três frameworks.)
Para o caso de você já ter experiência em programar em um framework como [Processing](https://processing.org/), [Three.js](http://threejs.org/), [OpenFrameworks](http://openframeworks.cc/) ou [SFML](https://www.sfml-dev.org/), você provavelmente está animado para tentar os shaders nessas plataformas que você se sente confortável. Os exemplos a seguir são formas de como configurar os shaders em alguns frameworks populares com os mesmos uniforms que vamos usar ao longo desse livro. (No [Repositório GitHub para esse capítulo](https://github.com/patriciogonzalezvivo/thebookofshaders/tree/master/04), você encontra o código completo para esses três frameworks.)
### Em **Three.js**

@ -13,7 +13,7 @@
Если вы разделяете мой подход к разработке, вам возможно захочется запускать шейдеры напрямую из консоли, в чём вам поможет [glslViewer](https://github.com/patriciogonzalezvivo/glslViewer). Это приложение позволяет встраивать шейдеры в `bash`-скрипты или конвейер unix, и может использоваться по аналогии с [ImageMagick](http://www.imagemagick.org/script/index.php). Так же, [glslViewer](https://github.com/patriciogonzalezvivo/glslViewer) - отличный способ скомпилировать шейдеры на [Raspberry Pi](https://www.raspberrypi.org/), и поэтому он используется на [openFrame.io](http://openframe.io/) для демонстрации шейдеров. Подробнее с этим приложением можно познакомиться [здесь](https://github.com/patriciogonzalezvivo/glslViewer).
```bash
glslViewer yourShader.frag yourInputImage.png —w 500 -h 500 -s 1 -o yourOutputImage.png
glslViewer yourShader.frag yourInputImage.png —w 500 -h 500 -E screenshot,yourOutputImage.png
```
**Создание**: чтобы сделать опыт создания шейдеров более ярким, я сделал онлайн-редактор [glslEditor](https://github.com/patriciogonzalezvivo/glslEditor). Этот редактор используется для демонстрации интерактивных примеров в книге и предоставляет набор виджетов, делающих абстрактный код на GLSL более осязаемым. Его так же можно запустить в отдельном веб-приложении по адресу [editor.thebookofshaders.com](http://editor.thebookofshaders.com/). Подробнее о редакторе [здесь](https://github.com/patriciogonzalezvivo/glslEditor).
@ -34,7 +34,7 @@ glslViewer yourShader.frag yourInputImage.png —w 500 -h 500 -s 1 -o yourOutput
## Запуск шейдера в вашем любимом фреймворке
Если у вас уже есть опыт программирования на таких фреймворках, как [Processing](https://processing.org/), [Three.js](http://threejs.org/) или [OpenFrameworks](http://openframeworks.cc/), вы можете попробовать шейдеры прямо в них. Ниже показаны способы установки используемых в книге uniform-переменных на некоторых популярных фреймворках. В [репозитории](https://github.com/patriciogonzalezvivo/thebookofshaders/tree/master/04) этой главы на Гитхабе вы найдёте полный исходный код для этих трёх фреймворков.
Если у вас уже есть опыт программирования на таких фреймворках, как [Processing](https://processing.org/), [Three.js](http://threejs.org/), [OpenFrameworks](http://openframeworks.cc/) или [SFML](https://www.sfml-dev.org/), вы можете попробовать шейдеры прямо в них. Ниже показаны способы установки используемых в книге uniform-переменных на некоторых популярных фреймворках. В [репозитории](https://github.com/patriciogonzalezvivo/thebookofshaders/tree/master/04) этой главы на Гитхабе вы найдёте полный исходный код для этих трёх фреймворков.
### **Three.js**

@ -15,7 +15,7 @@ Như bạn thấy, chỉ cần một thẻ `canvas` với `class="glslCanvas"` v
Nếu bạn giống tôi, bạn có thể sẽ muốn preview shader ngay trong console, và trong trường hợp thì bạn nên ngó qua [glslViewer](https://github.com/patriciogonzalezvivo/glslViewer). Ứng dụng này cho phép bạn kết hợp shader với script `bash` hay bất kỳ công cụ dòng lệnh nào của Unix giống như cách mà [ImageMagick](http://www.imagemagick.org/script/index.php) hoạt động. Ngoài ra [glslViewer](https://github.com/patriciogonzalezvivo/glslViewer) cũng là một cách hay để biên dịch shader trên [Raspberry Pi](https://www.raspberrypi.org/), cũng chính là lí do mà [openFrame.io](http://openframe.io/) dùng nó để preview shader. Tìm hiểu thêm về công cụ này tại [đây](https://github.com/patriciogonzalezvivo/glslViewer).
```bash
glslViewer yourShader.frag yourInputImage.png —w 500 -h 500 -s 1 -o yourOutputImage.png
glslViewer yourShader.frag yourInputImage.png —w 500 -h 500 -E screenshot,yourOutputImage.png
```
**Viết shader**: để chia sẻ kinh nghiệm code shader, tôi đã tạo một editor online gọi là [glslEditor](https://github.com/patriciogonzalezvivo/glslEditor). Editor này được nhúng vào các ví dụ trong quyển sách này, nó bổ sung các widget rất tiện cho việc viết code GLSL. Bạn cũng có thể chạy riêng nó như một ứng dụng web ở [editor.thebookofshaders.com/](http://editor.thebookofshaders.com/). Tìm hiểu thêm tại [đây](https://github.com/patriciogonzalezvivo/glslEditor).
@ -26,7 +26,7 @@ Nếu bạn thích làm việc offline bằng [SublimeText](https://www.sublimet
![](glslViewer.gif)
**Chia sẻ**: Bạn có thể chia sẻ shader bằng editor online ([editor.thebookofshaders.com/](http://editor.thebookofshaders.com/)) Cả phiên bản nhúng và chạy độc lập đều có nút bấm export cho bạn URL tới shader của mình. Nó còn có khả năng export trực tiếp tới [openFrame.io](http://openframe.io/).
**Chia sẻ**: Bạn có thể chia sẻ shader bằng editor online ([editor.thebookofshaders.com/](http://editor.thebookofshaders.com/))! Cả phiên bản nhúng và chạy độc lập đều có nút bấm export cho bạn một URL tới shader của mình. Nó còn có khả năng export trực tiếp tới [openFrame.io](http://openframe.io/).
![](glslEditor-00.gif)
@ -36,11 +36,11 @@ Nếu bạn thích làm việc offline bằng [SublimeText](https://www.sublimet
## Chạy shader trên framework yêu thích
Trong trường hợp bạn đã có kinh nghiệm lập trình với các framework như: [Processing](https://processing.org/), [Three.js](http://threejs.org/) hay [OpenFrameworks](http://openframeworks.cc/), you có thể sẽ muốn thử shader trên các nền tảng đó. Dưới đây là hướng dẫn sử dụng shader trên các framework phổ biến với các uniform giống như shader được viết trong quyển sách này. (Trong [repository GitHub cho chương này](https://github.com/patriciogonzalezvivo/thebookofshaders/tree/master/04), bạn có thể tìm thấy mã nguồn hoàn chỉnh của cả 3 framework này).
Trong trường hợp bạn đã có kinh nghiệm lập trình với các framework như: [Processing](https://processing.org/), [Three.js](http://threejs.org/), [OpenFrameworks](http://openframeworks.cc/) hay [SFML](https://www.sfml-dev.org/), you có thể sẽ muốn thử shader trên các nền tảng đó. Dưới đây là hướng dẫn sử dụng shader trên các framework phổ biến với các uniform giống như shader được viết trong quyển sách này. (Trong [repository GitHub cho chương này](https://github.com/patriciogonzalezvivo/thebookofshaders/tree/master/04), bạn có thể tìm thấy mã nguồn hoàn chỉnh của cả 3 framework này).
### Với **Three.js**
Ricardo Cabello (hay còn gọi là [MrDoob](https://twitter.com/mrdoob) ), một anh chàng thông minh và khiêm tốn đã phát triển một trong những framework nổi tiếng nhất cho WebGL cùng với các [cộng sự](https://github.com/mrdoob/three.js/graphs/contributors), đó là [Three.js](http://threejs.org/). Bạn sẽ tìm thấy rất nhiều ví dụ, hướng dẫn và sách dạy bạn cách dùng thư viện Javascript này để tạo nên các tác phẩm đồ hoạ 3D rất ngầu.
Ricardo Cabello (hay còn gọi là [MrDoob](https://twitter.com/mrdoob) ), một anh chàng thông minh và khiêm tốn đã phát triển một trong những framework nổi tiếng nhất cho WebGL cùng với các [cộng sự](https://github.com/mrdoob/three.js/graphs/contributors), đó là [Three.js](http://threejs.org/). Bạn sẽ tìm thấy rất nhiều ví dụ, hướng dẫn và sách dạy bạn cách dùng thư viện JavaScript này để tạo nên các tác phẩm đồ hoạ 3D rất ngầu.
Dưới đây là một ví dụ về code HTML và JS mà bạn cần để bắt đầu viết shader với three.js. Hãy chú ý tới đoạn `id="fragmentShader"`, đây là nơi mà bạn có thể copy-paste shader từ quyển sách này thay vào đó để thử.
@ -190,7 +190,7 @@ void ofApp::draw(){
}
```
Nếu bạn muốn sử dụng bộ đầy đủ các uniform trong GlslViewer và GlslCanvas trong openFrameworks một cách đơn giản, tôi xin giới thiệu addon [ofxShader](https://github.com/patriciogonzalezvivo/ofxshader) để hỗ trợ nhiều buffer, vật liệu, hot-reload và tự động chuyển đổi sang OpenGL ES trên Raspberry Pi. Code đơn giản như sau:
Nếu bạn muốn sử dụng bộ đầy đủ các uniform trong GlslViewer và GlslCanvas trong openFrameworks một cách đơn giản, tôi xin giới thiệu addon [ofxShader](https://github.com/patriciogonzalezvivo/ofxshader) để hỗ trợ nhiều buffer, chất liệu, hot-reload và tự động chuyển đổi sang OpenGL ES trên Raspberry Pi. Code đơn giản như sau:
```cpp
//--------------------------------------------------------------
@ -224,7 +224,7 @@ void ofApp::draw(){
![](blender/01.png)
3. Sử dụng ảnh trong vật liệu. Tên của ảnh sẽ dựa trên tên của file shader.
3. Sử dụng ảnh trong chất liệu. Tên của ảnh sẽ dựa trên tên của file shader.
![](blender/02.png)

@ -4,7 +4,7 @@ As part of the construction of this book and my art practice I made an ecosystem
## Running your shaders on the browser
**Display**: all live examples in this book are displayed using [glslCanvas](https://github.com/patriciogonzalezvivo/glslCanvas) which makes the process of running standalone shader incredible easy.
**Display**: all live examples in this book are displayed using [glslCanvas](https://github.com/patriciogonzalezvivo/glslCanvas) which makes the process of running standalone shader incredibly easy.
```html
<canvas class="glslCanvas" data-fragment-url=“yourShader.frag" data-textures=“yourInputImage.png” width="500" height="500"></canvas>
@ -15,7 +15,7 @@ As you can see, it just needs a `canvas` element with `class="glslCanvas"` and t
If you are like me, you will probably want to run shaders directly from the console, in that case you should check out [glslViewer](https://github.com/patriciogonzalezvivo/glslViewer). This application allows you to incorporate shaders into your `bash` scripts or unix pipelines and use it in a similar way to [ImageMagick](http://www.imagemagick.org/script/index.php). Also [glslViewer](https://github.com/patriciogonzalezvivo/glslViewer) is a great way to compile shaders on your [Raspberry Pi](https://www.raspberrypi.org/), which is the reason [openFrame.io](http://openframe.io/) uses it to display shader artwork. Learn more about this application [here](https://github.com/patriciogonzalezvivo/glslViewer).
```bash
glslViewer yourShader.frag yourInputImage.png —w 500 -h 500 -s 1 -o yourOutputImage.png
glslViewer yourShader.frag yourInputImage.png —w 500 -h 500 -E screenshot,yourOutputImage.png
```
**Create**: in order to illuminate the experience of coding shaders I made an online editor called [glslEditor](https://github.com/patriciogonzalezvivo/glslEditor). This editor is embedded on the book's live examples, it brings a series of handy widgets to make more tangible the abstract experience of working with glsl code. You can also run it as a standalone web application from [editor.thebookofshaders.com/](http://editor.thebookofshaders.com/). Learn more about it [here](https://github.com/patriciogonzalezvivo/glslEditor).
@ -36,7 +36,7 @@ If you prefer to work offline using [SublimeText](https://www.sublimetext.com/)
## Running your shaders on your favorite framework
In case you already have experience programming in a framework like: [Processing](https://processing.org/), [Three.js](http://threejs.org/) or [OpenFrameworks](http://openframeworks.cc/), you're probably excited to try shaders on these platforms you feel comfortable with. The following are examples of how to set shaders in some popular frameworks with the same uniforms that we are going to use throughout this book. (In the [GitHub repository for this chapter](https://github.com/patriciogonzalezvivo/thebookofshaders/tree/master/04), you'll find the full source code for these three frameworks.)
In case you already have experience programming in a framework like: [Processing](https://processing.org/), [Three.js](http://threejs.org/), [OpenFrameworks](http://openframeworks.cc/) or [SFML](https://www.sfml-dev.org/), you're probably excited to try shaders on these platforms you feel comfortable with. The following are examples of how to set shaders in some popular frameworks with the same uniforms that we are going to use throughout this book. (In the [GitHub repository for this chapter](https://github.com/patriciogonzalezvivo/thebookofshaders/tree/master/04), you'll find the full source code for these three frameworks.)
### In **Three.js**
@ -211,10 +211,9 @@ void ofApp::draw(){
For more information about shaders in openFrameworks go to this [excellent tutorial](http://openframeworks.cc/ofBook/chapters/shaders.html) made by [Joshua Noble](http://thefactoryfactory.com/).
### In **Blender**
[GlslTexture](https://github.com/patriciogonzalezvivo/glslTexture) is an addon that allows you to programatically generate textures using GLSL Shaders and is fully compatible with the rest of the sandboxes on this chapter. How it works:
[GlslTexture](https://github.com/patriciogonzalezvivo/glslTexture) is an addon that allows you to programmatically generate textures using GLSL Shaders and is fully compatible with the rest of the sandboxes on this chapter. How it works:
1. Operator Search: `F3` (or `SpaceBar` depending on your setup). Type `GlslTexture`

@ -0,0 +1,20 @@
cmake_minimum_required(VERSION 3.15)
project(TheBookOfShaders LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_EXTENSIONS OFF)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
find_package(SFML 2.5 COMPONENTS graphics REQUIRED)
add_executable(TheBookOfShaders
src/main.cpp
)
target_link_libraries(TheBookOfShaders sfml-graphics)
install(TARGETS TheBookOfShaders
RUNTIME DESTINATION .)
install(DIRECTORY data
DESTINATION .)

@ -0,0 +1,12 @@
#ifdef GL_ES
precision mediump float;
#endif
uniform vec2 u_resolution;
uniform vec3 u_mouse;
uniform float u_time;
void main() {
vec2 st = gl_FragCoord.st/u_resolution;
gl_FragColor = vec4(st.x,st.y,0.0,1.0);
}

@ -0,0 +1,45 @@
#include <SFML/Graphics.hpp>
#include <iostream>
int main()
{
auto window = sf::RenderWindow{ { 800U, 800U }, "The Book of Shaders" };
window.setFramerateLimit(144);
auto clock = sf::Clock{};
auto shape = sf::RectangleShape{ sf::Vector2f{ window.getSize() } };
auto shader = sf::Shader{};
if (!shader.loadFromFile("data/shader.frag", sf::Shader::Fragment))
{
std::cerr << "Couldn't load fragment shader\n";
return -1;
}
auto mouse_position = sf::Vector2f{};
while (window.isOpen())
{
for (auto event = sf::Event{}; window.pollEvent(event);)
{
if (event.type == sf::Event::Closed)
{
window.close();
}
else if (event.type == sf::Event::MouseMoved)
{
mouse_position = window.mapPixelToCoords({ event.mouseMove.x, event.mouseMove.y });
}
}
shader.setUniform("u_resolution", sf::Glsl::Vec2{ window.getSize() });
shader.setUniform("u_mouse", sf::Glsl::Vec2{ mouse_position });
shader.setUniform("u_time", clock.getElapsedTime().asSeconds());
window.clear();
window.draw(shape, &shader);
window.display();
}
}

@ -17,7 +17,7 @@ Esta relación par entre *x* e *y* (o el brillo) es conocida como *interpolació
<div class="codeAndCanvas" data="expo.frag"></div>
Interesante ¿No? En la línea 19 puedes probar diferentes exponentes: 20.0, 2.0, 1.0, 0.0, 0.2 o 0.02 por ejemplo. Entender esta relación entre el valor y el exponente nos será muy útil. Usar este tipo de funciones matemáticas aquí y allá nos dará un control expresivo sobre nuestro código, como si fuese un tipo de acupuntura con el que manejas el flujo de los valores.
Interesante ¿No? En la línea 22 puedes probar diferentes exponentes: 20.0, 2.0, 1.0, 0.0, 0.2 o 0.02 por ejemplo. Entender esta relación entre el valor y el exponente nos será muy útil. Usar este tipo de funciones matemáticas aquí y allá nos dará un control expresivo sobre nuestro código, como si fuese un tipo de acupuntura con el que manejas el flujo de los valores.
[```pow()```](../glossary/?search=pow) es una función nativa en GLSL y hay muchas más. La mayoría de ellas son aceleradas por hardware, lo que significa que, usadas de la forma correcta, harán tu código mucho más rápido.

@ -1,7 +1,7 @@
# Các thuật toán hình học
## Các hàm số cơ bản (Hàm hình dạng - Shape function)
Chương này có thể đặt tên là "bài học sơn hàng rào của ngài Miyagi". Trước đó, ta đã ánh xạ toạ độ *x**y* sang các kênh *RED**GREEN*. Ta cũng đã tạo ra một hàm nhận một vector 2 chiều (x, y) làm tham số đầu vào và trả ra một vector 4 chiều (r, g, b, a). Nhưng trước khi đi sâu vào việc biến đổi dữ liệu giữa các kiểu thì ta cần bắt đầu từ những thứ đơn giản hơn ... rất nhiều. Đó là việc tạo ra các hàm chỉ xử lý vector 1 chiều. Càng bỏ thời gian và công sức học cho thun thục kỹ năng này, võ karate-shader của bạn sẽ càng cao siêu.
Chương này có thể đặt tên là "bài học sơn hàng rào của ngài Miyagi". Trước đó, ta đã ánh xạ toạ độ *x**y* sang các kênh *RED**GREEN*. Ta cũng đã tạo ra một hàm nhận một vector 2 chiều (x, y) làm tham số đầu vào và trả ra một vector 4 chiều (r, g, b, a). Nhưng trước khi đi sâu vào việc biến đổi dữ liệu giữa các kiểu thì ta cần bắt đầu từ những thứ đơn giản hơn... rất nhiều. Đó là việc tạo ra các hàm chỉ xử lý vector 1 chiều. Càng bỏ thời gian và công sức học cho thun thục kỹ năng này, võ karate-shader của bạn sẽ càng cao siêu.
![The Karate Kid (1984)](mr_miyagi.jpg)
@ -9,7 +9,7 @@ Cấu trúc code dưới đây sẽ là hàng rào của chúng ta. Trong đó,
<div class="codeAndCanvas" data="linear.frag"></div>
**Chú thích**: Hàm khởi tạo `vec3` sẽ tự động "nhận ra" bạn muốn gán màu của cả 3 kênh RGB giống nhau ở dòng 19. Còn hàm khởi tạo `vec4` thì "nhận ra`" bạn muốn tạo một vector 4 chiều từ một vector 3 chiều kết hợp một số thực nữa dành cho chiều thứ tư, ở dòng 25.
**Chú thích**: Hàm khởi tạo `vec3` sẽ tự động "nhận ra" bạn muốn gán màu của cả 3 kênh RGB giống nhau ở dòng 19. Còn hàm khởi tạo `vec4` thì "nhận ra" bạn muốn tạo một vector 4 chiều từ một vector 3 chiều kết hợp một số thực nữa dành cho chiều thứ tư, ở dòng 25.
Đoạn code này là hàng rào của bạn; nên hãy tập trung quan sát kỹ. Bạn sẽ còn sử dụng khoảng `0.0``1.0` này nhiều lần nữa. Bạn sẽ thuần thục kỹ năng tạo nên đồ thị này.
@ -19,25 +19,25 @@ Cấu trúc code dưới đây sẽ là hàng rào của chúng ta. Trong đó,
Thú vị phải không ? Ở dòng 22, hãy thử các số mũ khác nhau như: 20.0, 2.0, 1.0, 0.0, 0.2 và 0.02 chẳng hạn. Hiểu được mối quan hệ giữa giá trị và số mũ sẽ rất hữu ích. Bằng cách sử dụng các hàm toán học ở đây bạn sẽ nắm rõ hơn về cách điều khiển các đường cong.
[`pow()`](..glossary/?lan=vi&search=pow) là hàm có sẵn trong số rất nhiều hàm của GLSL. Hầu hết đều được tăng tốc tính toán bởi phần cứng, có nghĩa là nếu được dùng đúng cách nó sẽ giúp code chạy nhanh hơn.
[`pow()`](../glossary/?lan=vi&search=pow) là hàm có sẵn trong số rất nhiều hàm của GLSL. Hầu hết đều được tăng tốc tính toán bởi phần cứng, có nghĩa là nếu được dùng đúng cách nó sẽ giúp code chạy nhanh hơn.
Hãy thay hàm luỹ thừa ở dòng 22 bằng các hàm khác như: [`exp()`](..glossary/?lan=vi&search=exp), [`log()`](..glossary/?lan=vi&search=log) và [`sqrt()`](..glossary/?lan=vi&search=sqrt). Một số hàm sẽ cho kết quả thú vị nếu bạn sử dụng hằng số PI. Ở dòng 8 tôi có định nghĩa macro sẽ thay thế tất cả những chỗ `PI` xuất hiện bằng hằng số `3.14159265359`.
Hãy thay hàm luỹ thừa ở dòng 22 bằng các hàm khác như: [`exp()`](../glossary/?lan=vi&search=exp), [`log()`](../glossary/?lan=vi&search=log) và [`sqrt()`](../glossary/?lan=vi&search=sqrt). Một số hàm sẽ cho kết quả thú vị nếu bạn sử dụng hằng số PI. Ở dòng 8 tôi có định nghĩa macro sẽ thay thế tất cả những chỗ `PI` xuất hiện bằng hằng số `3.14159265359`.
### Step và Smoothstep
GLSL cũng có vài hàm số riêng biệt được tăng tốc bởi phần cứng.
Hàm [`step()`](..glossary/?lan=vi&search=step) nhận 2 tham số đầu vào. Tham số đầu tiên là một ngưỡng giới hạn nào đó, còn tham số thứ 2 là giá trị mà ta muốn biết có vượt qua ngưỡng giới hạn kia không. Bất kỳ giá trị nào nhỏ hơn ngưỡng sẽ cho kết quả `0.0` và ngược lại, tất cả các giá trị lớn hơn ngưỡng sẽ cho kết quả `1.0`.
Hàm [`step()`](../glossary/?lan=vi&search=step) nhận 2 tham số đầu vào. Tham số đầu tiên là một ngưỡng giới hạn nào đó, còn tham số thứ 2 là giá trị mà ta muốn biết có vượt qua ngưỡng giới hạn kia không. Bất kỳ giá trị nào nhỏ hơn ngưỡng sẽ cho kết quả `0.0` và ngược lại, tất cả các giá trị lớn hơn ngưỡng sẽ cho kết quả `1.0`.
Hãy thử thay giá trị ở dòng 20 của đoạn code dưới đây.
<div class="codeAndCanvas" data="step.frag"></div>
Một hàm tương tự là [`smoothstep()`](..glossary/?lan=vi&search=smoothstep). Tham số đầu vào là 1 khoảng min-max kèm thêm 1 giá trị. Hàm này sẽ nội suy giá trị đó trong khoảng min-max, các giá trị nằm ngoài khoảng này sẽ trở min hoặc max tuỳ theo nó nằm ở phía nào của khoảng đã cho.
Một hàm tương tự là [`smoothstep()`](../glossary/?lan=vi&search=smoothstep). Tham số đầu vào là 1 khoảng min-max kèm thêm 1 giá trị. Hàm này sẽ nội suy giá trị đó trong khoảng min-max, các giá trị nằm ngoài khoảng này sẽ trở min hoặc max tuỳ theo nó nằm ở phía nào của khoảng đã cho.
<div class="codeAndCanvas" data="smoothstep.frag"></div>
Ở ví dụ trước, dòng 12, chú ý rằng ta đã dùng hàm `smoothstep` để vẽ đồ thị trong hàm `plot()`. Nếu muốn đồ thị trồi lên ở một đoạn nào đó thì làm thế nào ? Bằng cách ghép hai hàm [`smoothstep()`](..glossary/?lan=vi&search=smoothstep) lại. Hãy thay dòng code dưới đây vào dòng 20. Trông như ta đã chẻ đôi canvas ra phải không ?
Ở ví dụ trước, dòng 12, chú ý rằng ta đã dùng hàm `smoothstep` để vẽ đồ thị trong hàm `plot()`. Nếu muốn đồ thị trồi lên ở một đoạn nào đó thì làm thế nào ? Bằng cách ghép hai hàm [`smoothstep()`](../glossary/?lan=vi&search=smoothstep) lại. Hãy thay dòng code dưới đây vào dòng 20. Trông như ta đã chẻ đôi canvas ra phải không ?
```glsl
float y = smoothstep(0.2,0.5,st.x) - smoothstep(0.5,0.8,st.x);
@ -47,7 +47,7 @@ float y = smoothstep(0.2,0.5,st.x) - smoothstep(0.5,0.8,st.x);
Khi bạn muốn dùng Toán để tạo chuyển động, tạo hình hay pha trộn các giá trị, không có gì tốt hơn việc làm quen với sin và cos.
Hai hàm lượng giác cơ bản này kết hợp với nhau để tạo nên những vòng tròn đa năng như dao gấp quân đội Thuỵ Sỹ của MacGyver vậy. Việc tìm hiểu cách chúng hoạt động và kết hợp với nhau ra sao rất quan trọng. Về cơ bản, cho một góc bất kỳ (đơn vị radian), hai hàm này sẽ cho kết quả là tọa độ *x* ([cos](..glossary/?lan=vi&search=cos)) và *y* ([sin](..glossary/?lan=vi&search=sin)) của 1 điểm trên đường tròn có bán kính bằng 1. Và chính việc kết quả thu được từ 2 hàm này vừa biến thiên một cách mềm mại lại còn luôn được chuẩn hoá sẵn theo cặp và cả đơn lẻ (trong khoảng -1 tới 1) khiến cho 2 hàm này trở thành các công cụ siêu hữu ích.
Hai hàm lượng giác cơ bản này kết hợp với nhau để tạo nên những vòng tròn đa năng như dao gấp quân đội Thuỵ Sỹ của MacGyver vậy. Việc tìm hiểu cách chúng hoạt động và kết hợp với nhau ra sao rất quan trọng. Về cơ bản, cho một góc bất kỳ (đơn vị radian), hai hàm này sẽ cho kết quả là tọa độ *x* ([cos](../glossary/?lan=vi&search=cos)) và *y* ([sin](../glossary/?lan=vi&search=sin)) của 1 điểm trên đường tròn có bán kính bằng 1. Và chính việc kết quả thu được từ 2 hàm này vừa biến thiên một cách mềm mại lại còn luôn được chuẩn hoá sẵn theo cặp và cả đơn lẻ (trong khoảng -1 tới 1) khiến cho 2 hàm này trở thành các công cụ siêu hữu ích.
![](sincos.gif)
@ -55,7 +55,7 @@ Mặc dù rất khó để mô tả mối liên hệ giữa các hàm lượng g
<div class="simpleFunction" data="y = sin(x);"></div>
Hãy nhìn thật kỹ đồ thị hình sine. Chú ý cách mà các giá trị *y* biến thiên rất mượt giữa +1 và -1. Như ta đã thấy ở ví dụ có sử dụng thời gian ở chương trước, bạn có thể sử dụng tính chất tuần hoàn này của hàm [`sin()`](..glossary/?lan=vi&search=sin) để áp dụng cho các thuộc tính. Nếu bạn đang đọc trên trình duyệt, bạn có thể sửa đoạn code phía trên để xem các sóng đồ thị thay đổi như thế nào. (Chú ý: Đừng quên dấu chấm phẩy ở cuối dòng.)
Hãy nhìn thật kỹ đồ thị hình sine. Chú ý cách mà các giá trị *y* biến thiên rất mượt giữa +1 và -1. Như ta đã thấy ở ví dụ có sử dụng thời gian ở chương trước, bạn có thể sử dụng tính chất tuần hoàn này của hàm [`sin()`](../glossary/?lan=vi&search=sin) để áp dụng cho các thuộc tính. Nếu bạn đang đọc trên trình duyệt, bạn có thể sửa đoạn code phía trên để xem các sóng đồ thị thay đổi như thế nào. (Chú ý: Đừng quên dấu chấm phẩy ở cuối dòng.)
Hãy thử các thay đổi sau và xem điều gì xảy ra:
@ -63,21 +63,21 @@ Hãy thử các thay đổi sau và xem điều gì xảy ra:
* Nhân *x* với `PI` trước khi gọi hàm `sin`. Bạn sẽ thấy 2 chu kỳ bị **co lại** và lặp lại mỗi 2 đơn vị số nguyên.
* Nhân `u_time`với *x* trước khi gọi hàm `sin`. Bạn sẽ thấy **tần số (frequency)** giữa các chu kỳ ngày càng ngắn lại. Chú ý rằng u_time càng lớn thì càng khó nhìn rõ đồ thị do các chu kỳ bị co lại rất nhiều.
* Nhân `u_time` với *x* trước khi gọi hàm `sin`. Bạn sẽ thấy **tần số (frequency)** giữa các chu kỳ ngày càng ngắn lại. Chú ý rằng u_time càng lớn thì càng khó nhìn rõ đồ thị do các chu kỳ bị co lại rất nhiều.
* Cộng 1.0 vào [`sin(x)`](..glossary/?lan=vi&search=sin). Và bạn sẽ thấy toàn bộ sóng được **nâng lên (displaced)** khiến cho giá trị nằm trong khoảng 0.0 và 2.0.
* Cộng 1.0 vào [`sin(x)`](../glossary/?lan=vi&search=sin). Và bạn sẽ thấy toàn bộ sóng được **nâng lên (displaced)** khiến cho giá trị nằm trong khoảng 0.0 và 2.0.
* Nhân [`sin(x)`](..glossary/?lan=vi&search=sin) với 2.0. Và bạn sẽ thấy **biên độ (amplitude)** rộng gấp đôi.
* Nhân [`sin(x)`](../glossary/?lan=vi&search=sin) với 2.0. Và bạn sẽ thấy **biên độ (amplitude)** rộng gấp đôi.
* Tính giá trị tuyệt đối ([`abs()`](..glossary/?lan=vi&search=abs)) của hàm `sin(x)`. Trông đồ thị sẽ giống như đường đi của quả bóng nảy trên mặt đất.
* Tính giá trị tuyệt đối ([`abs()`](../glossary/?lan=vi&search=abs)) của hàm `sin(x)`. Trông đồ thị sẽ giống như đường đi của quả bóng nảy trên mặt đất.
* Tách riêng phần thập phân bằng hàm [`fract()`](..glossary/?lan=vi&search=fract)từ kết quả của [`sin(x)`](..glossary/?lan=vi&search=sin).
* Tách riêng phần thập phân bằng hàm [`fract()`](../glossary/?lan=vi&search=fract) từ kết quả của [`sin(x)`](../glossary/?lan=vi&search=sin).
* Làm tròn lên bằng hàm [`ceil()`](..glossary/?lan=vi&search=ceil) và làm tròn xuống bằng hàm [`floor()`](..glossary/?lan=vi&search=floor) từ kết quả của [`sin(x)`](..glossary/?lan=vi&search=sin) để có được sóng điện tử của các giá trị 1 và -1.
* Làm tròn lên bằng hàm [`ceil()`](../glossary/?lan=vi&search=ceil) và làm tròn xuống bằng hàm [`floor()`](../glossary/?lan=vi&search=floor) từ kết quả của [`sin(x)`](../glossary/?lan=vi&search=sin) để có được sóng điện tử của các giá trị 1 và -1.
### Các hàm hữu ích khác
Chúng tôi vừa mới giới thiệu cho các bạn 1 vài hàm mới. Giờ là lúc thử nghiệm từng hàm một bằng cách uncomment từng dòng dưới đây một. Hãy làm quen với các hàm này. Tôi biết bạn đang thắc mắc ... tại sao ? Google nhanh với từ khoá "generative art" sẽ cho bạn câu trả lời. Hãy nhớ rằng các hàm này là hàng rào của chúng ta. Chúng ta đang dần thuần thục với các chuyển động 1 chiều, chỉ có lên và xuống. Sớm thôi, ta sẽ đụng tới các chiều thứ hai, ba và bốn!
Chúng tôi vừa mới giới thiệu cho các bạn 1 vài hàm mới. Giờ là lúc thử nghiệm từng hàm một bằng cách uncomment từng dòng dưới đây một. Hãy làm quen với các hàm này. Tôi biết bạn đang thắc mắc... tại sao ? Google nhanh với từ khoá "generative art" sẽ cho bạn câu trả lời. Hãy nhớ rằng các hàm này là hàng rào của chúng ta. Chúng ta đang dần thuần thục với các chuyển động 1 chiều, chỉ có lên và xuống. Sớm thôi, ta sẽ đụng tới các chiều thứ hai, ba và bốn!
![Anthony Mattox (2009)](anthony-mattox-ribbon.jpg)
@ -125,7 +125,7 @@ Hãy nhìn vào bảng các phương trình dưới đây, được tạo bởi
#### Một vài công cụ cho bạn
Đây là một vài công cụu sẽ giúp bạn vẽ đồ thị các hàm 1 cách trực quan nhất.
Đây là một vài công cụ sẽ giúp bạn vẽ đồ thị các hàm 1 cách trực quan nhất.
* Grapher: Nếu bạn dùng máy Mac, gõ `grapher` trong Spotlight và bạn có thể dùng ngay công cụ siêu tiện ích này.

@ -45,16 +45,6 @@ magenta = yellow.rbg; // Assign the channels with green and blue swapped
green.rgb = yellow.bgb; // Assign the blue channel of Yellow (0) to red and blue channels
```
#### 个人工具箱
你可能不习惯用数字拾取颜色--这样非常反直觉。幸运的是app store上有许多可以轻松完成这项任务的程序。寻找一个合适自己的并练习将颜色转化为 ```vec3``` 或 ```vec4``` 格式。例如,这是我在[Spectrum](http://www.eigenlogik.com/spectrum/mac)中使用的的模板。
```
vec3({{rn}},{{gn}},{{bn}})
vec4({{rn}},{{gn}},{{bn}},1.0)
```
### 混合颜色
现在你了解到如何定义颜色是时候将先前所学的整合一下了在GLSL中有个十分有用的函数[```mix()```](../glossary/?search=mix)这个函数让你以百分比混合两个值。猜下百分比的取值范围没错0到1完美学了这么久的基本功是时候来用一用了

@ -43,15 +43,6 @@ magenta = yellow.rbg; // Zuweisung von yellow an magenta bei gleichzeitigem Ta
green.rgb = yellow.bgb; // Zuweisung des Blau-Kanals von yellow an den Rot- und Blau-Kanal von green
```
#### Für Deine Werkzeugkiste
Vielleicht bist Du es nicht gewohnt, Farben über Zahlenwerte zu definieren. Und mal ganz ehrlich, das ist ja auch nicht sonderlich intuitiv. Glücklicherweise gibt es eine Menge intelligenter Programme und Webseiten, mit denen man Farben am Bildschirm auswählen kann und dann die zugehörigen Werte für Rot, Grün und Blau erhält. Am besten, man bekommt sie gleich als Definition für einen ```vec3``` oder ```vec4``` im GLSL-Format geliefert. Hier sind zum Beispiel die Vorlagen, die ich auf [Spectrum](http://www.eigenlogik.com/spectrum/mac) nutze, um einen passenden Ausdruck für GLSL zu erhalten:
```
vec3({{rn}},{{gn}},{{bn}})
vec4({{rn}},{{gn}},{{bn}},1.0)
```
### Mischen von Farben
Jetzt, wo Du weißt, wie man Farben definiert, wird es Zeit, dies mit unserem bisher gesammelten Wissen zu verknüpfen. In GLSL gibt es eine äußerst praktische Funktion mit dem Namen [```mix()```](../glossary/?search=mix), über die man zwei Werte in Form von Prozentangaben mischen kann. Vielleicht kannst Du Dir bereits denken, wie diese Prozentangaben auszusehen haben? Genau, als Werte zwischen ```0.0``` und ```1.0```! Das passt doch perfekt, nachdem Du schon so viel Zahlen-Karate am Zaun geübt hast. Es ist an der Zeit, Dein Wissen umzusetzen.

@ -43,15 +43,6 @@ magenta = yellow.rbg; // Assign the channels with green and blue swapped
green.rgb = yellow.bgb; // Assign the blue channel of Yellow (0) to red and blue channels
```
#### Para tu caja de herramientas
Quizás no estás acostumbrado a seleccionar colores usando números - puede ser un poco confuso. Por suerte, hay muchísimos programas que nos hacen este trabajo mucho más sencillo. Encuentra el que más se adapte a tus necesidades y úsalo para trabajar con colores en formato vec3 o vec4. Por ejemplo, estos son los templates que uso en [Spectrum](http://www.eigenlogik.com/spectrum/mac):
```
vec3({{rn}},{{gn}},{{bn}})
vec4({{rn}},{{gn}},{{bn}},1.0)
```
### Mezclando color
Ahora que sabes como se definen los colores, es hora de integrar esto con lo que aprendimos previamente. En GLSL hay una función muy útil, [```mix()```](../glossary/?search=mix), que te permite mezclar dos valores en porcentaje. ¿Puedes adivinar cuál es el rango de porcentaje? ¡Si, valores de 0.0 a 1.0! Lo cual es perfecto para ti, porque luego de esas largas horas practicando tus movimientos de karate en la cerca. ¡Ahora es el momento de usar esos conocimientos!

@ -43,14 +43,6 @@ magenta = yellow.rbg; // Assign the channels with green and blue swapped
green.rgb = yellow.bgb; // Assign the blue channel of Yellow (0) to red and blue channels
```
#### ابزار کمکی شما
احتمالا عادت ندارید با استفاده از مقادیر عددی رنگ خودر را انتخاب کنید، خیلی عقلانی هم نیست. خوشبختانه بسیاری از برنامه ها به صورت هوشمند این کار را انجام می‌دهند، یکی را که مناسب خودتان می‌بینید را ، پیدا و از آن بردار های رنگی خود را استخراج کنید. من از این الگو ها در [Spectrum](http://www.eigenlogik.com/spectrum/mac) استفاده می‌کنم:
```
vec3({{rn}},{{gn}},{{bn}})
vec4({{rn}},{{gn}},{{bn}},1.0)
```
### ترکیب رنگ ها
اکنون که می‌دانید رنگ ها چگونه تعریف می‌شوند، وقت آن است، از دانش های قبلیمان استفاده کنیم. در GLSL فانکشن مفیدی به نام [mix()](../glossary/?search=mix) وجود دارد، که به شما این امکان را می‌دهد دو مقدار را با درصد خاصی با هم مخلوط کنید. آیا می‌توانید حدس بزنید دامنه مقدار چقدر است؟ بله بین 0.0 تا 1.0 . بعد از تمرین های گذشته که آن ها هم با اعداد بین 0 تا 1 مرتبط بودند. وقت آن است دوباره از آنان استفاده کنید.

@ -19,7 +19,7 @@ red.z = 0.0;
Dans l'exemple ci dessus, *x*, *y* et *z* permettent d'**accéder** aux 3 valeurs contenues dans l'objet `red` de type `vec3`, ce sont les **accesseurs** aux propriétés de `red`.
Définir une couleur avec *x*, *y* et *z* peut être un peu déroutant, c'est pourquoi il existe différentes manières d'accéder aux valeurs des propriétés des vectuers.
Définir une couleur avec *x*, *y* et *z* peut être un peu déroutant, c'est pourquoi il existe différentes manières d'accéder aux valeurs des propriétés des vecteurs.
Les valeurs de `.x`, `.y` et `.z` peuvent être récupérées avec les **accesseurs** `.r`, `.g` et `.b`, ou `.s`, `.t` et `.p`. (`.s`, `.t` et `.p` sont généralement utilisées pour encoder les coordonnées spatiales des textures, nous verrons ça dans les chapitres suivants).
Il est également possible d'accéder aux valeurs des propriétés des vecteurs par leur position d'index dans l'objet: `[0]`, `[1]` and `[2]`.
@ -118,19 +118,6 @@ magenta = jaune.rbg; // Assigne the valeur en intervertissant le vert et le bl
vert.rgb = jaune.bgb; // Assigne le canal bleu du jaune (0) aux canaux rouges et bleus
```
#### Pour la boîte à outils
Si vous êtes incapables de choisir des couleurs par le biais des chiffres, c'est normal ; cela peut être très contre-intuitif.
Heureusement pour nous, il existe de nombreux programmes qui nous simplifient la tâche.
Trouvez celui qui vous convient et apprenez à formater vos couleurs en `vec3` ou `vec4`.
Par exemple, voici les gabarits que j'utilise avec [Spectrum](http://www.eigenlogik.com/spectrum/mac) :
```
vec3({{rn}},{{gn}},{{bn}})
vec4({{rn}},{{gn}},{{bn}},1.0)
```
### Mélanger les couleurs
A présent que nous savons définir les couleurs, il est temps de les utiliser avec ce que nous avons déjà appris.

@ -43,15 +43,6 @@ magenta = yellow.rbg; // Assign the channels with green and blue swapped
green.rgb = yellow.bgb; // Assign the blue channel of Yellow (0) to red and blue channels
```
#### Untuk kotak alat Anda
Anda mungkin tidak terbiasa memilih warna dengan angka - ini bisa sangat berlawanan dengan intuisi. Beruntung bagi Anda, ada banyak program pintar yang memudahkan pekerjaan ini. Temukan yang sesuai dengan kebutuhan Anda, lalu latih untuk memberikan warna dalam format `vec3` atau` vec4`. Misalnya, berikut adalah template yang saya gunakan di [Spectrum](http://www.eigenlogik.com/spectrum/mac):
```
vec3({{rn}},{{gn}},{{bn}})
vec4({{`rn}},{{gn}},{{bn}},1.0)
```
### Mencampur warna
Sekarang setelah Anda mengetahui bagaimana warna didefinisikan, sekarang saatnya untuk mengintegrasikannya dengan pengetahuan kita sebelumnya. Di GLSL ada fungsi yang sangat berguna, [`mix()`](../glossary/?search=mix), yang memungkinkan Anda mencampur dua nilai dalam persentase. Bisakah Anda menebak berapa kisaran persentasenya? Ya, nilai antara 0,0 dan 1,0! Yang sempurna untuk Anda, setelah berjam-jam berlatih gerakan karate Anda dengan pagar - sekarang saatnya menggunakannya!

@ -44,15 +44,6 @@ magenta = yellow.rbg; // Invertite il canale del verde con quello del blu
green.rgb = yellow.bgb; // Assegnare il canale blu del giallo (0) ai canali rosso e blu
```
#### Per la vostra cassetta degli attrezzi
Potreste non essere abituati a selezionare i colori attraverso numeri - di sicuro questo processo potrebbe risultare controintuitivo. Per vostra fortuna esistono tanti programmi che semplificano questo lavoro. Trovatene uno che vada incontro ai vostri bisogni e usatelo per ottenere colori in formato ```vec3``` 0 ```vec4``` format. Per esempio, qui trovate i templates che io uso su [Spectrum](http://www.eigenlogik.com/spectrum/mac):
```
vec3({{rn}},{{gn}},{{bn}})
vec4({{rn}},{{gn}},{{bn}},1.0)
```
### Mescolare i colori
Ora che sapete come sono definiti i colori, è tempo di integrare ciò con le nostre conoscenze precedenti. In GLSL cè una funzione molto utile, [```mix()```](../glossary/?search=mix), che vi permette di mescolare due valori in percentuali. Riuscite ad indovinare lestensione della percentuale? Esatto, i valori tra 0.0 e 1.0! Dopo lunghe ore di esercizio, finalmente è ora di mettere le vostre conoscenze in pratica!

@ -44,15 +44,6 @@ magenta = yellow.rbg; // Assign the channels with green and blue swapped
green.rgb = yellow.bgb; // Assign the blue channel of Yellow (0) to red and blue channels
```
#### 便利な道具
数値を使って色を指定するのに慣れていないかもしれません。なかなか直感的ではありませんからね。ありがたいことに、手助けになる良くできたプログラムが数多くあります。あなたの使い道にあったものを見つけて ```vec3``` や ```vec4``` の形式で色を取り出せるように設定しておきましょう。例えば、下記は私が[Spectrum](http://www.eigenlogik.com/spectrum/mac)で使っているテンプレートです。
```
vec3({{rn}},{{gn}},{{bn}})
vec4({{rn}},{{gn}},{{bn}},1.0)
```
### 色の調合
色がどのように定義されるか分かったところで、これまでに学んだ知識と組み合わせてみましょう。GLSLにはとても便利な [```mix()```](../glossary/?search=mix) 関数があり、2つの値をパーセンテージを指定して混ぜ合わせることができます。

@ -46,17 +46,6 @@ magenta = yellow.rbg; // 초록과 파랑채널을 교환
green.rgb = yellow.bgb; // 노란색의 파랑채널(0)을 빨강과 파랑채널에 할당.
```
#### 도구상자
여러분은 숫자를 기반으로 색을 고르는 것에 익숙하지 않을 수 있다. - 이는 매우 직관에 어긋날 수도 있다.
다행히, 이를 쉽게 해주는 똑똑한 프로그램들이 많이 있다.
그 중 필요한 것을 찾아서, 프로그램에서 원하는 색을 `vec3`, `vec4`형식으로 가져올 수 있도록 연습해보길 바란다.
예를 들어, [스펙트럼](http://www.eigenlogik.com/spectrum/mac)에서 내가 사용하는 템플릿은 다음과 같다:
```
vec3({{rn}},{{gn}},{{bn}})
vec4({{rn}},{{gn}},{{bn}},1.0)
```
### 색상 혼합
이제 색이 어떻게 정의되는지 알았으니, 이것을 지금까지 배운것들과 통합할 때이다. GLSL에는 두 값을 백분율로 혼합할 수 있는 매우 유용한 함수인 [`mix()`](../glossary/?search=mix) 라는것이 있다.

@ -43,15 +43,6 @@ magenta = yellow.rbg; // Assign the channels with green and blue swapped
green.rgb = yellow.bgb; // Assign the blue channel of Yellow (0) to red and blue channels
```
#### Para sua caixa de ferramentas
Você pode não estar acostumado a escolher cores com números - isso pode ser bem não intuitivo. Felizmente, existem inúmeros excelentes programas que facilitarão seu trabalho. Encontre um que atende as suas necessidades e então pratique para conseguir entregar cores em `vec3` ou `vec4`. Por exemplo, aqui está os templates que uso no [Spectrum](http://www.eigenlogik.com/spectrum/mac):
```
vec3({{rn}},{{gn}},{{bn}})
vec4({{rn}},{{gn}},{{bn}},1.0)
```
### Misturando cores
Agora que você sabe como cores são definidas, chegou a hora de integrar isso com nosso conhecimento prévio. Em GLSL, existe uma função muito útil chamada [`mix()`](../glossary/?search=mix), que permite que você misture dois valores em porcentagens. Você consegue adivinhar em qual intervalo esta porcentagem é? Sim, estes valores vão de 0.0 a 1.0! O que é perfeito para você, depois destas longas horas praticando seus movimentos de karatê na cerca - É hora de usá-los!

@ -43,15 +43,6 @@ magenta = yellow.rbg; // Меняем местами зелёный и син
green.rgb = yellow.bgb; // Записываем значение синего канала жёлтого цвета (0) в красный и синий
```
#### Инструментарий
Возможно, вам ранее не приходилось подбирать цвет с помощью чисел. Это выглядит очень контринтуитивно. К счастью, есть множество умных программ, которые упрощают это занятие. Найдите наиболее подходящую для себя и научите её представлять цвета в форматах `vec3` или `vec4`. Например, вот такие шаблоны я использую в [Spectrum](http://www.eigenlogik.com/spectrum/mac):
```
vec3({{rn}},{{gn}},{{bn}})
vec4({{rn}},{{gn}},{{bn}},1.0)
```
### Смешивание цветов
Теперь, когда вы знаете как задаются цвета, мы можем собрать все новые знания воедино. В GLSL есть очень полезная функция [`mix()`](../glossary/?search=mix), которая смешивает значения в указанной пропорции. Угадайте, как задаются пропорции? Конечно же, числом от 0.0 до 1.0! И это просто отлично, учитывая те долгие часы, что вы практиковали движения карате с забором. Самое время применить их на практике!

@ -13,7 +13,7 @@ red.y = 0.0;
red.z = 0.0;
```
Định nghĩa một màu sử dụng các ký hiệu *x*, *y**z* có thể hơi khó hiểu nhỉ ? Đó cũng chính là lý do mà ta sẽ có nhiều cách khác để truy cập dữ liệu trong vector. Các ký hiệu `x`, `y``z` có thể thay thế bằng `.r`, `.g`, `.b`, hoặc `.s`, `.t`, `.p`. (`.s`, `.t``.p` sẽ được sử dụng ở các chương sau để truy cập các toạ độ trong không gian texture). Ngoài ra bạn cũng có thể truy cập các giá trị trong vector bằng vị trí trong array (`[0]`, `[1]``[2]`).
Định nghĩa một màu sử dụng các ký hiệu *x*, *y**z* có thể hơi khó hiểu nhỉ? Đó cũng chính là lý do mà ta sẽ có nhiều cách khác để truy cập dữ liệu trong vector. Các ký hiệu `x`, `y``z` có thể thay thế bằng `.r`, `.g`, `.b`, hoặc `.s`, `.t`, `.p`. (`.s`, `.t``.p` sẽ được sử dụng ở các chương sau để truy cập các toạ độ trong không gian của texture). Ngoài ra bạn cũng có thể truy cập các giá trị trong vector bằng vị trí trong array (`[0]`, `[1]``[2]`).
Mỗi dòng code dưới đây đều truy cập một giá trị giống nhau trong vector:
@ -43,15 +43,6 @@ magenta = yellow.rbg; // Đảo vị trí của 2 kênh G và B
green.rgb = yellow.bgb; // Lấy giá trị ở kênh B của màu vàng để gán đồng thời cho cả kênh R và B của màu xanh lá
```
#### Tiện ích
Bạn có thể hiếm khi chọn màu bằng các con số vì nó không mấy trực quan, nhưng bắt buộc phải làm vậy trong GLSL. May thay, có rất nhiều tiện ích hỗ trợ thao tác này. Bạn có thể tuỳ ý lựa chọn tiện ích phù hợp nhất, miễn là kết quả trả về được lưu dưới dạng `vec3` hoặc `vec4`. Ví dụ, tôi sử dụng các template sau trên trang [Spectrum](http://www.eigenlogik.com/spectrum/mac):
```
vec3({{rn}},{{gn}},{{bn}})
vec4({{rn}},{{gn}},{{bn}},1.0)
```
### Trộn màu
Bạn đã biết cách định nghĩa các màu sắc rồi, giờ thì kết hợp nó với kiến thức đã có từ các chương trước nào. Trong GLSL có 1 hàm rất hữu ích, đó là [`mix()`](../glossary/?lan=vi&search=mix), giúp bạn trộn 2 màu với nhau theo 1 tỉ lệ nhất định. Và tỉ lệ đó cũng nằm trong khoảng [0.0, 1.0]. Hoàn hảo, đó chính là những gì mà ta đã học và luyện tập ở chương trước với việc sơn hàng rào, giờ thì lôi ra áp dụng thôi!
@ -64,7 +55,7 @@ Hãy xem đoạn code dưới đây và chú ý vào dòng 18 vì tôi sẽ sử
Thử xem bạn thuần thục môn võ karate-shader đến đâu rồi nào:
* Hãy tạo một vùng chuyển tiếp mượt mà giữa 2 màu xem sao. Hãy sử dụng nó để diễn tả một cảm giác nào đó nhé. Màu gì thì diễn tả cảm giác đó tốt nhất ? Nó xuất hiện rồi biến mất như thế nào ? Rồi lại thử với một cảm giác khác. Sửa code để đổi 2 màu được chọn để trộn phía trên xem sao.
* Hãy tạo một vùng chuyển tiếp mượt mà giữa 2 màu xem sao. Hãy sử dụng nó để diễn tả một cảm giác nào đó nhé. Màu gì thì diễn tả cảm giác đó tốt nhất? Nó xuất hiện rồi biến mất như thế nào? Rồi lại thử với một cảm giác khác. Sửa code để đổi 2 màu được chọn để trộn phía trên xem sao.
* Thay vì dùng hàm sin, hãy thử các hàm khác mà ta đã học ở chương trước xem sao
* Robert Penner đã phát triển một series các hàm số dùng trong animation rất nổi tiếng, chúng được gọi là các [easing functions](http://easings.net/), bạn có thể sử dụng [ví dụ này](../edit.php#06/easing.frag) để tham khảo và lấy cảm hứng nhưng tốt nhất là bạn tự tạo ra dải màu gradient của riêng mình.
@ -124,7 +115,7 @@ Hãy thử sửa code sao cho:
![Quang phổ tổng hợp và tách riêng tần số đỏ, vàng, xanh - William Home Lizars (1834)](spectrums.jpg)
* Nếu quan sát kỹ bánh xe màu được dùng để chọn màu (như hình dưới), bạn sẽ thấy các dải phổ của nó hơi khác một chút vì nó dùng không gian màu RYB. Ví dụ, màu ở vị trí đối diện với đỏ trên bánh xe là màu xanh lá, còn ở ví dụ trên thì ta lại thấy đó là màu xanh da trời (cyan). Bạn có thể sửa code để tạo ra bánh xe màu giống như hình này không ? (Gợi ý: hàm số)
* Nếu quan sát kỹ bánh xe màu được dùng để chọn màu (như hình dưới), bạn sẽ thấy các dải phổ của nó hơi khác một chút vì nó dùng không gian màu RYB. Ví dụ, màu ở vị trí đối diện với đỏ trên bánh xe là màu xanh lá, còn ở ví dụ trên thì ta lại thấy đó là màu xanh da trời (cyan). Bạn có thể sửa code để tạo ra bánh xe màu giống như hình này không? (Gợi ý: hàm số)
![](colorwheel.png)

@ -25,7 +25,7 @@ vector[2] = vector.b = vector.z = vector.p;
vector[3] = vector.a = vector.w = vector.q;
```
These different ways of pointing to the variables inside a vector are just nomenclatures designed to help you write clear code. This flexibility embedded in shading language is a door for you to start thinking interchangably about color and space coordinates.
These different ways of pointing to the variables inside a vector are just nomenclatures designed to help you write clear code. This flexibility embedded in shading language is a door for you to start thinking interchangeably about color and space coordinates.
Another great feature of vector types in GLSL is that the properties can be combined in any order you want, which makes it easy to cast and mix values. This ability is called *swizzle*.
@ -43,15 +43,6 @@ magenta = yellow.rbg; // Assign the channels with green and blue swapped
green.rgb = yellow.bgb; // Assign the blue channel of Yellow (0) to red and blue channels
```
#### For your toolbox
You might not be used to picking colors with numbers - it can be very counterintuitive. Lucky for you, there are a lot of smart programs that make this job easy. Find one that fits your needs and then train it to deliver colors in `vec3` or `vec4` format. For example, here are the templates I use on [Spectrum](http://www.eigenlogik.com/spectrum/mac):
```
vec3({{rn}},{{gn}},{{bn}})
vec4({{rn}},{{gn}},{{bn}},1.0)
```
### Mixing color
Now that you know how colors are defined, it's time to integrate this with our previous knowledge. In GLSL there is a very useful function, [`mix()`](../glossary/?search=mix), that lets you mix two values in percentages. Can you guess what the percentage range is? Yes, values between 0.0 and 1.0! Which is perfect for you, after those long hours practicing your karate moves with the fence - it is time to use them!

@ -44,7 +44,7 @@ void main(){
}
```
step函数会让每一个小于0.1的像素变成黑色vec30.0并将其余的变成白色vec31.0))。```left``` 乘 ```bottom``` 效果相当于逻辑 AND —— 当 x y 都为 1.0 时乘积才能是 1.0。这样做的效果就是画了两条黑线,一个在画布的底边另一个在左边。
step函数会让每一个小于0.1的像素变成黑色vec30.0并将其余的变成白色vec31.0))。```left``` 乘 ```bottom``` 效果相当于逻辑 AND —— 当 x y 都为 1.0 时乘积才能是 1.0。这样做的效果就是画了两条黑线,一个在画布的底边另一个在左边。
![](rect-01.jpg)
@ -136,7 +136,7 @@ There are several ways to calculate that distance. The easiest one uses the [```
* 反转前景色和背景色。
* 调戏下[```smoothstep()```](../glossary/?search=smoothstep)函数,用不同的值来试着做出一个边界顺滑的圆。
* 使用[```smoothstep()```](../glossary/?search=smoothstep)函数,通过修改不同的值来试着做出一个边界顺滑的圆。
* 一旦遇到令你满意的应用,把他写成一个函数,这样将来就可以调用了。

@ -5,6 +5,18 @@
precision mediump float;
#endif
// Copyright (c) Patricio Gonzalez Vivo, 2015 - http://patriciogonzalezvivo.com/
// I am the sole copyright owner of this Work.
//
// You cannot host, display, distribute or share this Work in any form,
// including physical and digital. You cannot use this Work in any
// commercial or non-commercial product, website or project. You cannot
// sell this Work and you cannot mint an NFTs of it.
// I share this Work for educational purposes, and you can link to it,
// through an URL, proper attribution and unmodified screenshot, as part
// of your educational material. If these conditions are too restrictive
// please contact me and we'll definitely work it out.
uniform vec2 u_resolution;
uniform vec2 u_mouse;
uniform float u_time;

@ -1,42 +0,0 @@
// Author @patriciogv - 2015
// http://patriciogonzalezvivo.com
// My own port of this processing code by @beesandbombs
// https://dribbble.com/shots/1696376-Circle-wave
#ifdef GL_ES
precision mediump float;
#endif
uniform vec2 u_resolution;
uniform vec2 u_mouse;
uniform float u_time;
mat2 rotate2d(float _angle){
return mat2(cos(_angle),-sin(_angle),
sin(_angle),cos(_angle));
}
float circleWave(vec2 st, float radius) {
st = vec2(0.5)-st;
float r = length(st)*2.0;
float a = atan(st.y,st.x);
float m = abs(mod(a+u_time*2.,3.14*2.)-3.14)/3.6;
float f = (cos(a*10.)*.1*pow(m,2.))+radius;
return 1.-smoothstep(f,f+0.007,r);
}
float circleWaveLine(vec2 st, float radius, float width) {
return circleWave(st,radius)-circleWave(st,radius-width);
}
void main() {
vec2 st = gl_FragCoord.xy/u_resolution.xy;
vec3 color = vec3(1.0) * circleWaveLine(st,0.8,0.02);
st -= vec2(0.5);
st = rotate2d(.314)*st;
st += vec2(0.5);
color = mix(color,vec3(1.0),circleWaveLine(st,0.8,0.02));
gl_FragColor = vec4( color, 1.0 );
}

@ -1,50 +0,0 @@
// Author @patriciogv - 2015
// http://patriciogonzalezvivo.com
// My own port of this processing code by @beesandbombs
// https://dribbble.com/shots/1698964-Circle-wave-II.
#ifdef GL_ES
precision mediump float;
#endif
uniform vec2 u_resolution;
uniform vec2 u_mouse;
uniform float u_time;
mat2 rotate2d(float _angle){
return mat2(cos(_angle),-sin(_angle),
sin(_angle),cos(_angle));
}
float circleWave(vec2 st, float radius) {
st = vec2(0.5)-st;
float r = length(st)*2.0;
float a = atan(st.y,st.x);
float m = abs(mod(a+u_time*2.,3.14*2.)-3.14)/3.6;
float f = cos(a*10.)*.1*pow(m,3.)+radius;
return 1.-smoothstep(f,f+0.007,r);
}
float circleWaveLine(vec2 st, float radius, float width) {
return circleWave(st,radius)-circleWave(st,radius-width);
}
void main() {
vec2 st = gl_FragCoord.xy/u_resolution.xy;
vec3 color = vec3(0.0);
float alpha = .8;
float size = .8;
float width = 0.03;
color += vec3(1.000,0.232,0.565) * circleWaveLine(st,size,width) * alpha;
st -= vec2(0.5);
st = rotate2d(1.004)*st;
st += vec2(0.5);
color += vec3(0.267,.850,0.308) * circleWaveLine(st,size,width) * alpha;
st -= vec2(0.5);
st = rotate2d(1.04)*st;
st += vec2(0.5);
color += vec3(0.489,0.630,1.000) * circleWaveLine(st,size,width) * alpha;
gl_FragColor = vec4( color, 1.0 );
}

@ -1,50 +0,0 @@
// Author @patriciogv ( patriciogonzalezvivo.com ) - 2015
#ifdef GL_ES
precision mediump float;
#endif
#define PI 3.14159265359
uniform vec2 u_resolution;
uniform float u_time;
mat2 rotate2d(float angle){
return mat2(cos(angle),-sin(angle),
sin(angle),cos(angle));
}
float boxDF(vec2 st, float size) {
st = st*2.-1.;
return length(max(abs(st)-size,.0));
}
float box(vec2 st, float size, float radio) {
radio = max(radio,.000001);
return 1.-step(radio,boxDF(st,size-radio));
}
float cross(vec2 st, float radio) {
float size = .25;
size *= (1.0-radio*2.);
return box(st,size,radio) +
box(st+vec2(.0,size*(1.0-radio*2.)),size,min(radio,size)) +
box(st+vec2(.0,-size*(1.0-radio*2.)),size,min(radio,size)) +
box(st+vec2(size*(1.0-radio*2.),.0),size,min(radio,size)) +
box(st+vec2(-size*(1.0-radio*2.),.0),size,min(radio,size));
}
void main(){
vec2 st = gl_FragCoord.xy/u_resolution.xy;
st.x *= u_resolution.x/u_resolution.y;
vec3 color = vec3(0.0);
st -= vec2(0.5);
st = rotate2d( sin(u_time)*PI ) * st;
st += vec2(0.5);
// Add the shape on the foreground
color += cross(st,(1.0-abs(sin(u_time)))*.5);
gl_FragColor = vec4(color,1.0);
}

@ -1,26 +0,0 @@
// Author @patriciogv ( patriciogonzalezvivo.com ) - 2015
#ifdef GL_ES
precision mediump float;
#endif
uniform vec2 u_resolution;
uniform float u_time;
float box(vec2 _st, vec2 _size){
_size = vec2(0.5) - _size*0.5;
vec2 uv = smoothstep(_size,
_size+vec2(0.0001),
_st);
uv *= smoothstep(_size,
_size+vec2(0.0001),
vec2(1.0)-_st);
return uv.x*uv.y;
}
void main(){
vec2 st = gl_FragCoord.xy/u_resolution.xy;
float pct = box(st, vec2(0.9,0.3)) + box(st, vec2(0.3,0.9));
gl_FragColor = vec4( vec3(1.-pct),pct );
}

@ -1,35 +0,0 @@
// Author @patriciogv - 2015
// http://patriciogonzalezvivo.com
#ifdef GL_ES
precision mediump float;
#endif
uniform vec2 u_resolution;
uniform vec2 u_mouse;
uniform float u_time;
mat2 rotate2d(float angle){
return mat2(cos(angle),-sin(angle),
sin(angle),cos(angle));
}
float stripes(vec2 st, float angle){
st = rotate2d(angle) * st*10.;
return 1.0-abs(sin(st.x*3.1415));
}
void main() {
vec2 st = gl_FragCoord.xy/u_resolution.xy;
vec3 color = vec3(.0);
vec2 pos = vec2(0.5)-st;
float t = u_time*.5;
float r = dot(pos,pos)*4.;
st *= 2.;
float pattern = sin(fract(r+t)*3.1415);
pattern = mix(stripes(st,-0.786375),stripes(st,0.786375),pattern);
gl_FragColor = vec4( vec3(smoothstep(.4,.5,pattern)), 1.0 );
}

@ -4,6 +4,18 @@
precision mediump float;
#endif
// Copyright (c) Patricio Gonzalez Vivo, 2015 - http://patriciogonzalezvivo.com/
// I am the sole copyright owner of this Work.
//
// You cannot host, display, distribute or share this Work in any form,
// including physical and digital. You cannot use this Work in any
// commercial or non-commercial product, website or project. You cannot
// sell this Work and you cannot mint an NFTs of it.
// I share this Work for educational purposes, and you can link to it,
// through an URL, proper attribution and unmodified screenshot, as part
// of your educational material. If these conditions are too restrictive
// please contact me and we'll definitely work it out.
uniform vec2 u_resolution;
uniform float u_time;

@ -4,6 +4,18 @@
precision mediump float;
#endif
// Copyright (c) Patricio Gonzalez Vivo, 2015 - http://patriciogonzalezvivo.com/
// I am the sole copyright owner of this Work.
//
// You cannot host, display, distribute or share this Work in any form,
// including physical and digital. You cannot use this Work in any
// commercial or non-commercial product, website or project. You cannot
// sell this Work and you cannot mint an NFTs of it.
// I share this Work for educational purposes, and you can link to it,
// through an URL, proper attribution and unmodified screenshot, as part
// of your educational material. If these conditions are too restrictive
// please contact me and we'll definitely work it out.
uniform vec2 u_resolution;
uniform vec2 u_mouse;
uniform float u_time;

@ -5,6 +5,18 @@
precision mediump float;
#endif
// Copyright (c) Patricio Gonzalez Vivo, 2015 - http://patriciogonzalezvivo.com/
// I am the sole copyright owner of this Work.
//
// You cannot host, display, distribute or share this Work in any form,
// including physical and digital. You cannot use this Work in any
// commercial or non-commercial product, website or project. You cannot
// sell this Work and you cannot mint an NFTs of it.
// I share this Work for educational purposes, and you can link to it,
// through an URL, proper attribution and unmodified screenshot, as part
// of your educational material. If these conditions are too restrictive
// please contact me and we'll definitely work it out.
uniform vec2 u_resolution;
uniform vec2 u_mouse;
uniform float u_time;

@ -5,6 +5,18 @@
precision mediump float;
#endif
// Copyright (c) Patricio Gonzalez Vivo, 2015 - http://patriciogonzalezvivo.com/
// I am the sole copyright owner of this Work.
//
// You cannot host, display, distribute or share this Work in any form,
// including physical and digital. You cannot use this Work in any
// commercial or non-commercial product, website or project. You cannot
// sell this Work and you cannot mint an NFTs of it.
// I share this Work for educational purposes, and you can link to it,
// through an URL, proper attribution and unmodified screenshot, as part
// of your educational material. If these conditions are too restrictive
// please contact me and we'll definitely work it out.
#define PI 3.14159265358979323846
uniform vec2 u_resolution;

@ -4,6 +4,18 @@
precision mediump float;
#endif
// Copyright (c) Patricio Gonzalez Vivo, 2015 - http://patriciogonzalezvivo.com/
// I am the sole copyright owner of this Work.
//
// You cannot host, display, distribute or share this Work in any form,
// including physical and digital. You cannot use this Work in any
// commercial or non-commercial product, website or project. You cannot
// sell this Work and you cannot mint an NFTs of it.
// I share this Work for educational purposes, and you can link to it,
// through an URL, proper attribution and unmodified screenshot, as part
// of your educational material. If these conditions are too restrictive
// please contact me and we'll definitely work it out.
uniform vec2 u_resolution;
uniform vec2 u_mouse;
uniform float u_time;

@ -4,6 +4,18 @@
precision mediump float;
#endif
// Copyright (c) Patricio Gonzalez Vivo, 2015 - http://patriciogonzalezvivo.com/
// I am the sole copyright owner of this Work.
//
// You cannot host, display, distribute or share this Work in any form,
// including physical and digital. You cannot use this Work in any
// commercial or non-commercial product, website or project. You cannot
// sell this Work and you cannot mint an NFTs of it.
// I share this Work for educational purposes, and you can link to it,
// through an URL, proper attribution and unmodified screenshot, as part
// of your educational material. If these conditions are too restrictive
// please contact me and we'll definitely work it out.
uniform vec2 u_resolution;
uniform vec2 u_mouse;
uniform float u_time;

@ -4,6 +4,18 @@
precision mediump float;
#endif
// Copyright (c) Patricio Gonzalez Vivo, 2015 - http://patriciogonzalezvivo.com/
// I am the sole copyright owner of this Work.
//
// You cannot host, display, distribute or share this Work in any form,
// including physical and digital. You cannot use this Work in any
// commercial or non-commercial product, website or project. You cannot
// sell this Work and you cannot mint an NFTs of it.
// I share this Work for educational purposes, and you can link to it,
// through an URL, proper attribution and unmodified screenshot, as part
// of your educational material. If these conditions are too restrictive
// please contact me and we'll definitely work it out.
uniform vec2 u_resolution;
uniform vec2 u_mouse;
uniform float u_time;

@ -4,6 +4,18 @@
precision mediump float;
#endif
// Copyright (c) Patricio Gonzalez Vivo, 2015 - http://patriciogonzalezvivo.com/
// I am the sole copyright owner of this Work.
//
// You cannot host, display, distribute or share this Work in any form,
// including physical and digital. You cannot use this Work in any
// commercial or non-commercial product, website or project. You cannot
// sell this Work and you cannot mint an NFTs of it.
// I share this Work for educational purposes, and you can link to it,
// through an URL, proper attribution and unmodified screenshot, as part
// of your educational material. If these conditions are too restrictive
// please contact me and we'll definitely work it out.
#define PI 3.14159265358979323846
uniform vec2 u_resolution;

@ -4,6 +4,18 @@
precision mediump float;
#endif
// Copyright (c) Patricio Gonzalez Vivo, 2015 - http://patriciogonzalezvivo.com/
// I am the sole copyright owner of this Work.
//
// You cannot host, display, distribute or share this Work in any form,
// including physical and digital. You cannot use this Work in any
// commercial or non-commercial product, website or project. You cannot
// sell this Work and you cannot mint an NFTs of it.
// I share this Work for educational purposes, and you can link to it,
// through an URL, proper attribution and unmodified screenshot, as part
// of your educational material. If these conditions are too restrictive
// please contact me and we'll definitely work it out.
#define PI 3.14159265358979323846
uniform vec2 u_resolution;

@ -5,6 +5,18 @@
precision mediump float;
#endif
// Copyright (c) Patricio Gonzalez Vivo, 2015 - http://patriciogonzalezvivo.com/
// I am the sole copyright owner of this Work.
//
// You cannot host, display, distribute or share this Work in any form,
// including physical and digital. You cannot use this Work in any
// commercial or non-commercial product, website or project. You cannot
// sell this Work and you cannot mint an NFTs of it.
// I share this Work for educational purposes, and you can link to it,
// through an URL, proper attribution and unmodified screenshot, as part
// of your educational material. If these conditions are too restrictive
// please contact me and we'll definitely work it out.
#define PI 3.14159265359
#define TWO_PI 6.28318530718

@ -4,6 +4,18 @@
precision mediump float;
#endif
// Copyright (c) Patricio Gonzalez Vivo, 2015 - http://patriciogonzalezvivo.com/
// I am the sole copyright owner of this Work.
//
// You cannot host, display, distribute or share this Work in any form,
// including physical and digital. You cannot use this Work in any
// commercial or non-commercial product, website or project. You cannot
// sell this Work and you cannot mint an NFTs of it.
// I share this Work for educational purposes, and you can link to it,
// through an URL, proper attribution and unmodified screenshot, as part
// of your educational material. If these conditions are too restrictive
// please contact me and we'll definitely work it out.
const float PI = 3.1415926535897932384626433832795;
uniform vec2 u_resolution;

@ -4,6 +4,18 @@
precision mediump float;
#endif
// Copyright (c) Patricio Gonzalez Vivo, 2015 - http://patriciogonzalezvivo.com/
// I am the sole copyright owner of this Work.
//
// You cannot host, display, distribute or share this Work in any form,
// including physical and digital. You cannot use this Work in any
// commercial or non-commercial product, website or project. You cannot
// sell this Work and you cannot mint an NFTs of it.
// I share this Work for educational purposes, and you can link to it,
// through an URL, proper attribution and unmodified screenshot, as part
// of your educational material. If these conditions are too restrictive
// please contact me and we'll definitely work it out.
#define PI 3.14159265358979323846
uniform vec2 u_resolution;

@ -4,6 +4,18 @@
precision mediump float;
#endif
// Copyright (c) Patricio Gonzalez Vivo, 2015 - http://patriciogonzalezvivo.com/
// I am the sole copyright owner of this Work.
//
// You cannot host, display, distribute or share this Work in any form,
// including physical and digital. You cannot use this Work in any
// commercial or non-commercial product, website or project. You cannot
// sell this Work and you cannot mint an NFTs of it.
// I share this Work for educational purposes, and you can link to it,
// through an URL, proper attribution and unmodified screenshot, as part
// of your educational material. If these conditions are too restrictive
// please contact me and we'll definitely work it out.
#define PI 3.14159265358979323846
uniform vec2 u_resolution;

@ -4,6 +4,18 @@
precision mediump float;
#endif
// Copyright (c) Patricio Gonzalez Vivo, 2015 - http://patriciogonzalezvivo.com/
// I am the sole copyright owner of this Work.
//
// You cannot host, display, distribute or share this Work in any form,
// including physical and digital. You cannot use this Work in any
// commercial or non-commercial product, website or project. You cannot
// sell this Work and you cannot mint an NFTs of it.
// I share this Work for educational purposes, and you can link to it,
// through an URL, proper attribution and unmodified screenshot, as part
// of your educational material. If these conditions are too restrictive
// please contact me and we'll definitely work it out.
#define PI 3.14159265358979323846
#define TWO_PI 6.28318530717958647693

@ -1,32 +0,0 @@
// Author @patriciogv ( patriciogonzalezvivo.com ) - 2015
#ifdef GL_ES
precision mediump float;
#endif
uniform vec2 u_resolution;
uniform vec2 u_mouse;
uniform float u_time;
vec2 tile(vec2 _st, float _zoom){
_st *= _zoom;
return fract(_st);
}
float circle(vec2 _st, float _radius){
vec2 pos = vec2(0.5)-_st;
_radius *= 0.75;
return 1.-smoothstep(_radius-(_radius*0.05),_radius+(_radius*0.05),dot(pos,pos)*3.14);
}
void main(){
vec2 st = gl_FragCoord.xy/u_resolution.xy;
st.x *= u_resolution.x/u_resolution.y;
float pct = 0.0;
vec2 st_i = floor(st*10.);
pct += abs(mod(st_i.x,2.)-mod(st_i.y,2.));
gl_FragColor = vec4(vec3(pct),1.0);
}

@ -1,45 +0,0 @@
// Author @patriciogv ( patriciogonzalezvivo.com ) - 2015
#ifdef GL_ES
precision mediump float;
#endif
uniform vec2 u_resolution;
uniform vec2 u_mouse;
uniform float u_time;
float rows = 10.0;
vec2 brickTile(vec2 _st, float _zoom){
_st *= _zoom;
if (fract(_st.y * 0.5) > 0.5){
_st.x += 0.5;
}
return fract(_st);
}
float circle(vec2 _st, float _radius){
vec2 pos = vec2(0.5)-_st;
_radius *= 0.75;
return 1.-smoothstep(_radius-(_radius*0.01),_radius+(_radius*0.01),dot(pos,pos)*3.14);
}
void main(){
vec2 st = gl_FragCoord.xy/u_resolution.xy;
st.x *= u_resolution.x/u_resolution.y;
vec2 pos = vec2(0.5)-st;
st = brickTile(st,20.);
float t = u_time*.5;
float r = dot(pos,pos)*4.;
st *= 2.;
float pattern = sin(fract(r+t)*3.1415);
vec3 color = vec3(circle(st, pattern));
gl_FragColor = vec4(color,1.0);
}

@ -1,47 +0,0 @@
// Author @patriciogv ( patriciogonzalezvivo.com ) - 2015
#ifdef GL_ES
precision mediump float;
#endif
uniform sampler2D u_tex0;
uniform vec2 u_resolution;
uniform vec2 u_mouse;
uniform float u_time;
float rows = 100.0;
vec2 brickTile(vec2 _st, float _zoom){
_st *= _zoom;
if (fract(_st.y * 0.5) > 0.5) {
_st.x += 0.5;
}
return fract(_st);
}
float circle(vec2 _st, float _radius){
vec2 pos = vec2(0.5)-_st;
_radius *= 0.75;
return 1.-smoothstep(_radius-(_radius*0.01),_radius+(_radius*0.01),dot(pos,pos)*3.14);
}
void main(){
vec2 st = gl_FragCoord.xy/u_resolution.xy;
st = (st-.5)*1.02+.5;
st.x *= u_resolution.x/u_resolution.y;
vec2 pos = st;
float grid = 50.;
st *= grid;
if (fract(st.y * 0.5) > 0.5){
st.x += 0.5;
pos.x += 0.5/grid;
}
float pattern = texture2D(u_tex0,clamp(floor(pos*grid)/grid+vec2(.5,.5)/grid,vec2(0.),vec2(1.))).r;
pattern = circle(fract(st), smoothstep(0.1,1.,pattern));
gl_FragColor = vec4(pattern,0.,0.,pattern);
}

@ -1,33 +0,0 @@
// Author @patriciogv ( patriciogonzalezvivo.com ) - 2015
#ifdef GL_ES
precision mediump float;
#endif
uniform vec2 u_resolution;
uniform vec2 u_mouse;
uniform float u_time;
vec2 tile(vec2 _st, float _zoom){
_st *= _zoom;
return fract(_st);
}
float circle(vec2 _st, float _radius){
vec2 pos = vec2(0.5)-_st;
_radius *= 0.75;
return 1.-smoothstep(_radius-(_radius*0.05),_radius+(_radius*0.05),dot(pos,pos)*3.14);
}
void main(){
vec2 st = gl_FragCoord.xy/u_resolution.xy;
st.x *= u_resolution.x/u_resolution.y;
st = tile(st,5.);
float size = .45;
float pct = circle(st,size);
st = abs(st-.5);
pct += circle(st,size);
gl_FragColor = vec4(vec3(pct),1.0);
}

@ -1,68 +0,0 @@
// Author @patriciogv ( patricio.io ) - 2015
// Inspired by the Patterns of Nina Warmerdam ( www.behance.net/ninawarmerdam )
#ifdef GL_OES_standard_derivatives
#extension GL_OES_standard_derivatives : enable
#endif
#ifdef GL_ES
precision mediump float;
#endif
uniform vec2 u_resolution;
uniform vec2 u_mouse;
uniform float u_time;
float aastep(float threshold, float value) {
#ifdef GL_OES_standard_derivatives
float afwidth = length(vec2(dFdx(value), dFdy(value))) * 0.70710678118654757;
return smoothstep(threshold-afwidth, threshold+afwidth, value);
#else
return step(threshold, value);
#endif
}
vec2 brickTile(vec2 st, float zoom){
st *= zoom;
if (fract(st.y * 0.5) > 0.5){
st.x += 0.5;
}
return fract(st);
}
float circleDF(vec2 st){
vec2 pos = vec2(0.5)-st;
return dot(pos,pos)*3.14;
}
float circle(vec2 st, float radius){
radius *= 0.75;
return 1.-aastep(radius,circleDF(st));
}
float dots(vec2 st, float size){
st = brickTile(st, 2.);
return circle(st, size);
}
float dotsDF(vec2 st){
st = brickTile(st, 2.);
return circleDF(st);
}
void main(){
vec2 st = gl_FragCoord.xy/u_resolution.xy;
st.x *= u_resolution.x/u_resolution.y;
vec3 color = vec3(0.0);
vec2 IN = st;
vec2 OUT = st*2.;
float pct = 1.0-fract(u_mouse.y/u_resolution.y);
pct = pow(pct,6.);
float d = 0.0;
// d = mix(dots(fract(IN),(1.-pct)), dots(fract(OUT),pct), pct);
// d = mix(dotsDF(fract(IN)), dotsDF(fract(OUT)), pct);
d = dotsDF(fract(IN))*(1.-pct) + dotsDF(fract(OUT))*pct;
d = aastep(.21,d);
color = vec3(d);
gl_FragColor = vec4(color,1.0);
}

@ -1,58 +0,0 @@
// Author @patriciogv ( patricio.io ) - 2015
// Inspired by the Patterns of Nina Warmerdam ( www.behance.net/ninawarmerdam )
#ifdef GL_OES_standard_derivatives
#extension GL_OES_standard_derivatives : enable
#endif
#ifdef GL_ES
precision mediump float;
#endif
uniform vec2 u_resolution;
uniform vec2 u_mouse;
uniform float u_time;
float aastep(float threshold, float value) {
#ifdef GL_OES_standard_derivatives
float afwidth = length(vec2(dFdx(value), dFdy(value))) * 0.70710678118654757;
return smoothstep(threshold-afwidth, threshold+afwidth, value);
#else
return step(threshold, value);
#endif
}
vec2 brickTile(vec2 st, float zoom){
st *= zoom;
if (fract(st.y * 0.5) > 0.5){
st.x += 0.5;
}
return fract(st);
}
float circleDF(vec2 st){
return dot(st,st);
}
void main(){
vec2 st = gl_FragCoord.xy/u_resolution.xy;
st.x *= u_resolution.x/u_resolution.y;
vec3 color = vec3(0.0);
vec2 IN = st;
vec2 OUT = st*2.;
float pct = 1.0-fract(u_mouse.y/u_resolution.y);
float A = circleDF(vec2(0.5)-st);
float B = circleDF(vec2(0.25)-st)*5.;
B = min(B, circleDF(vec2(0.75,0.25)-st)*5.);
B = min(B, circleDF(vec2(0.5,0.75)-st)*5.);
B = min(B, circleDF(vec2(0.,0.75)-st)*5.);
B = min(B, circleDF(vec2(1.,0.75)-st)*5.);
float d = 0.0;
d = mix(A,B,pct);
d = aastep(.21,d);
color = vec3(d);
gl_FragColor = vec4(color,1.0);
}

@ -1,30 +0,0 @@
// Author @patriciogv ( patriciogonzalezvivo.com ) - 2015
#ifdef GL_ES
precision mediump float;
#endif
uniform vec2 u_resolution;
uniform vec2 u_mouse;
uniform float u_time;
vec2 tile(vec2 _st, float _zoom){
_st *= _zoom;
return fract(_st);
}
float circle(vec2 _st, float _radius){
vec2 pos = vec2(0.5)-_st;
_radius *= 0.75;
return 1.-smoothstep(_radius-(_radius*0.05),_radius+(_radius*0.05),dot(pos,pos)*3.14);
}
void main(){
vec2 st = gl_FragCoord.xy/u_resolution.xy;
st.x *= u_resolution.x/u_resolution.y;
st = tile(st,5.);
vec3 color = vec3(circle(st, 0.2));
gl_FragColor = vec4(color,1.0);
}

@ -1,28 +0,0 @@
// Author @patriciogv - 2015 - patricio.io
#ifdef GL_ES
precision mediump float;
#endif
#define PI 3.14159265358979323846
uniform vec2 u_resolution;
uniform vec2 u_mouse;
uniform float u_time;
bool grid(vec2 _pos, float _res){
vec2 grid = fract(_pos*_res*250.);
return grid.x < _res || grid.y < _res;
}
void main(){
vec2 st = gl_FragCoord.xy/u_resolution.xy-vec2(.5);
st.x *= u_resolution.x/u_resolution.y;
vec3 color = vec3(0.0);
if(grid(st,0.01)) color += vec3(0.25);
if(grid(st,0.1)) color += vec3(0.15);
gl_FragColor = vec4(color,1.0);
}

@ -1,33 +0,0 @@
// Author @patriciogv ( patriciogonzalezvivo.com ) - 2015
#ifdef GL_ES
precision mediump float;
#endif
uniform vec2 u_resolution;
uniform float u_time;
vec2 tile(vec2 _st, float _zoom){
_st *= _zoom;
return fract(_st);
}
float X(vec2 _st, float _width){
float pct0 = smoothstep(_st.x-_width,_st.x,_st.y);
pct0 *= 1.-smoothstep(_st.x,_st.x+_width,_st.y);
float pct1 = smoothstep(_st.x-_width,_st.x,1.0-_st.y);
pct1 *= 1.-smoothstep(_st.x,_st.x+_width,1.0-_st.y);
return pct0+pct1;
}
void main(void){
vec2 st = gl_FragCoord.xy/u_resolution.xy;
st.y *= u_resolution.y/u_resolution.x;
vec2 xy = st-vec2(.5);
float grid = 1.0-X(tile(xy,10.+20.0*dot(xy,xy)),0.05);
gl_FragColor = vec4(vec3(grid),1.0);
}

@ -1,38 +0,0 @@
// Author @patriciogv - 2015 - patricio.io
#extension GL_OES_standard_derivatives : enable
#ifdef GL_ES
precision mediump float;
#endif
const float PI = 3.1415926535897932384626433832795;
uniform vec2 u_resolution;
uniform vec2 u_mouse;
uniform float u_time;
float aastep(float threshold, float value) {
#ifdef GL_OES_standard_derivatives
float afwidth = length(vec2(dFdx(value), dFdy(value))) * 0.70710678118654757;
return smoothstep(threshold-afwidth, threshold+afwidth, value);
#else
return step(threshold, value);
#endif
}
mat2 rotate2d(float angle){
return mat2(cos(angle),-sin(angle),
sin(angle),cos(angle));
}
float stripes(vec2 st){
st = rotate2d(.72)*st;
st *= 92.;
return aastep(.3,abs(sin(st.y*3.14159265358)));
}
void main(){
vec2 st = gl_FragCoord.xy/u_resolution.xy;
st.x *= u_resolution.x/u_resolution.y;
vec3 color = vec3(stripes(st));
gl_FragColor = vec4(color, 1.0);
}

@ -1,34 +0,0 @@
// Author @patriciogv - 2015 - patricio.io
#extension GL_OES_standard_derivatives : enable
#ifdef GL_ES
precision mediump float;
#endif
const float PI = 3.1415926535897932384626433832795;
uniform vec2 u_resolution;
uniform vec2 u_mouse;
uniform float u_time;
float aastep(float threshold, float value) {
#ifdef GL_OES_standard_derivatives
float afwidth = length(vec2(dFdx(value), dFdy(value))) * 0.70710678118654757;
return smoothstep(threshold-afwidth, threshold+afwidth, value);
#else
return step(threshold, value);
#endif
}
float stripes(vec2 st, float width){
return aastep(width,abs(sin(st.y*3.14159265358)));
}
void main(){
vec2 st = gl_FragCoord.xy/u_resolution.xy;
st.x *= u_resolution.x/u_resolution.y;
vec2 pos = st;
pos.y += sin(pos.x*30.)*.01;
vec3 color = vec3(stripes(pos*92.,.4));
gl_FragColor = vec4(color, 1.0);
}

@ -1,35 +0,0 @@
// Author @patriciogv - 2015 - patricio.io
#extension GL_OES_standard_derivatives : enable
#ifdef GL_ES
precision mediump float;
#endif
const float PI = 3.1415926535897932384626433832795;
uniform vec2 u_resolution;
uniform vec2 u_mouse;
uniform float u_time;
float aastep(float threshold, float value) {
#ifdef GL_OES_standard_derivatives
float afwidth = length(vec2(dFdx(value), dFdy(value))) * 0.70710678118654757;
return smoothstep(threshold-afwidth, threshold+afwidth, value);
#else
return step(threshold, value);
#endif
}
float stripes(vec2 st, float width){
return aastep(width,abs(sin(st.y*3.14159265358)));
}
void main(){
vec2 st = gl_FragCoord.xy/u_resolution.xy;
st.x *= u_resolution.x/u_resolution.y;
vec2 pos = fract(st*30.);
pos.y += mix(fract(pos.x),fract(1.0-pos.x),step(.5,pos.x))*3.;
vec3 color = vec3(stripes(pos,.3));
gl_FragColor = vec4(color, 1.0);
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 MiB

@ -1,41 +0,0 @@
// Author @patriciogv ( patriciogonzalezvivo.com ) - 2015
#ifdef GL_ES
precision mediump float;
#endif
uniform vec2 u_resolution;
uniform float u_time;
vec2 tile (vec2 st, float _zoom) {
st *= _zoom;
return fract(st);
}
vec2 seamlessTile(vec2 st){
st *= 2.0;
float index = 0.0;
index += step(1., mod(st.x,2.0));
index += step(1., mod(st.y,2.0))*2.0;
st = fract(st);
if(index == 1.0){
st.x = 1.0-st.x;
} else if(index == 2.0){
st.y = 1.0-st.y;
} else if(index == 3.0){
st = 1.0-st;
}
return st;
}
void main (void) {
vec2 st = gl_FragCoord.xy/u_resolution.xy;
st = tile(st,1.0);
st = seamlessTile(st);
// step(st.x,st.y) just makes a b&w triangles
// but you can use whatever design you want.
gl_FragColor = vec4(vec3(step(st.x,st.y)),1.0);
}

@ -5,6 +5,18 @@
precision mediump float;
#endif
// Copyright (c) Patricio Gonzalez Vivo, 2015 - http://patriciogonzalezvivo.com/
// I am the sole copyright owner of this Work.
//
// You cannot host, display, distribute or share this Work in any form,
// including physical and digital. You cannot use this Work in any
// commercial or non-commercial product, website or project. You cannot
// sell this Work and you cannot mint an NFTs of it.
// I share this Work for educational purposes, and you can link to it,
// through an URL, proper attribution and unmodified screenshot, as part
// of your educational material. If these conditions are too restrictive
// please contact me and we'll definitely work it out.
uniform vec2 u_resolution;
uniform vec2 u_mouse;
uniform float u_time;

@ -5,6 +5,18 @@
precision mediump float;
#endif
// Copyright (c) Patricio Gonzalez Vivo, 2015 - http://patriciogonzalezvivo.com/
// I am the sole copyright owner of this Work.
//
// You cannot host, display, distribute or share this Work in any form,
// including physical and digital. You cannot use this Work in any
// commercial or non-commercial product, website or project. You cannot
// sell this Work and you cannot mint an NFTs of it.
// I share this Work for educational purposes, and you can link to it,
// through an URL, proper attribution and unmodified screenshot, as part
// of your educational material. If these conditions are too restrictive
// please contact me and we'll definitely work it out.
#define PI 3.14159265359
#define TWO_PI 6.28318530718

@ -5,6 +5,18 @@
precision mediump float;
#endif
// Copyright (c) Patricio Gonzalez Vivo, 2015 - http://patriciogonzalezvivo.com/
// I am the sole copyright owner of this Work.
//
// You cannot host, display, distribute or share this Work in any form,
// including physical and digital. You cannot use this Work in any
// commercial or non-commercial product, website or project. You cannot
// sell this Work and you cannot mint an NFTs of it.
// I share this Work for educational purposes, and you can link to it,
// through an URL, proper attribution and unmodified screenshot, as part
// of your educational material. If these conditions are too restrictive
// please contact me and we'll definitely work it out.
uniform vec2 u_resolution;
uniform vec2 u_mouse;
uniform float u_time;

@ -1,36 +0,0 @@
// Author @patriciogv - 2015
// Title: Wave
#ifdef GL_ES
precision mediump float;
#endif
uniform vec2 u_resolution;
uniform vec2 u_mouse;
uniform float u_time;
float random (in float x) { return fract(sin(x)*1e4); }
float random (in vec2 st) { return fract(sin(dot(st.xy, vec2(12.9898,78.233)))* 43758.5453123); }
void main() {
vec2 st = gl_FragCoord.xy/u_resolution.xy;
st.x *= u_resolution.x/u_resolution.y;
vec3 color = vec3(0.0);
vec2 grid = vec2(100.0,2.0);
float t = u_time*max(grid.x,grid.y);
vec2 ipos = floor(st*grid);
vec2 fpos = fract(st*grid);
float value = random(floor(ipos.x+t));
if (mod(ipos.y,2.) == 0.) {
fpos = 1.0-fpos;
}
color += step(fpos.y*1.5,value);
gl_FragColor = vec4(color,1.0);
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

@ -1,40 +0,0 @@
// Author @patriciogv - 2015
// Title: DeFrag
#ifdef GL_ES
precision mediump float;
#endif
uniform vec2 u_resolution;
uniform vec2 u_mouse;
uniform float u_time;
float random (in float x) { return fract(sin(x)*1e4); }
float random (in vec2 _st) { return fract(sin(dot(_st.xy, vec2(12.9898,78.233)))* 43758.5453123);}
void main() {
vec2 st = gl_FragCoord.xy/u_resolution.xy;
st.x *= u_resolution.x/u_resolution.y;
st *= vec2(100.0,50.);
vec2 ipos = floor(st); // integer
vec2 fpos = fract(st); // fraction
vec2 vel = floor(vec2(u_time*10.)); // time
vel *= vec2(-1.,0.); // direction
vel *= (step(1., mod(ipos.y,2.0))-0.5)*2.; // Oposite directions
vel *= random(ipos.y); // random speed
// Move
ipos += floor(vel);
// Assign a random value base on the integer coord
float pct = 1.0;
pct *= random(ipos);
pct *= step(.1,fpos.x)*step(.1,fpos.y); // margin
pct = step(0.001+u_mouse.x/u_resolution.x,pct); // threshold
gl_FragColor = vec4(vec3(pct),1.0);
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 217 B

@ -5,6 +5,18 @@
precision mediump float;
#endif
// Copyright (c) Patricio Gonzalez Vivo, 2015 - http://patriciogonzalezvivo.com/
// I am the sole copyright owner of this Work.
//
// You cannot host, display, distribute or share this Work in any form,
// including physical and digital. You cannot use this Work in any
// commercial or non-commercial product, website or project. You cannot
// sell this Work and you cannot mint an NFTs of it.
// I share this Work for educational purposes, and you can link to it,
// through an URL, proper attribution and unmodified screenshot, as part
// of your educational material. If these conditions are too restrictive
// please contact me and we'll definitely work it out.
uniform vec2 u_resolution;
uniform vec2 u_mouse;
uniform float u_time;

@ -5,6 +5,18 @@
precision mediump float;
#endif
// Copyright (c) Patricio Gonzalez Vivo, 2015 - http://patriciogonzalezvivo.com/
// I am the sole copyright owner of this Work.
//
// You cannot host, display, distribute or share this Work in any form,
// including physical and digital. You cannot use this Work in any
// commercial or non-commercial product, website or project. You cannot
// sell this Work and you cannot mint an NFTs of it.
// I share this Work for educational purposes, and you can link to it,
// through an URL, proper attribution and unmodified screenshot, as part
// of your educational material. If these conditions are too restrictive
// please contact me and we'll definitely work it out.
uniform vec2 u_resolution;
uniform vec2 u_mouse;
uniform float u_time;

@ -5,6 +5,18 @@
precision mediump float;
#endif
// Copyright (c) Patricio Gonzalez Vivo, 2015 - http://patriciogonzalezvivo.com/
// I am the sole copyright owner of this Work.
//
// You cannot host, display, distribute or share this Work in any form,
// including physical and digital. You cannot use this Work in any
// commercial or non-commercial product, website or project. You cannot
// sell this Work and you cannot mint an NFTs of it.
// I share this Work for educational purposes, and you can link to it,
// through an URL, proper attribution and unmodified screenshot, as part
// of your educational material. If these conditions are too restrictive
// please contact me and we'll definitely work it out.
uniform vec2 u_resolution;
uniform float u_time;

@ -5,6 +5,18 @@
precision mediump float;
#endif
// Copyright (c) Patricio Gonzalez Vivo, 2015 - http://patriciogonzalezvivo.com/
// I am the sole copyright owner of this Work.
//
// You cannot host, display, distribute or share this Work in any form,
// including physical and digital. You cannot use this Work in any
// commercial or non-commercial product, website or project. You cannot
// sell this Work and you cannot mint an NFTs of it.
// I share this Work for educational purposes, and you can link to it,
// through an URL, proper attribution and unmodified screenshot, as part
// of your educational material. If these conditions are too restrictive
// please contact me and we'll definitely work it out.
uniform vec2 u_resolution;
uniform float u_time;

@ -5,6 +5,18 @@
precision mediump float;
#endif
// Copyright (c) Patricio Gonzalez Vivo, 2015 - http://patriciogonzalezvivo.com/
// I am the sole copyright owner of this Work.
//
// You cannot host, display, distribute or share this Work in any form,
// including physical and digital. You cannot use this Work in any
// commercial or non-commercial product, website or project. You cannot
// sell this Work and you cannot mint an NFTs of it.
// I share this Work for educational purposes, and you can link to it,
// through an URL, proper attribution and unmodified screenshot, as part
// of your educational material. If these conditions are too restrictive
// please contact me and we'll definitely work it out.
uniform vec2 u_resolution;
uniform float u_time;

@ -5,6 +5,18 @@
precision mediump float;
#endif
// Copyright (c) Patricio Gonzalez Vivo, 2015 - http://patriciogonzalezvivo.com/
// I am the sole copyright owner of this Work.
//
// You cannot host, display, distribute or share this Work in any form,
// including physical and digital. You cannot use this Work in any
// commercial or non-commercial product, website or project. You cannot
// sell this Work and you cannot mint an NFTs of it.
// I share this Work for educational purposes, and you can link to it,
// through an URL, proper attribution and unmodified screenshot, as part
// of your educational material. If these conditions are too restrictive
// please contact me and we'll definitely work it out.
uniform vec2 u_resolution;
uniform float u_time;

Binary file not shown.

Before

Width:  |  Height:  |  Size: 807 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 138 B

@ -1,156 +0,0 @@
// Author @patriciogv - 2015
// http://patriciogonzalezvivo.com
#ifdef GL_ES
precision mediump float;
#endif
uniform vec2 u_resolution;
uniform float u_time;
float random (in float x) { return fract(sin(x)*1e4);}
float random (in vec2 st) { return fract(1e4 * sin(17.0 * st.x + st.y * 0.1) * (0.1 + abs(sin(st.y * 13.0 + st.x)))); }
float binChar (vec2 ipos, float n) {
float remain = mod(n,33554432.);
for (float i = 0.0; i < 15.0; i++) {
if ( floor(i/3.) == ipos.y && mod(i,3.) == ipos.x ) {
return step(1.0,mod(remain,2.));
}
remain = ceil(remain/2.);
}
return 0.0;
}
float char (vec2 st, float n) {
st.x = st.x*2.-0.5;
st.y = st.y*1.2-0.1;
vec2 grid = vec2(3.,5.);
vec2 ipos = floor(st*grid);
vec2 fpos = fract(st*grid);
n = floor(mod(n,10.));
float digit = 0.0;
if (n < 1. ) { digit = 31600.; }
else if (n < 2. ) { digit = 9363.0; }
else if (n < 3. ) { digit = 31184.0; }
else if (n < 4. ) { digit = 31208.0; }
else if (n < 5. ) { digit = 23525.0; }
else if (n < 6. ) { digit = 29672.0; }
else if (n < 7. ) { digit = 29680.0; }
else if (n < 8. ) { digit = 31013.0; }
else if (n < 9. ) { digit = 31728.0; }
else if (n < 10. ) { digit = 31717.0; }
float pct = binChar(ipos, digit);
vec2 borders = vec2(1.);
// borders *= step(0.01,fpos.x) * step(0.01,fpos.y); // inner
borders *= step(0.0,st)*step(0.0,1.-st); // outer
return step(.5,1.0-pct) * borders.x * borders.y;
}
float binBar (vec2 ipos, float n) {
float remain = mod(n,128.);
for(float i = 0.0; i < 8.0; i++){
if ( mod(i,10.) == ipos.x ) {
return step(1.0,mod(remain,2.));
}
remain = ceil(remain/2.);
}
return 0.0;
}
// Standard UPC-E Barcode reference from
// https://en.wikipedia.org/wiki/Universal_Product_Code
float bar (vec2 st, float n, bool L) {
vec2 grid = vec2(7.,1.);
if (L) { st = 1.0-st; }
vec2 ipos = floor(st*grid);
vec2 fpos = fract(st*grid);
n = floor(mod(n,10.));
float digit = 0.0;
if (n < 1. ) { digit = 114.; }
else if (n < 2. ) { digit = 102.0; }
else if (n < 3. ) { digit = 108.0; }
else if (n < 4. ) { digit = 66.0; }
else if (n < 5. ) { digit = 92.0; }
else if (n < 6. ) { digit = 78.0; }
else if (n < 7. ) { digit = 80.0; }
else if (n < 8. ) { digit = 68.0; }
else if (n < 9. ) { digit = 72.0; }
else if (n < 10. ) { digit = 116.0; }
float pct = binBar(ipos, digit+1.);
if (L) { pct = 1.-pct; }
return step(.5,pct);
}
float bar (vec2 st, float n) {
return bar(st,n,true);
}
float barStart (vec2 st) {
vec2 grid = vec2(7.,1.);
vec2 ipos = floor((1.0-st)*grid);
float digit = 122.0;
float pct = binBar(ipos, digit+1.);
return step(.5,1.0-pct);
}
float barEnd(vec2 st) {
vec2 grid = vec2(7.,1.);
vec2 ipos = floor((1.0-st)*grid);
float digit = 85.0;
float pct = binBar(ipos, digit+1.);
return step(.5,1.0-pct);
}
float barCode(vec2 st, float rows, float value) {
rows = ceil(rows);
vec2 ipos = floor(st*rows);
vec2 fpos = fract(st*rows);
value = value*pow(10.,ipos.x)*0.0000000001+0.1;
if (ipos.x == 0.0 ) {
return barStart(fpos);
} else if (ipos.x == rows-1.) {
return barEnd(fpos);
} else {
if (ipos.y == 0.0) {
return 1.0-char(fpos,value);
} else {
return bar(fpos,value);
}
}
}
void main(){
vec2 st = gl_FragCoord.st/u_resolution.xy;
st *= 3.;
vec2 ipos = floor(st);
vec2 fpos = fract(st);
fpos.y *= u_resolution.y/u_resolution.x;
vec3 color = vec3(0.0);
if (ipos.x == 1. && ipos.y == 1.) {
float value = 0.0;
// value = 123456789.0;
value += floor(u_time);
value = random(floor(u_time*10.))*1000000000.;
color += barCode(fpos,12.,value);
} else {
color += 1.;
}
gl_FragColor = vec4( color , 1.0);
}

@ -1,69 +0,0 @@
// Author @patriciogv - 2015
// http://patriciogonzalezvivo.com
#ifdef GL_ES
precision mediump float;
#endif
uniform vec2 u_resolution;
uniform float u_time;
float random (in float x) { return fract(sin(x)*1e4);}
float random (in vec2 st){ return fract(sin(dot(st.xy ,vec2(12.9898,78.233))) * 43758.5453); }
float bin(vec2 ipos, float n){
float remain = mod(n,33554432.);
for(float i = 0.0; i < 25.0; i++){
if ( floor(i/3.) == ipos.y && mod(i,3.) == ipos.x ) {
return step(1.0,mod(remain,2.));
}
remain = ceil(remain/2.);
}
return 0.0;
}
float char(vec2 st, float n){
st.x = st.x*2.-0.5;
st.y = st.y*1.2-0.1;
vec2 grid = vec2(3.,5.);
vec2 ipos = floor(st*grid);
vec2 fpos = fract(st*grid);
n = floor(mod(n,10.));
float digit = 0.0;
if (n < 1. ) { digit = 31600.; }
else if (n < 2. ) { digit = 9363.0; }
else if (n < 3. ) { digit = 31184.0; }
else if (n < 4. ) { digit = 31208.0; }
else if (n < 5. ) { digit = 23525.0; }
else if (n < 6. ) { digit = 29672.0; }
else if (n < 7. ) { digit = 29680.0; }
else if (n < 8. ) { digit = 31013.0; }
else if (n < 9. ) { digit = 31728.0; }
else if (n < 10. ) { digit = 31717.0; }
float pct = bin(ipos, digit);
vec2 borders = vec2(1.);
// borders *= step(0.01,fpos.x) * step(0.01,fpos.y); // inner
borders *= step(0.0,st)*step(0.0,1.-st); // outer
return step(.5,1.0-pct) * borders.x * borders.y;
}
void main(){
vec2 st = gl_FragCoord.st/u_resolution.xy;
st.x *= u_resolution.x/u_resolution.y;
float rows = 34.0;
vec2 ipos = floor(st*rows);
vec2 fpos = fract(st*rows);
ipos += vec2(0.,floor(u_time*20.*random(ipos.x+1.)));
float pct = random(ipos);
vec3 color = vec3(char(fpos,100.*pct));
color = mix(color,vec3(color.r,0.,0.),step(.99,pct));
gl_FragColor = vec4( color , 1.0);
}

@ -1,13 +0,0 @@
#!/bin/bash
SHADER=$1
SEC=$1
COUNTER=0
for i in `seq -w 0.01 .031 $SEC`; do
echo $i
`glslViewer $SHADER -s $i -o frame-$COUNTER.png`
let COUNTER=COUNTER+1
done
convert -delay 3.5 -loop 1 frame-*.png animated.gif

@ -1,42 +0,0 @@
// Author @patriciogv - 2015
// http://patriciogonzalezvivo.com
#ifdef GL_ES
precision mediump float;
#endif
uniform vec2 u_resolution;
uniform vec2 u_mouse;
uniform float u_time;
float random (in float x) { return fract(sin(x)*1e4); }
float noise (in float x) {
float i = floor(x);
float f = fract(x);
float u = f * f * (3.0 - 2.0 * f);
return mix(random(i), random(i + 1.0), u);
}
void main() {
vec2 st = gl_FragCoord.xy/u_resolution.xy;
st.x *= u_resolution.x/u_resolution.y;
vec3 color = vec3(0.0);
vec2 grid = vec2(20.0,2.0);
float t = u_time*max(grid.x,grid.y)*.5;
vec2 ipos = floor(st*grid);
vec2 fpos = fract(st*grid);
float offset = ipos.x+floor(t);
float value = pow(noise(offset*0.2),2.)+noise(offset*0.9)*.5;
if (mod(ipos.y,2.) == 0.) {
fpos.y = 1.0-fpos.y;
}
color += step(fpos.y*1.5,value)*step(.5,fpos.x);
gl_FragColor = vec4(color,1.0);
}

@ -1,49 +0,0 @@
// Author @patriciogv - 2015
// http://patriciogonzalezvivo.com
#ifdef GL_ES
precision mediump float;
#endif
uniform vec2 u_resolution;
uniform vec2 u_mouse;
uniform float u_time;
float random (in float x) { return fract(sin(x)*1e4);}
float random (in vec2 st) { return fract(1e4 * sin(17.0 * st.x + st.y * 0.1) * (0.1 + abs(sin(st.y * 13.0 + st.x)))); }
float pattern(vec2 st, vec2 v, float t) {
vec2 p = floor(st+v);
return step(t, random(100.+p*.000001)+random(p.x)*0.5 );
}
void main() {
vec2 st = gl_FragCoord.xy/u_resolution.xy;
if (u_resolution.x>u_resolution.y) {
st.x *= u_resolution.x/u_resolution.y;
} else {
st.y *= u_resolution.y/u_resolution.x;
}
vec2 grid = vec2(100.0,50.);
st *= grid;
vec2 ipos = floor(st); // integer
vec2 fpos = fract(st); // fraction
vec2 vel = vec2(u_time*2.*max(grid.x,grid.y)); // time
vel *= vec2(-1.,0.0) * random(1.0+ipos.y); // direction
// Assign a random value base on the integer coord
vec2 offset = vec2(0.3,0.);
float pct = 0.5;//u_mouse.x/u_resolution.x;
vec3 color = vec3(0.);
color.r = pattern(st+offset,vel,0.5+pct);
color.g = pattern(st,vel,0.5+pct);
color.b = pattern(st-offset,vel,0.5+pct);
// Margins
color *= step(0.2,fpos.y);
gl_FragColor = vec4(color,1.0);
}

@ -1,55 +0,0 @@
// Author @patriciogv - 2015
// http://patriciogonzalezvivo.com
#ifdef GL_ES
precision mediump float;
#endif
uniform vec2 u_resolution;
uniform vec2 u_mouse;
uniform float u_time;
float random (in float x) { return fract(sin(x)*1e4); }
float random (in vec2 _st) { return fract(sin(dot(_st.xy, vec2(12.9898,78.233)))* 43758.5453123);}
void main() {
vec2 st = gl_FragCoord.xy/u_resolution.xy;
st.x *= u_resolution.x/u_resolution.y;
// Grid
vec2 grid = vec2(100.0,50.);
st *= grid;
vec2 ipos = floor(st); // integer
vec2 vel = floor(vec2(u_time*10.)); // time
vel *= vec2(-1.,0.); // direction
vel *= (step(1., mod(ipos.y,2.0))-0.5)*2.; // Oposite directions
vel *= random(ipos.y); // random speed
// 100%
float totalCells = grid.x*grid.y;
float t = mod(u_time*max(grid.x,grid.y)+floor(1.0+u_time*u_mouse.y),totalCells);
vec2 head = vec2(mod(t,grid.x), floor(t/grid.x));
vec2 offset = vec2(0.1,0.);
vec3 color = vec3(1.0);
color *= step(grid.y-head.y,ipos.y); // Y
color += (1.0-step(head.x,ipos.x))*step(grid.y-head.y,ipos.y+1.); // X
color = clamp(color,vec3(0.),vec3(1.));
// Assign a random value base on the integer coord
color.r *= random(floor(st+vel+offset));
color.g *= random(floor(st+vel));
color.b *= random(floor(st+vel-offset));
color = smoothstep(0.,.5+u_mouse.x/u_resolution.x*.5,color*color); // smooth
color = step(0.5+u_mouse.x/u_resolution.x*0.5,color); // threshold
// Margin
color *= step(.1,fract(st.x+vel.x))*step(.1,fract(st.y+vel.y));
gl_FragColor = vec4(color,1.0);
}

@ -1,71 +0,0 @@
// Author @patriciogv - 2015
// http://patriciogonzalezvivo.com
#ifdef GL_ES
precision mediump float;
#endif
uniform sampler2D u_tex;
uniform vec2 u_resolution;
uniform float u_time;
float random(in float x){ return fract(sin(x)*43758.5453); }
float random(in vec2 st){ return fract(sin(dot(st.xy ,vec2(12.9898,78.233))) * 43758.5453); }
float noise(in vec2 x) {
vec2 i = floor(x);
vec2 f = fract(x);
float a = random(i);
float b = random(i + vec2(1.0, 0.0));
float c = random(i + vec2(0.0, 1.0));
float d = random(i + vec2(1.0, 1.0));
vec2 u = f * f * (3.0 - 2.0 * f);
return mix(a, b, u.x) + (c - a) * u.y * (1.0 - u.x) + (d - b) * u.x * u.y;
}
float fbm( in vec2 p ){
float s = 0.0;
float m = 0.0;
float a = 0.5;
for(int i=0; i<2; i++ ){
s += a * noise(p);
m += a;
a *= 0.5;
p *= 2.0;
}
return s/m;
}
void main(){
vec2 st = gl_FragCoord.st/u_resolution.xy;
float aspect = u_resolution.x/u_resolution.y;
vec2 grain_st = st-.5;
float grain = 0.0;
grain = mix(1., 0.9, dot(grain_st,grain_st) + (fbm(gl_FragCoord.xy*0.6)*0.1) );
// Random blocks
vec2 blocks_st = floor(st*vec2(5.*random(floor(u_time*10.)),10.*(1.+random(floor(u_time*3.))) ));
float t = u_time*2.+random(blocks_st);
float time_i = floor(t);
float time_f = fract(t);
float block = step(0.9,random(blocks_st+time_i))*(1.0-time_f);
vec2 offset = vec2(block*0.01,block*0.005)+(1.0-grain)*.08;
vec4 color = vec4(1.);
color.r = texture2D(u_tex,st+offset).r;
color.g = texture2D(u_tex,st).r;
color.b = texture2D(u_tex,st-offset).r;
color.a = max(texture2D(u_tex,st+offset).a,max(texture2D(u_tex,st).a, texture2D(u_tex,st-offset).a));
if (block > .5) {
color.rgb = abs(block*grain-color.rgb);
}
color.rgb *= 0.4+sin((st.y*3.1415+u_time)*500.);
gl_FragColor = color;
}

@ -1,48 +0,0 @@
// Author @patriciogv - 2015
// http://patriciogonzalezvivo.com
#ifdef GL_ES
precision mediump float;
#endif
uniform vec2 u_resolution;
uniform float u_time;
float random(in float x){ return fract(sin(x)*43758.5453); }
float random(in vec2 st){ return fract(sin(dot(st.xy ,vec2(12.9898,78.233))) * 43758.5453); }
float randomChar(vec2 outer,vec2 inner){
float grid = 5.;
vec2 margin = vec2(.2,.05);
vec2 borders = step(margin,inner)*step(margin,1.-inner);
vec2 ipos = floor(inner*grid);
vec2 fpos = fract(inner*grid);
return step(.5,random(outer*64.+ipos)) * borders.x * borders.y * step(0.01,fpos.x) * step(0.01,fpos.y);
}
void main(){
vec2 st = gl_FragCoord.st/u_resolution.xy;
if (u_resolution.x > u_resolution.y) {
st.x *= u_resolution.x/u_resolution.y;
} else {
st.y *= u_resolution.y/u_resolution.y;
}
vec3 color = vec3(0.0);
float rows = 1.0;
// rows = 3.0;
rows = 12.0;
//rows = 24.0;
vec2 ipos = floor(st*rows);
vec2 fpos = fract(st*rows);
ipos += vec2(0.,floor(u_time*20.*random(ipos.x+1.)));
float pct = 1.0;
pct *= randomChar(ipos,fpos);
// pct *= random(ipos);
color = vec3(pct);
gl_FragColor = vec4( color , 1.0);
}

@ -1,178 +0,0 @@
// Author @patriciogv - 2015
// http://patriciogonzalezvivo.com
#ifdef GL_ES
precision mediump float;
#endif
uniform vec2 u_resolution;
uniform float u_time;
float random(in float x){ return fract(sin(x)*43758.5453); }
float random(in vec2 st){ return fract(sin(dot(st.xy ,vec2(12.9898,78.233))) * 43758.5453); }
float noise(in vec2 x) {
vec2 i = floor(x);
vec2 f = fract(x);
float a = random(i);
float b = random(i + vec2(1.0, 0.0));
float c = random(i + vec2(0.0, 1.0));
float d = random(i + vec2(1.0, 1.0));
vec2 u = f * f * (3.0 - 2.0 * f);
return mix(a, b, u.x) + (c - a) * u.y * (1.0 - u.x) + (d - b) * u.x * u.y;
}
float fbm( in vec2 p ){
float s = 0.0;
float m = 0.0;
float a = 0.5;
for(int i=0; i<2; i++ ){
s += a * noise(p);
m += a;
a *= 0.5;
p *= 2.0;
}
return s/m;
}
float bin(vec2 ipos, float n){
float remain = mod(n,33554432.);
for(float i = 0.0; i < 25.0; i++){
if ( floor(i/3.) == ipos.y && mod(i,3.) == ipos.x ) {
return step(1.0,mod(remain,2.));
}
remain = ceil(remain/2.);
}
return 0.0;
}
float char(vec2 st, float n){
st.x = st.x*2.-0.5;
st.y = st.y*1.2-0.1;
vec2 grid = vec2(3.,5.);
vec2 ipos = floor(st*grid);
vec2 fpos = fract(st*grid);
n = floor(mod(n,10.));
float digit = 0.0;
if (n < 1. ) { digit = 31600.; }
else if (n < 2. ) { digit = 9363.0; }
else if (n < 3. ) { digit = 31184.0; }
else if (n < 4. ) { digit = 31208.0; }
else if (n < 5. ) { digit = 23525.0; }
else if (n < 6. ) { digit = 29672.0; }
else if (n < 7. ) { digit = 29680.0; }
else if (n < 8. ) { digit = 31013.0; }
else if (n < 9. ) { digit = 31728.0; }
else if (n < 10. ) { digit = 31717.0; }
float pct = bin(ipos, digit);
vec2 borders = vec2(1.);
// borders *= step(0.01,fpos.x) * step(0.01,fpos.y); // inner
borders *= step(0.0,st)*step(0.0,1.-st); // outer
return step(.5,1.0-pct) * borders.x * borders.y;
}
float grid(vec2 st, float res) {
vec2 grid = fract(st*res);
return 1.-(step(res,grid.x) * step(res,grid.y));
}
float superGrid(vec2 st) {
return 1.*grid(st,0.01) +
0.5*grid(st,0.02) +
0.6*grid(st,0.1);
}
float box(in vec2 st, in vec2 size){
size = vec2(0.5) - size*0.5;
vec2 uv = smoothstep(size,
size+vec2(0.001),
st);
uv *= smoothstep(size,
size+vec2(0.001),
vec2(1.0)-st);
return uv.x*uv.y;
}
float cross(in vec2 st, vec2 size){
return clamp(box(st, vec2(size.x*0.5,size.y*0.125)) +
box(st, vec2(size.y*0.125,size.x*0.5)),0.,1.);
}
void main(){
vec2 st = gl_FragCoord.st/u_resolution.xy;
float aspect = u_resolution.x/u_resolution.y;
vec2 grain_st = st-.5;
vec3 color = vec3(0.0);
float grain = 0.0;
grain = mix(1., 0.8, dot(grain_st,grain_st) + (fbm(gl_FragCoord.xy*0.6)*0.1) );
// Fix Aspect ration
st -= .5;
st.x *= aspect;
// Zoom
st *= 2.8;
// Random blocks
vec2 blocks_st = floor((st-.25)*6.);
float t = u_time*.3+random(blocks_st);
float time_i = floor(t);
float time_f = fract(t);
float block = step(0.9,random(blocks_st+time_i))*(1.0-time_f);
vec2 offset = vec2(block*0.02,block*0.001)+(1.0-grain)*.08;
// Grid
vec2 grid_st = st*300.;
vec3 grid_chroma = vec3(0.0);
grid_chroma.r = superGrid(grid_st+offset*100.);
grid_chroma.g = superGrid(grid_st);
grid_chroma.b = superGrid(grid_st-offset*100.);
color += vec3(0.1,0.08,0.08)*grid_chroma;
// Crosses
vec2 crosses_st = st + .5;
crosses_st *= 3.;
vec2 crosses_st_f = fract(crosses_st);
color *= 1.-cross(crosses_st_f,vec2(.2,.2));
vec3 cross_chroma = vec3(0.0);
cross_chroma.r = cross(crosses_st_f+offset,vec2(.15,.15));
cross_chroma.g = cross(crosses_st_f,vec2(.15,.15));
cross_chroma.b = cross(crosses_st_f-offset,vec2(.15,.15));
color += vec3(.7)*cross_chroma;
// Digits
vec2 digits_st = mod(st*60.,20.);
vec2 digits_st_i = floor(digits_st);
float digits_n = ceil(block*5.);
offset *= 10.;
if (block > 0.0 &&
digits_st_i.y == 1. &&
digits_st_i.x > 0. && digits_st_i.x < digits_n ) {
vec2 digits_st_f = fract(digits_st);
float pct = random(digits_st_i+floor(crosses_st)+floor(u_time*20.));
color.r += block*char(digits_st_f+offset,100.*pct);
color.g += block*char(digits_st_f,100.*pct);
color.b += block*char(digits_st_f-offset,100.*pct);
} else if ( block > 0.0 &&
digits_st_i.y == 2. &&
digits_st_i.x > 0. && digits_st_i.x < digits_n ) {
vec2 digits_st_f = fract(digits_st);
float pct = random(digits_st_i+floor(crosses_st)+floor(u_time*20.));
color.r += block*char(digits_st_f+offset,100.*pct);
color.g += block*char(digits_st_f,100.*pct);
color.b += block*char(digits_st_f-offset,100.*pct);
}
gl_FragColor = vec4( (1.0-color) * grain, 1.0);
}

@ -4,6 +4,18 @@
precision mediump float;
#endif
// Copyright (c) Patricio Gonzalez Vivo, 2015 - http://patriciogonzalezvivo.com/
// I am the sole copyright owner of this Work.
//
// You cannot host, display, distribute or share this Work in any form,
// including physical and digital. You cannot use this Work in any
// commercial or non-commercial product, website or project. You cannot
// sell this Work and you cannot mint an NFTs of it.
// I share this Work for educational purposes, and you can link to it,
// through an URL, proper attribution and unmodified screenshot, as part
// of your educational material. If these conditions are too restrictive
// please contact me and we'll definitely work it out.
#define PI 3.14159265359
#define TWO_PI 6.28318530718

@ -0,0 +1,78 @@
# 图像处理
## 纹理
![](01.jpg)
显卡GPU有特殊的图像存储类型。在中央处理器CPU图像往往储存成字节数组但在GPU上图像却往往储存成```sampler2D``` (二维采样器)。它们更像是一个由浮点向量组成的表格(或矩阵)。更有意思的是,这张*表格*中向量们的值是连续的。这意味着邻近像素点的值之间是用较低级别的插值出来的。
为了用到这一特性我们首先要把图像从CPU*上传*到GPU然后再把纹理的```id```(序列号)传给对应的[```uniform```](../05)。这一切流程发生在着色器之外。
一旦纹理texture加载好了并且链接上了一个有效的```uniform sampler2D```,你就可以用[```texture2D()```](index.html#texture2D.md)函数获取特定坐标(用二维向量[```vec2```](index.html#vec2.md)类型表示)对应的颜色值(用四维向量[```vec4```](index.html#vec4.md)类型表示)。
```glsl
vec4 texture2D(sampler2D texture, vec2 coordinates)
```
在下面的代码中我们将《神奈川冲浪里》1830以```uniform sampler2D u_tex0```为类型和名字加载了进来并且我们在显示平面billboard中调用了它的每个像素
<div class="codeAndCanvas" data="texture.frag" data-textures="hokusai.jpg"></div>
如果你注意观察你会发现纹理的坐标是归一化的这真的是个惊喜不是吗纹理坐标和我们已然熟识的东西是一致的。它们的坐标总是在0.0和1.0之间。这意味着它和我们使用的归一化空间坐标完美吻合。
现在既然你已经了解了如何正确的加载纹理,是时候来试验性地探索我们究竟能用这一技巧做些什么了。快试试下面这些:
* 把纹理缩小到原先的一半。
* 把原先的纹理旋转90度。
* 将鼠标位置赋值给纹理坐标来移动纹理。
为什么你要为纹理痴狂呢首先请忘了通道那可悲的255值吧一旦你的图像被转换成了一个```uniform sampler2D```所有的值都会在0.0和1.0的区间范围内(小数精度取决于你把```precision```设置成了多少)。这就是着色器能创造出美轮美奂的后处理效果的原因。
其次,[```vec2()```](index.html#vec2.md)类型意味着你甚至可以获取到像素之间的值。如前所述纹理是连续体continuum。也就是说如果正确地设置好了你的纹理你可以获取纹理图像上的任意值而这些值在像素点之间是平滑过渡的
最后你可以让你的图像在边缘处重复。这样的话在你获取坐标超出0.0到1.0这个归一化区间的值时,返回值会从另一边的边缘开始循环往复。
所有这些功能会让你的图像越发像是无限循环往复的化纤面料。你可以拉扯、伸缩你的纹理而无需注意它们原初的数据究竟是什么样的。要体验这一点,看看下面的代码吧,其中我们使用[我们先前创建的噪声函数](../11/)来扭曲纹理。
<div class="codeAndCanvas" data="texture-noise.frag" data-textures="hokusai.jpg"></div>
## 纹理分辨率
上述的种种示例仅展现了长宽相等的方形图像匹配方形显示平面billboard的情形。而至于非正方形图像事情就没那么简单了。不幸的是几个世纪以来的绘画艺术和摄影艺术发现非正方形比例的图像更令人赏心悦目。
![Joseph Nicéphore Niépce (1826)](nicephore.jpg)
我们该如何解决这个问题呢?我们需要知道这一图像的原始比例,才好在放大或缩小纹理的时候正确地保持它原始的[*宽高比*](http://en.wikipedia.org/wiki/Aspect_ratio)。为此,纹理的宽和高是以```uniform```的形式传递进着色器的——在我们的示例框架里是以纹理名后跟```Resolution```的```uniform vec2```传递进来的。一旦着色器里有了这些信息,我们就可以将纹理分辨率的```宽度```除以```高度```来获得纹理的宽高比。最后,把这个比例和```y```坐标相乘,我们就可以实现伸缩这根轴来让纹理匹配其原始比例。
取消 21 行的注释来实操一下吧。
<div class="codeAndCanvas" data="texture-resolution.frag" data-textures="nicephore.jpg"></div>
* 如果要这张图片居中显示,我们应该怎么做呢?
## 数字装潢Digital upholstery
![](03.jpg)
你可能会觉得这有些不必要地繁琐……呃,可能你是对的。但这种对待图像的方式给了“奇技淫巧”足够的发挥空间。试想,你是一名室内装潢师,通过拉伸和折叠织物结构,你可以创造出更好的新图案和新技巧。
![Eadweard's Muybridge study of motion](muybridge.jpg)
这种水平的工艺可以追溯到最早的一些光学实验。例如,游戏里很常见的*精灵动画**sprite animations*你不可避免地会在它身上看到费纳奇镜phenakistoscope、西洋镜zoetrope和改良版西洋镜praxinoscope的影子。
这看起来很简单,但修改纹理坐标可以带来巨大的可能性。例如:
<div class="codeAndCanvas" data="texture-sprite.frag" data-textures="muybridge.jpg"></div>
现在轮到你了:
* 你能活学活用,做出万花筒效果吗?
* 在Oculus和谷歌Cardboard之前立体摄影是件大事。你能编写一个简单的着色器来重新使用这些美丽的图像吗?
<a href=“../edit.php#10/ikeda-03.frag”><canvas id=“custom” class=“canvas” data-fragment-url=“ikeda-03.frag” width=“520px” height=“200px”></canvas></a>
* 你还可以使用纹理来再创造哪些其他的光学玩具吗?
在下一章中,我们将学习如何使用着色器进行一些图像处理。你会注意到着色器的复杂性最终是有意义的,因为它很大程度上是为这一过程而生的。我们将开始做一些图像操作!

@ -5,6 +5,18 @@
precision mediump float;
#endif
// Copyright (c) Patricio Gonzalez Vivo, 2015 - http://patriciogonzalezvivo.com/
// I am the sole copyright owner of this Work.
//
// You cannot host, display, distribute or share this Work in any form,
// including physical and digital. You cannot use this Work in any
// commercial or non-commercial product, website or project. You cannot
// sell this Work and you cannot mint an NFTs of it.
// I share this Work for educational purposes, and you can link to it,
// through an URL, proper attribution and unmodified screenshot, as part
// of your educational material. If these conditions are too restrictive
// please contact me and we'll definitely work it out.
#define PI 3.14159265359
#define TWO_PI 6.28318530718

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save