Skip to content

Commit

Permalink
Merge pull request #4 from patriciogonzalezvivo/master
Browse files Browse the repository at this point in the history
refresh
  • Loading branch information
rnbastos committed Jan 12, 2021
2 parents 46e4d5d + 34f8ae6 commit b3300b3
Show file tree
Hide file tree
Showing 162 changed files with 4,838 additions and 116 deletions.
50 changes: 50 additions & 0 deletions 00/README-vi.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# Giới thiệu

<canvas id="custom" class="canvas" data-fragment-url="cmyk-halftone.frag" data-textures="vangogh.jpg" width="700px" height="320px"></canvas>

Hai bức ảnh trên đây được tạo ra bằng những cách khác nhau. Bức đầu tiên được vẽ bởi Van Gogh bằng nhiều lớp sơn chồng lên nhau. Nó đã ngốn của ông ấy hàng giờ đồng hồ. Bức thứ hai được tạo ra trong chớp mắt từ 4 ma trận điểm ảnh: một cho màu xanh (Cyan), một cho màu hồng (Magenta), một cho màu vàng (Yellow) và một cho màu đen (Black). Điểm khác biệt chính là: các lớp của bức tranh thứ hai được tạo ra đồng thời chứ không phải tuần tự.

Quyển sách này nói về một kỹ thuật mang tính cách mạng trong Đồ họa Máy tính, *fragment shader*, giúp nâng tầm đồ hoạ kỹ thuật số lên một tầm cao mới. Bạn có thể nghĩ sức ảnh hưởng của nó tương đương với cỗ máy in của Gutenberg khi xưa vậy.

![Cỗ máy in của Gutenberg](gutenpress.jpg)

Fragment shader cho bạn toàn quyền kiểm soát các điểm ảnh được render trên màn hình cực kỳ nhanh chóng. Đó là lí do tại sao nó được dùng trong mọi lĩnh vực của Đồ hoạ máy tính, từ các bộ lọc video trên điện thoại di động tới các trò chơi điện tử 3D đáng kinh ngạ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.

## Quyển sách này dành cho những ai ?

Quyển sách này được viết cho các kỹ sư và lập trình viên sáng tạo, những người đã có kinh nghiệm lập trình và kiến thức cơ bản về Giải tích và Lượng giác, và cho những ai muốn nâng tầm chất lượng đồ hoạ trong tác phẩm của mình. (Nếu bạn muốn học lập trình, tôi khuyên bạn nên bắt đầu từ trang web [Processing](https://processing.org/) rồi quay lại đây khi đã cảm thấy đủ kiến thức.

Quyển sách này sẽ chỉ cho bạn cách dùng các shader và cách áp dụng shader vào các dự án để cải thiện hiệu năng cũng như chất lượng đồ hoạ. Vì các shader viết bằng GLSL (viết tắt của OpenGL Shading Language) sẽ được biên dịch và chạy trên rất nhiều nền tảng khác nhau, bạn có thể ứng dụng những gì học được ở đây cho bất kỳ môi trường nào sử dụng OpenGL, OpenGL ES hoặc WebGL. Cụ thể, bạn có thể ứng dụng những kiến thức này cho các bản vẽ [Processing](https://processing.org/), các ứng dụng [openFrameworks](http:https://openframeworks.cc/), các cỗ máy [Cinder](http:https://libcinder.org/) tương tác được, các website sử dụng [Three.js](http:https://threejs.org/) hay các trò chơi trên iOS/Android.

## 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.

*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ễ.

Những nội dung nằm ngoài phạm vi của quyển sách:

* Đây *không phải* sách nói về OpenGL hay WebGL. OpenGL/WebGL là chủ đề rộng lớn hơn cả GLSL và fragment shader. Để tìm hiểu thêm về OpenGL/WebGL, tôi khuyên bạn nên đọc [Giới thiệu OpenGL](https://open.gl/introduction), [Hướng dẫn lập trình OpenGL - xuất bản lần 8](http:https://www.amazon.com/OpenGL-Programming-Guide-Official-Learning/dp/0321773039/ref=sr_1_1?s=books&ie=UTF8&qid=1424007417&sr=1-1&keywords=open+gl+programming+guide) (còn được biết tới với tên gọi là The Red Book) hoặc [WebGL: Up and Running](http:https://www.amazon.com/WebGL-Up-Running-Tony-Parisi/dp/144932357X/ref=sr_1_4?s=books&ie=UTF8&qid=1425147254&sr=1-4&keywords=webgl)

* Đây *không phải* sách Toán. Mặc dù ta có đề cập tới một vài thuật toán và kỹ thuật liên quan tới Giải tích và Lượng giác, nhưng chúng tôi sẽ không giải thích chúng một cách chi tiết. Để tiện giải đáp các thắc mắc về Toán, tôi khuyên bạn nên có một trong số các quyển sách sau: [Ứng dụng Toán trong lập trình và đồ hoạ máy tính - xuất bản lần 3](http:https://www.amazon.com/Mathematics-Programming-Computer-Graphics-Third/dp/1435458869/ref=sr_1_1?ie=UTF8&qid=1424007839&sr=8-1&keywords=mathematics+for+games) hoặc [Kiến thức Toán cần thiết cho lập trình Game và Ứng dụng real-time](http:https://www.amazon.com/Essential-Mathematics-Games-Interactive-Applications/dp/0123742978/ref=sr_1_1?ie=UTF8&qid=1424007889&sr=8-1&keywords=essentials+mathematics+for+developers).


## Bạn cần gì để bắt đầu ?

Chỉ vài thứ thôi! Nếu bạn có trình duyệt có thể xử lý WebGL (như Chrome, Firefox hoặc Safari) và kết nối Internet, click nút _"Next >>>"_ ở cuối trang này để bắt đầu ngay.

Hoặc, tuỳ theo bạn có gì và cần gì từ quyển sách, bạn có thể:

- [Tạo quyển sách phiên bản không cần Internet](https://thebookofshaders.com/appendix/00/?lan=vi)

- [Chạy các ví dụ trên Raspberry Pi mà không cần trình duyệt](https://thebookofshaders.com/appendix/01/?lan=vi)

- [Tạo phiên bản PDF của sách để in](https://thebookofshaders.com/appendix/02/?lan=vi)

- Xem [repository trên GitHub](https://github.com/patriciogonzalezvivo/thebookofshaders) của quyền sách này để giúp sửa và chia sẻ code.
4 changes: 2 additions & 2 deletions 01/README-fr.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ Imaginez le CPU de votre ordinateur comme un *tuyau* et chacune des opérations
Les jeux vidéos et autres applications graphiques demandent beaucoup plus de puissance de calcul que les autres programmes.
Par nature, ils demandent de grandes quantités d'opérations au pixel, chaque changement d'image demande de recalculer l'ensemble des pixels de l'écran. Dans les applications 3D, on doit également mettre à jour les modèles, les textures, les transformations etc. ce qui rajoute encore plus de charge au CPU.

Revenons à notre métaphore des tuyaux et des opérations. Chaque pixel à l'écran représente une simple petite opération. En soi, chaque le traitement d'une opération n'est pas un problème pour le CPU, mais (et c'est ici que se trouve le problème) il faut appliquer cette petite opération sur chaque pixel à l'écran ! Par exemple, sur un vieux moniteur ayant une résolution de 800x600, 480 000 pixels ont besoin d'être traités par *frame* ce qui équivaut à 14 600 000 calculs par seconde ! C’est une opération assez importante pour surcharger un microprocesseur. Sur un écran rétina moderne ayant une résolution de 2880x1800 cadencé à 60 *frames* par seconde, cela représente un total de 311 040 000 calculs par seconde. Comment les ingénieurs graphiques résolvent-ils ce problème?
Revenons à notre métaphore des tuyaux et des opérations. Chaque pixel à l'écran représente une simple petite opération. En soi, le traitement d'une opération n'est pas un problème pour le CPU, mais (et c'est ici que se trouve le problème) il faut appliquer cette petite opération sur chaque pixel à l'écran ! Par exemple, sur un vieux moniteur ayant une résolution de 800x600, 480 000 pixels ont besoin d'être traités par *frame* ce qui équivaut à 14 600 000 calculs par seconde ! C’est une opération assez importante pour surcharger un microprocesseur. Sur un écran rétina moderne ayant une résolution de 2880x1800 cadencé à 60 *frames* par seconde, cela représente un total de 311 040 000 calculs par seconde. Comment les ingénieurs graphiques résolvent-ils ce problème?

![](03.jpeg)

Expand All @@ -37,7 +37,7 @@ C'est là qu'intervient le traitement parallèle (parallel processing). Au lieu

Imaginez ces petits microprocesseurs comme une trame de tuyaux, et les données de chaque pixel comme des balles de ping-pong. 14 400 000 balles de ping-pong par seconde pourraient obstruer presque n'importe quel tuyau. Mais une trame de 800x600 petits tuyaux recevant 30 vagues de 480 000 balles de ping-pong par seconde peuvent traiter la charge facilement. Et ça marche également pour des résolutions plus élevées; plus le matériel est capable de traiter d'informations en parallèle, plus il pourra traiter des flux importants.

Un autre *pouvoir magique* du GPU c'est l'accélération matérielle de certaines fonctions mathématiques. Certaines fonctions souvent complexes seront traitées directement par le matériel au lieu de passer par la couche logicielle. Ce qui signifie que certaines opérations mathématiques un peu complexes comme les transformations de matrices et les opérations trigonométriques seront traitées extrêmement - à la vitesse de l'électricité.
Un autre *pouvoir magique* du GPU c'est l'accélération matérielle de certaines fonctions mathématiques. Certaines fonctions souvent complexes seront traitées directement par le matériel au lieu de passer par la couche logicielle. Ce qui signifie que certaines opérations mathématiques un peu complexes comme les transformations de matrices et les opérations trigonométriques seront traitées extrêmement rapidement - à la vitesse de l'électricité.

## Qu'est ce que le GLSL ?

Expand Down
49 changes: 49 additions & 0 deletions 01/README-vi.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# Mở đầu
## 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ì ?

![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)

Nếu bạn đã từng vẽ trên máy tính, bạn biết rằng để có được hình mình muốn, bạn phải vẽ hình tròn, hình chữ nhật rồi vài đường thẳng, vài hình tam giác. Quá trình đó không khác gì việc viết từng chữ một - đó là một loạt các chỉ dẫn để máy tính thực hiện lần lượt.

Shader cũng là một tập hợp các chỉ dẫn, nhưng các chỉ dẫn đó sẽ được thực thi cùng lúc cho từng điểm ảnh trên màn hình. Điều đó có nghĩa là code bạn viết phải xử lý khác nhau tuỳ theo vị trí của điểm ảnh trên màn hình. Giống như máy rập chữ, chương trình của bạn sẽ hoạt động như một hàm nhận vị trí của điểm ảnh rồi trả về màu của điểm ảnh đó. Chương trình đó chạy rất rất nhanh.

![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 ?

Để 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*.

Hãy tưởng tượng CPU là một dây chuyền công nghiệp lớn, và mọi tác vụ đi qua dây chuyền là một khâu. Có vài khâu đồ sộ hơn các khâu khác, tức là chúng cần nhiều thời gian và năng lượng hơn để xử lý. Ta nói chúng cần nhiều năng lực xử lý hơn. Kiến trúc của máy tính khiến mỗi khâu phải thực hiện tuần tự; khâu này kết thúc rồi mới đến khâu tiếp theo. Máy tính hiện đại thường có tới 4 bộ xử lý tương tự như 4 dây chuyền sản xuất này, lần lượt thực thi từng tác vụ nhỏ. Mỗi dây chuyền nhỏ trong đó gọi là một *thread*.

![CPU](00.jpeg)

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 ?

![](03.jpeg)

Đây là lúc mà xử lý song song trở thành một giải pháp tốt. Thay vì phải trang bị vài bộ vi xử lý to lớn và mạnh mẽ, hoặc *các dây chuyền*, sẽ là thông minh hơn nếu để cho hàng loạt các bộ vi xử lý tí hon chạy song song. Và đó chính là việc mà các bộ xử lý đồ hoạ (GPU) là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.

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:https://openglbook.com/chapter-0-preface-what-is-opengl.html)

## 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.

Để 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ị **** 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.

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à 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!
Loading

0 comments on commit b3300b3

Please sign in to comment.