From 627e7a4f41dff409c48d97f30ec4278a16331750 Mon Sep 17 00:00:00 2001 From: Wojtek Pachowiak Date: Fri, 6 Jan 2023 21:44:08 +0100 Subject: [PATCH 01/23] update .gitignore for editing in VS Code --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index 5b0113c..29ee2fa 100644 --- a/.gitignore +++ b/.gitignore @@ -12,3 +12,5 @@ idea/ /07/test.html /appendix/04/index.html /09/test.html + +.vscode \ No newline at end of file From 0302bcff5f32debef1f17132c33738661a02b949 Mon Sep 17 00:00:00 2001 From: Wojtek Pachowiak Date: Fri, 6 Jan 2023 21:44:50 +0100 Subject: [PATCH 02/23] add Polish translation for 00 and main page --- 00/README-pl.md | 50 +++++++++++++++++++ README-pl.md | 127 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 177 insertions(+) create mode 100644 00/README-pl.md create mode 100644 README-pl.md diff --git a/00/README-pl.md b/00/README-pl.md new file mode 100644 index 0000000..5eaf1c8 --- /dev/null +++ b/00/README-pl.md @@ -0,0 +1,50 @@ +# Wprowadzenie + + + +Powyższe obrazy zostały stworzone na różny sposób. Pierwszy stworzył Van Gogh, aplikując farbę warstwa po wartwie. Zajęło mu to godziny. Drugi z nich stworzono poprzez połączenie czterech macierzy zawierających piksele koloru niebieskozielonego (cyjan), magenty, żółtego i czarnego. Kluczowa różnicę stanowi fakt, że drugi obraz stworzny został natychmiast, a nie seryjnie, krok po kroku. + +Ta książka jest o rewolucyjnej technice obliczeniowej, tzw. *fragment shaderach* (zwanych też *pixel shaderami*), które wznoszą cyfrowo generowane obrazy na wyższy poziom. Możesz o nich myśleć jak o ekwiwalencie maszyny drukarskiej Gutenberga dla zastosowań graficznych. + +![Gutenberg's press](gutenpress.jpg) + + +Fragment shadery dają ci pełnię kontroli nad błyskawicznym renderowaniem pikseli na ekranie. Właśnie dlatego są one używane w przeróżnych sytuacjach: od filtrów wideo w telefonach do niesamowitych twójwymiarowych gier wideo. + +![Journey by That Game Company](journey.jpg) + +W następujących rozdziałach odkryjesz jak niewiarygodnie szybkie i potężne są te techniki i jak zastosować je w twojej pracy zawodowej i osobistej. + +## Dla kogo jest ta książka? + +Ta książka jest napisana dla creative koderów, game developerów i inżynierów, którzy posiadają doświadczenie programistyczne, podstawową wiedzę z algebry liniowej i trygonometrii, i którzy chcą wznieść jakość swoich prac graficzny na wyższy poziom. (Jeżeli chcesz nauczyć się programować, polecam zacząć od [Processing](https://processing.org/) i wrócić, gdy opanujesz go do komfortowego poziomu. + +Ta książka nauczy cię jak używać i integrować shadery w twoich projektach, aby podnieść ich wydajność i wygląd. Ponieważ shadery GLSL (OpenGL Shading Language) kompilują i uruchamiają się na różnorodnych platformach, będziesz w stanie zaaplikować tutaj zdobytą wiedzę do jakiegokolwiek środowiska wykorzystującego OpenGL, OpenGL ES lub WebGL. Innymi słowy, będziesz w stanie wykorzystać tę wiedzę przy tworzeniu szkiców z [Processing](https://processing.org/), aplikacji z [openFrameworks](http://openframeworks.cc/), interaktywnych instalacji z [Cinder](http://libcinder.org/) czy stron internetowych i gier iOS/Android z [Three.js](http://threejs.org/). + +## Jaki materiał pokrywa ta książka? + +Ta książka skupia się na użyciu fragment shaderów GLSL. Wpierw zdefiniujemy czym shadery są; potem dowiemy się jak, z ich pomocą, tworzyć proceduralne kształty, wzorce, tekstury i animacje. Nauczysz się podstaw języka shadingowego i jego przydatnych aplikacji w przetwarzaniu obrazów (operacje na obrazach, sploty macierzowe, rozmycia, filtry koloru, "lookup tables" i inne efekty) czy symulacji ("Gra w życie" Conwaya, model reakcji-dyfuzji Graya-Scotta, plusk wody, efekt akwareli, komórki Voronoi, itp.). Pod koniec książki zobaczymy kilka zaawansowanych technik opartych o Ray Marching + +*W każdym rozdziale znajdziesz interaktywne przykłady do wypróbowania.* Kiedy zmodyfikujesz kod, natychmiastowo zobaczysz zmiany. Zagadnienia mogą być abstrakcyjne i mylące, więc takie interkatywne przykłady stanowią konieczną pomoc w zrozumieniu materiału. Im szybciej złapiesz praktykę, tym prostsza będzie dalsza nauka. + +Materiał, którego ta książka nie pokrywa: + +* To *nie jest* książka o OpenGL lub WebGL. OpenGL/WebGL jest większym tematem niż GLSL czy fragment shadery. Jeśli chcesz wiedzieć więcej o OpenGL i WebGL, to polecam zajrzeć do [OpenGL Introduction](https://open.gl/introduction), [the 8th edition of the OpenGL Programming Guide](http://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) (zwana również "czerwoną książką") lub [WebGL: Up and Running](http://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) + +* To *nie jest* książka do nauki matematyki. Choć opisane są w niej algorytmy i techniki, które opierają się zrozumieniu algebry i trygonometrii, to nie będziemy ich szczegółowo tłumaczyć. Z pytaniami dotyczącymi matematyki polecam zajrzeć do następujących książek: +[3rd Edition of Mathematics for 3D Game Programming and computer Graphics](http://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) lub [2nd Edition of Essential Mathematics for Games and Interactive Applications](http://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). + +## Co potrzeba, żeby zacząć? + +Niewiele! Jeśli masz współczesną przeglądarkę, która obsługuje WebGL (jak Chrome, Firefox czy Safari) i połączenie internetowe, to kliknij "Dalej" na dole strony, aby zacząć. + +Alternatywnie, w zależności od tego co masz albo co potrzebujesz od tej książki, możesz: + +- [Stworzyć wersję off-line tej książki](https://thebookofshaders.com/appendix/00/) + +- [Uruchomić przykłady na Raspberry PI bez przeglądarki](https://thebookofshaders.com/appendix/01/) + +- [Stworzyć wersję PDF tej książki do wydrukowania](https://thebookofshaders.com/appendix/02/) + +- Sprawdź [repozytorium GitHub](https://github.com/patriciogonzalezvivo/thebookofshaders) tej książki, by pomóc rożwiązać issues i podzielić się swoim kod + diff --git a/README-pl.md b/README-pl.md new file mode 100644 index 0000000..7479904 --- /dev/null +++ b/README-pl.md @@ -0,0 +1,127 @@ + + +# The Book of Shaders +*by [Patricio Gonzalez Vivo](http://patriciogonzalezvivo.com/) and [Jen Lowe](http://jenlowe.net/)* + +Łagodny, krok po kroku przewodnik przez abstrakcyjny i złożony świat Fragment Shaderów. + +
+ +
+ +## Spis treści + +* [O książce](00/) + +* Wprowadzenie + * [Czym jest shader?](01/) + * [“Hello world!”](02/) + * [Uniformy](03/) + * [Uruchomienie shaderu](04/) + +* Rysowanie algorytmiczne + * [Shaping functions](05/) + * [Kolory](06/) + * [Kształty](07/) + * [Macierze](08/) + * [Wzorce](09/) + +* Design generatywny + * [Random](10/) + * [Noise](11/) + * [Cellular noise](12/) + * [Fraktalny ruch Browna](13/) + * Fraktale + +* Przetwarzanie obrazów + * Tekstury + * Operacje na obrazach + * Kernel convolutions + * Filtry + * Inne efekty + +* Symulacja + * Pingpong + * Conway + * Ripples + * Water color + * Reaction diffusion + +* Grafika 3D + * Światła + * Normal-mapy + * Bump-mapy + * Ray marching + * Environmental-mapy (spherical and cube) + * Odbicie i refrakcja + +* [Dodatek:](appendix/) Inne sposoby korzystania z tej książki + * [Jak korzystać z tej książki offline?](appendix/00/) + * [Jak uruchomić przykłady na Raspberry Pi?](appendix/01/) + * [Jak wydrukować tę książkę?](appendix/02/) + * [Jak mogę pomóc?](appendix/03/) + * [Wprowadzenie dla biegłych w JavaScript](appendix/04/) by [Nicolas Barradeau](http://www.barradeau.com/) + +* [Galeria przykładów](examples/) + +* [Glosariusz](glossary/) + +## O autorach + +[Patricio Gonzalez Vivo](http://patriciogonzalezvivo.com/) (1982, Buenos Aires, Argentyna) is a New York based artist and developer. He explores interstitial spaces between organic and synthetic, analog and digital, individual and collective. In his work he uses code as an expressive language with the intention of developing a better together. + +# **TODO** +jest nowojorskim artystą i developerem. Bada to, co między organicznym a syntetycznym, analogowym a cyfrowym, indywidualnym i kolektywnym. W swojej pracy używa kodu jako ekspresywnego języka z intencją rozwijania + +Patricio studiował i praktykował psychoterapię oraz arteterapię. Otrzymał tytuł magistra sztuk pięknych w Design & Technology od Parsons The New School, gdzie aktualnie uczy. Obecnie pracuje jako inżynier graficzny w Mapzen, gdzie tworzy opensource'owe narzędzia do kartografii komputerowej. + + + +[Jen Lowe](http://jenlowe.net/) is an independent data scientist and data communicator at Datatelling where she brings together people + numbers + words. She teaches in SVA's Design for Social Innovation program, cofounded the School for Poetic Computation, taught Math for Artists at NYU ITP, researched at the Spatial Information Design Lab at Columbia University, and contributed ideas at the White House Office of Science and Technology Policy. She's spoken at SXSW and Eyeo. Her work has been covered by The New York Times and Fast Company. Her research, writing, and speaking explore the promises and implications of data and technology in society. She has a B.S. in Applied Math and a Master's in Information Science. Often oppositional, she's always on the side of love. + +# **TODO** +jest niezależną data scientist w Datatelling, gdzie łączy ludzi + liczby + słowa. Uczy w ramach programu Design for Social Innovation na SVA, współzałożyła School for Poetic Computation, uczyła matematyki dla artystów w NYU ITP, była badaczką w Spatial Information Design Lab na Uniwersytecie Columbia oraz zgłaszała swoje pomysły do Office of Science and Technology Policy Białego Domu. Przemawiała na SXSW i w Eyeo. Jej pracę opisywały The New York Times i Fast Company. Jej działalność badawczą, eksplorują obietnice i implikacje danych i technologii dla społeczeństwa. Obroniła tytuły licencjata matematyki stosowanej oraz magistra informatyki. Często buntownicza, ale zawsze po stronie miłości. + + + +## Podziękowania + +Podziękowania dla [Scott Murray](http://alignedleft.com/) za porady i inspriację. + +Podziękowania dla [Kenichi Yoneda (Kynd)](https://twitter.com/kyndinfo), [Nicolas Barradeau](https://twitter.com/nicoptere), [Karim Naaji](http://karim.naaji.fr/) za wsparcie, dobre pomysły i kod. + +Podziękowania dla [Kenichi Yoneda (Kynd)](https://twitter.com/kyndinfo) i [Sawako](https://twitter.com/sawakohome) za japońskie [tłumaczenie (日本語訳)](?lan=jp) + +Podziękowania dla [Tong Li](https://www.facebook.com/tong.lee.9484) i [Yi Zhang](https://www.facebook.com/archer.zetta?pnref=story) za chińskie [tłumaczenie (中文版)](?lan=ch) + +Podziękowania dla [Jae Hyun Yoo](https://www.facebook.com/fkkcloud) i [June Kim](https://github.com/rlawns324) za koreańskie [tłumaczenie (한국어)](?lan=kr) + +Podziękowania dla Nahuel Coppero (Necsoft) za hiszpańskie [tłumaczenie (español)](?lan=es) + +Podziękowania dla [Raphaela Protásio](https://github.com/Rawphs) i [Lucas Mendonça](https://github.com/luuchowl) za portugalskie [tłumaczenie (portugues)](?lan=pt) + +Podziękowania dla [Nicolas Barradeau](https://twitter.com/nicoptere) i [Karim Naaji](http://karim.naaji.fr/) za francuskie [tłumaczenie (français)](?lan=fr) + +Podziękowania dla [Andrea Rovescalli](https://www.earove.info) za włoskie [tłumaczenie (italiano)](?lan=it) + +Podziękowania dla [Michael Tischer](http://www.mitinet.de) za niemieckie [tłumaczenie (deutsch)](?lan=de) + +Podziękowania dla [Sergey Karchevsky](https://www.facebook.com/sergey.karchevsky.3) za rosyjskie [tłumaczenie (russian)](?lan=ru) + +Podziękowania dla [Vu Phuong Hoang](https://www.facebook.com/vuphuonghoang88) za wietnamskie [tłumaczenie (Tiếng Việt)](?lan=vi) + +Podziękowania dla [Andy Stanton](https://andy.stanton.is/) za naprawę i usprawnienie funkcji [eksportu pdf/epub ](https://thebookofshaders.com/appendix/02/) + +Podziękowania dla każdego, kto [współtworzy](https://github.com/patriciogonzalezvivo/thebookofshaders/graphs/contributors) ten projekt poprzez swoje rady, korekty lub finansowe wsparcie. + +## Zdobądź nowe rozdziały + +Zapisz się do newslettera lub obserwuj na [Twitter](https://twitter.com/bookofshaders) / Mastodon / [Discord](shader.zone) + +
+ From 28b1c857eaa94513c6be6baee7b727829ffb0339 Mon Sep 17 00:00:00 2001 From: Wojtek Pachowiak Date: Sun, 8 Jan 2023 17:15:53 +0100 Subject: [PATCH 03/23] fix table of contents. --- README-pl.md | 38 ++++++++++++++++---------------------- 1 file changed, 16 insertions(+), 22 deletions(-) diff --git a/README-pl.md b/README-pl.md index 7479904..70b23b4 100644 --- a/README-pl.md +++ b/README-pl.md @@ -1,7 +1,7 @@ # The Book of Shaders -*by [Patricio Gonzalez Vivo](http://patriciogonzalezvivo.com/) and [Jen Lowe](http://jenlowe.net/)* +*autorstwa [Patricio Gonzalez Vivo](http://patriciogonzalezvivo.com/) i [Jen Lowe](http://jenlowe.net/)* Łagodny, krok po kroku przewodnik przez abstrakcyjny i złożony świat Fragment Shaderów. @@ -15,7 +15,7 @@ * Wprowadzenie * [Czym jest shader?](01/) - * [“Hello world!”](02/) + * ["Witaj świecie!"](02/) * [Uniformy](03/) * [Uruchomienie shaderu](04/) @@ -33,27 +33,27 @@ * [Fraktalny ruch Browna](13/) * Fraktale -* Przetwarzanie obrazów - * Tekstury - * Operacje na obrazach +* Image processing + * Textures + * Image operations * Kernel convolutions - * Filtry - * Inne efekty + * Filters + * Others effects -* Symulacja +* Simulation * Pingpong * Conway * Ripples * Water color * Reaction diffusion -* Grafika 3D - * Światła - * Normal-mapy - * Bump-mapy +* 3D graphics + * Lights + * Normal-maps + * Bump-maps * Ray marching - * Environmental-mapy (spherical and cube) - * Odbicie i refrakcja + * Environmental-maps (spherical and cube) + * Reflect and refract * [Dodatek:](appendix/) Inne sposoby korzystania z tej książki * [Jak korzystać z tej książki offline?](appendix/00/) @@ -68,19 +68,13 @@ ## O autorach -[Patricio Gonzalez Vivo](http://patriciogonzalezvivo.com/) (1982, Buenos Aires, Argentyna) is a New York based artist and developer. He explores interstitial spaces between organic and synthetic, analog and digital, individual and collective. In his work he uses code as an expressive language with the intention of developing a better together. - -# **TODO** -jest nowojorskim artystą i developerem. Bada to, co między organicznym a syntetycznym, analogowym a cyfrowym, indywidualnym i kolektywnym. W swojej pracy używa kodu jako ekspresywnego języka z intencją rozwijania +[Patricio Gonzalez Vivo](http://patriciogonzalezvivo.com/) (1982, Buenos Aires, Argentyna) jest nowojorskim artystą i developerem. Bada granice między organicznym a syntetycznym, analogowym a cyfrowym, indywidualnym i kolektywnym. W swojej pracy używa kodu jako ekspresywnego języka, z intencją rozwijania współpracy międzyludzkiej. Patricio studiował i praktykował psychoterapię oraz arteterapię. Otrzymał tytuł magistra sztuk pięknych w Design & Technology od Parsons The New School, gdzie aktualnie uczy. Obecnie pracuje jako inżynier graficzny w Mapzen, gdzie tworzy opensource'owe narzędzia do kartografii komputerowej. -[Jen Lowe](http://jenlowe.net/) is an independent data scientist and data communicator at Datatelling where she brings together people + numbers + words. She teaches in SVA's Design for Social Innovation program, cofounded the School for Poetic Computation, taught Math for Artists at NYU ITP, researched at the Spatial Information Design Lab at Columbia University, and contributed ideas at the White House Office of Science and Technology Policy. She's spoken at SXSW and Eyeo. Her work has been covered by The New York Times and Fast Company. Her research, writing, and speaking explore the promises and implications of data and technology in society. She has a B.S. in Applied Math and a Master's in Information Science. Often oppositional, she's always on the side of love. - -# **TODO** -jest niezależną data scientist w Datatelling, gdzie łączy ludzi + liczby + słowa. Uczy w ramach programu Design for Social Innovation na SVA, współzałożyła School for Poetic Computation, uczyła matematyki dla artystów w NYU ITP, była badaczką w Spatial Information Design Lab na Uniwersytecie Columbia oraz zgłaszała swoje pomysły do Office of Science and Technology Policy Białego Domu. Przemawiała na SXSW i w Eyeo. Jej pracę opisywały The New York Times i Fast Company. Jej działalność badawczą, eksplorują obietnice i implikacje danych i technologii dla społeczeństwa. Obroniła tytuły licencjata matematyki stosowanej oraz magistra informatyki. Często buntownicza, ale zawsze po stronie miłości. +[Jen Lowe](http://jenlowe.net/) jest niezależną data scientist i komunikatorką danych w Datatelling, gdzie łączy ludzi + liczby + słowa. Uczy w ramach programu Design for Social Innovation na SVA, współzałożyła School for Poetic Computation, uczyła matematyki dla artystów w NYU ITP, była badaczką w Spatial Information Design Lab na Uniwersytecie Columbia oraz zgłaszała swoje pomysły do Office of Science and Technology Policy Białego Domu. Przemawiała na SXSW i w Eyeo. Jej pracę opisywały The New York Times i Fast Company. Jej działalność badawcza, pisarska i mównicza eksplorują obietnice oraz implikacje danych i technologii dla społeczeństwa. Obroniła tytuły licencjata matematyki stosowanej oraz magistra informatyki. Często opozycyjna, ale zawsze po stronie miłości. From 8a24def06fe9753f56eb123a336a92cc3d89da6b Mon Sep 17 00:00:00 2001 From: Wojtek Pachowiak Date: Sun, 8 Jan 2023 17:16:08 +0100 Subject: [PATCH 04/23] add first chapter --- 01/README-pl.md | 76 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+) create mode 100644 01/README-pl.md diff --git a/01/README-pl.md b/01/README-pl.md new file mode 100644 index 0000000..c80f2de --- /dev/null +++ b/01/README-pl.md @@ -0,0 +1,76 @@ +# Początki +## Czym jest fragment shader? + +W poprzednim rozdziale nazwaliśmy shadery ekwiwalentem prasy drukarskiej Gutenberga dla grafiki. Dlaczego? A co ważniejsze: czym jest shader? + +![Od "litera po literze" do "strona po stronie", po prawej: William Blades (1891), po lewej: Rolt-Wheeler (1920).](print.png) + +Jeżeli masz doświadczenie w rysowaniu z użyciem komputera, to wiesz, że proces ten polega na rysowaniu kółek, prostokątów, linii oraz trójkątów do momentu skomponowania pożądanego obrazu. Proces ten jest bardzo podobny do pisania listów lub książek odręcznie - jest to zbiór instrukcji wykonujących zadanie po zadaniu. + +If you already have experience making drawings with computers, you know that in that process you draw a circle, then a rectangle, a line, some triangles until you compose the image you want. That process is very similar to writing a letter or a book by hand - it is a set of instructions that do one task after another. + +Shader jest również zbiorem instrukcji, ale wykonywanych równocześnie dla każdego piksela na ekranie. Oznacza to, że kod, który piszesz musi działać inaczej w zależności od pozycji piksela na ekranie. Podobnie jak maszyna drukarska, twój program będzie działał jak funkcja matematyczna otrzymująca pozycję piksela i zwracająca jego kolor. Po skompilowaniu twój program będzie działał błyskawicznie. + +Shaders are also a set of instructions, but the instructions are executed all at once for every single pixel on the screen. That means the code you write has to behave differently depending on the position of the pixel on the screen. Like a type press, your program will work as a function that receives a position and returns a color, and when it's compiled it will run extraordinarily fast. + +![Chińska ruchoma czcionka](typepress.jpg) + +## Dlaczego shadery są szybkie? + +Aby odpowiedzieć na pytanie, omówmy cud *przetwarzania równoległego* (ang. *parallel processing*) + +To answer this, I present the wonders of *parallel processing*. + +Wyobraź sobie procesor twojego komputera jako pipeline, przez który przechodzą różnorakie zadania (jak na linii produkcyjnej w fabryce). Niektóre zadania są większe od innych, co oznacza, że wymagają więcej czasu i energii. Mówimy wtedy, że wymagają więcej *mocy obliczeniowej* (ang. *processing power*). Ze względu na architekturę współczesnych komputerów, zadania te wykonują się seryjnie (jeden po drugim) - każde zadanie musi poczekać, dopóki poprzednie zadanie nie zostanie ukończone. Jednakże, współczesne komputery posiadają zwykle więcej niż jedną jednostkę przetwarzają (np. 2, 4 lub 8 rdzeni procesora), które funkcjonują jak pomniejsze pipeline'y. Każda taki pomniejsze pipeline nazywany jest również *wątkiem* (ang. *thread*). + +Imagine the CPU of your computer as a big industrial pipe, and every task as something that passes through it - like a factory line. Some tasks are bigger than others, which means they require more time and energy to deal with. We say they require more processing power. Because of the architecture of computers the jobs are forced to run in a series; each job has to be finished one at a time. Modern computers usually have groups of four processors that work like these pipes, completing tasks one after another to keep things running smoothly. Each pipe is also known as a *thread*. + +![CPU](00.jpeg) + +Gry video i inne aplikacje graficzne wymagają zdecydowanie więcej mocy obliczeniowej niż większość programów, gdyż muszą wykonywać ogromne ilości operacji piksel po pikselu. Nie dość, że każdy pojedynczy piksel musi być obliczony, to w wypadku gier 3D dochodzą do tego obliczania geometryczne i obliczenie perspektywy. + +Video games and other graphic applications require a lot more processing power than other programs. Because of their graphic content they have to do huge numbers of pixel-by-pixel operations. Every single pixel on the screen needs to be computed, and in 3D games geometries and perspectives need to be calculated as well. + +Wróćmy do naszej metafory pipeline'u. Każdy piksel na ekranie reprezentuje proste zadanie. Indywidualnie zadania te nie stanowią problemu dla CPU, jednak sytuacja zmienia się, gdy takie zadanie musi być wykonane dla każdego piksela na ekranie. Oznacza to, że na starym monitorze 800x600 na jedną klatkę przypada 480.000 obliczeń, a na jedną sekundę - 14.400.000. Właśnie tak! Skala problemu może przeciążyć mikroprocesor. Na współczesnym monitorze 2560x1440 przy 60 FPS osiągamy 221.356.800 obliczeń na sekundę. Jak inżynierowie graficzni rozwiązują ten problem? + +Let's go back to our metaphor of the pipes and tasks. Each pixel on the screen represents a simple small task. Individually each pixel task isn't an issue for the CPU, but (and here is the problem) the tiny task has to be done to each pixel on the screen! That means in an old 800x600 screen, 480,000 pixels have to processed per frame which means 14,400,000 calculations per second! Yes! That’s a problem big enough to overload a microprocessor. In a modern 2880x1800 retina display running at 60 frames per second that calculation adds up to 311,040,000 calculations per second. How do graphics engineers solve this problem? + +![](03.jpeg) + +Z pomocą przychodzi przetwarzanie równoległe. Zamiast kilku dużych, potężnych mikroprocesorów (lub *rur*) lepiej mieć wiele małych mikroprocesorów działających równolegle. Tak właśnie działa procesor graficzna (GPU) w karcie graficznej. + +This is when parallel processing becomes a good solution. Instead of having a couple of big and powerful microprocessors, or *pipes*, it is smarter to have lots of tiny microprocessors running in parallel at the same time. That’s what a Graphic Processor Unit (GPU) is. + +![GPU](04.jpeg) + +Wyobraź sobie mały mikroprocesor jako tabele rur, a dane jako piłeczkę ping pongową. 14.400.000 piłeczek ping pongowych na sekundę może zablokować prawie każdą rurę. Ale tabela 800x600 malutkich rur przyjmująca co sekundę 30 fal po 480.000 pikseli poradzi sobie z nimi bez problemu. Tak samo działa to na wyższych rozdzielczościach - im więcej równolegle pracującego hardware'u, tym większy potok, z którym sobie poradzi. + +Picture the tiny microprocessors as a table of pipes, and the data of each pixel as a ping pong ball. 14,400,000 ping pong balls a second can obstruct almost any pipe. But a table of 800x600 tiny pipes receiving 30 waves of 480,000 pixels a second can be handled smoothly. This works the same at higher resolutions - the more parallel hardware you have, the bigger the stream it can manage. + +Inną "super umiejętnością" GPU jest fakt, że złożone funkcje matematyczne wykonywane są bezpośrednio na poziomie hardware'u przez mikroczipy, a nie przez software. Skutkiem tego są super szybkie operacje trygonometryczne i macierzowe. + +Another “super power” of the GPU is special math functions accelerated via hardware, so complicated math operations are resolved directly by the microchips instead of by software. That means extra fast trigonometrical and matrix operations - as fast as electricity can go. + +## Czym jest GLSL? + +GLSL oznacza "Open**GL** **S**hading **L**anguage" i stanowi standard pisania shaderów, który zobaczysz następnych rozdziałach tej książki. W zależności od hardware'u i systemu operacyjnego wyróżnia się też inne rodzaje shaderów. Tutaj skupimy się na specyfikacji OpenGL uregulowanej przez [Khronos Group](https://www.khronos.org/opengl/). Zrozumienie historii OpenGL może pomóc w zrozumieniu wielu dziwnych konwencji; w tym celu polecam zajrzeć do: [openglbook.com/chapter-0-preface-what-is-opengl.html](http://openglbook.com/chapter-0-preface-what-is-opengl.html). + +GLSL stands for openGL Shading Language, which is the specific standard of shader programs you'll see in the following chapters. There are other types of shaders depending on hardware and Operating Systems. Here we will work with the openGL specs regulated by [Khronos Group](https://www.khronos.org/opengl/). Understanding the history of OpenGL can be helpful for understanding most of its weird conventions, for that I recommend taking a look at: [openglbook.com/chapter-0-preface-what-is-opengl.html](http://openglbook.com/chapter-0-preface-what-is-opengl.html) + +## Dlaczego shadery budzą postrach? + +Jak to mówią: "with great power comes great responsibility". Stosuje się to również do obliczeń równoległych - potężne rozwiązania architektoniczne w GPU wiążą się również z pewnymi ograniczeniami. + +As Uncle Ben said “with great power comes great responsibility,” and parallel computation follows this rule; the powerful architectural design of the GPU comes with its own constraints and restrictions. + +Aby wątki mogły działać równolegle, muszą być od siebie niezależne. Mówimy, że wątki są *ślepe* na to, co robi reszta wątków. Ograniczenie to implikuje, że dane muszą "płynąć w ten samą stronę" - nie jest możliwe sprawdzić wynik innego wątku, zmodyfikować jego wejście albo przekazać wyjście jednego wątku do wejścia drugiego. + +In order to run in parallel every pipe, or thread, has to be independent from every other thread. We say the threads are *blind* to what the rest of the threads are doing. This restriction implies that all data must flow in the same direction. So it’s impossible to check the result of another thread, modify the input data, or pass the outcome of a thread into another thread. Allowing thread-to-thread communications puts the integrity of the data at risk. + +Poza tym GPU odpowiada za to, żeby każdy wątek miał coś do roboty, i żeby otrzymał dane potrzebne do jej wykonania. Nie jest możliwe, aby wątek wiedział, co robił sekundę temu. Mógł rysować przycisk w UI systemu operacyjnego, a potem renderować fragment nieba w grze wideo, a jeszcze potem wyświetlać treść maila. Każdy wątek jest nie tylko **ślepy**, ale również **bez pamięci**. Te cechy sprawiają, że pisanie shaderów nie cieszy się dużą popularnością wśród początkujących programistów. + +Also the GPU keeps the parallel micro-processor (the pipes) constantly busy; as soon as they get free they receive new information to process. It's impossible for a thread to know what it was doing in the previous moment. It could be drawing a button from the UI of the operating system, then rendering a portion of sky in a game, then displaying the text of an email. Each thread is not just **blind** but also **memoryless**. Besides the abstraction required to code a general function that changes the result pixel by pixel depending on its position, the blind and memoryless constraints make shaders not very popular among beginning programmers. + +Ale nie martw się! W następnych rozdziałąch nauczymy się, krok po kroku, prostych i zaawansowanych obliczeń shadingowych. Jeżeli czytasz to we współczesnej przeglądarce, to z pewnością docenisz zabawę z interaktywnymi przykładami. Ale nie przedłużajmy! Naciśnij *Next >>* aby przejść dalej. + +Don't worry! In the following chapters, we will learn step-by-step how to go from simple to advanced shading computations. If you are reading this with a modern browser, you will appreciate playing with the interactive examples. So let's not delay the fun any longer and press *Next >>* to jump into the code! From 7e6a6c233a2deec63c2b6bb06961d287a6360379 Mon Sep 17 00:00:00 2001 From: Wojtek Pachowiak Date: Sat, 14 Jan 2023 23:51:53 +0100 Subject: [PATCH 05/23] 04 --- 02/README-pl.md | 74 +++++++++++ 03/README-pl.md | 98 ++++++++++++++ 04/README-pl.md | 276 ++++++++++++++++++++++++++++++++++++++++ Questions_to_author.txt | 8 ++ 4 files changed, 456 insertions(+) create mode 100644 02/README-pl.md create mode 100644 03/README-pl.md create mode 100644 04/README-pl.md create mode 100644 Questions_to_author.txt diff --git a/02/README-pl.md b/02/README-pl.md new file mode 100644 index 0000000..2d37766 --- /dev/null +++ b/02/README-pl.md @@ -0,0 +1,74 @@ +## Hello World + +Zazwyczaj przykład "Hello world!" stanowi pierwszy krok przy nauce nowego języka. Jest to prosty jednolinijkowy programy, który zwraca pełną entuzjazmu wiadomość powitalną i tym samym zapowiada nadchodzące przygody. + +Usually the "Hello world!" example is the first step to learning a new language. It's a simple one-line program that outputs an enthusiastic welcoming message and declares opportunities ahead. + +W świecie GPU renderowanie tekstu jest jednak zbyt skomplikowanym zadaniem dla żółtodzioba. Zamiast tego wybierzemy jasny, serdeczny kolor by wykrzyczeć naszą ekscytację! + +In GPU-land rendering text is an overcomplicated task for a first step, instead we'll choose a bright welcoming color to shout our enthusiasm! + +
+ +Jeżeli czytasz tę książkę w przeglądarce: powyższy blok kodu jest interaktywny. Oznacza to, że możesz edytować dowolną linijkę kodu w celach eksploracyjnych. Shader kompiluje się na bieżąco, więc zmiany widoczne będą natychmiast. Spróbuj pozmieniać wartości w linijce 8. + +If you are reading this book in a browser the previous block of code is interactive. That means you can click and change any part of the code you want to explore. Changes will be updated immediately thanks to the GPU architecture that compiles and replaces shaders *on the fly*. Give it a try by changing the values on line 8. + +Choć kod jest prosty, to możemy wyciągnąć z niego ważne wnioski: + +1. Podobnie jak w C, język shadingowy ma jedną funkcje `main`. Pod koniec zwraca ona kolor. + +2. Finalny kolor piksela przypisywany jest do zarezerowanej zmiennej globalnej `gl_FragColor`. + +3. Ten C-podobny język ma wbudowane *zmienne* (jak `gl_FragColor`), *funkcje* i *typy*. W aktualnym przykładzie występuje jedynie typ `vec4`, oznaczający czterowymiarowy wektor zmiennoprzecinkowy ("float vector"). Później zobaczymy również takie typy jak `vec3`, `vec2` oraz znajome `float`, `int` i `bool`. + +4. Patrząc na typ `vec4`, możemy wywnioskować, że jego cztery argumenty odnoszą się do kanałów CZERWONEGO, ZIELONEGO, NIEBIESKIEGO i ALPHA. Widać też, że jego wartości są *znormalizowane*, więc znajdują się w zakresie od `0.0` do `1.0`. Później zobaczymy, jak normalizowanie wartości pomaga w *mapowaniu* wartości między zakresami. + +5. Kolejnym ważną C-podobną własnością w tym przykładzie jest obecność makr preprocessora. Dzięki nim można definiować zmienne globalne za pomocą `#define` oraz operacje warunkowe za pomocą `#ifdef` ("if defined"), `#ifndef` ("if not defined") i `#endif`. Wszystkie makra zaczynają się od płotka `#` kompilacją wszystkie ... W naszym powyższym przykładzie linijka 2 kompilowana jest tylko wtedy, gdy zmienna `GL_ES` jest zdefiniowana (jest na urządzeniach mobilnych i w przeglądarkach). + +Although these simple lines of code don't look like a lot, we can infer substantial knowledge from them: + +1. Shader Language has a single `main` function that returns a color at the end. This is similar to C. + +2. The final pixel color is assigned to the reserved global variable `gl_FragColor`. + +3. This C-flavored language has built in *variables* (like `gl_FragColor`), *functions* and *types*. In this case we've just been introduced to `vec4` that stands for a four dimensional vector of floating point precision. Later we will see more types like `vec3` and `vec2` together with the popular: `float`, `int` and `bool`. + +4. If we look closely to the `vec4` type we can infer that the four arguments respond to the RED, GREEN, BLUE and ALPHA channels. Also we can see that these values are *normalized*, which means they go from `0.0` to `1.0`. Later, we will learn how normalizing values makes it easier to *map* values between variables. + +5. Another important *C feature* we can see in this example is the presence of preprocessor macros. Macros are part of a pre-compilation step. With them it is possible to `#define` global variables and do some basic conditional operation (with `#ifdef` and `#endif`). All the macro commands begin with a hashtag (`#`). Pre-compilation happens right before compiling and copies all the calls to `#defines` and check `#ifdef` (is defined) and `#ifndef` (is not defined) conditionals. In our "hello world!" example above, we only insert the line 2 if `GL_ES` is defined, which mostly happens when the code is compiled on mobile devices and browsers. + +6. Typy zmiennoprzecinkowe są kluczowe w shaderach, więc ich poziom precyzji (ang. *precision*) jest kluczowy. Niższa precyzja oznacza szybsze renderowanie, ale kosztem jakości. Możesz być wybredny i określać precyzję każdej zmiennej zmiennoprzecinkowej z osobna. W linijce 2 (`precision mediump float;`) ustawiamy średnią precyzję zmiennych zmiennoprzecinkowych ("mediump", bo "medium precision"). Możemy też ustawić ją jako niską (`precision lowp float;`) lub wysoką (`precision highp float;`). + +7. Ostatni i chyba najważniejszy szczegół specyfikacji GLSL: nie ma gwaracji, że zmienne będą automatycznie castowane (np. z `int` do `float` przy dzieleniu liczby 5 przez 2). Producenci GPU mogą stosować przeróżne optymalizacje w kartach graficzncyh, ale muszą przy tym przestrzegać pewnych wytycznych. Automatyczne castowanie nie jest jednym z nich. W naszym przykładzie `vec4` ma precyzję zmiennoprzecinkową i dlatego jego argumenty wymagają `float`ów. Przezwyczaj się do stawiania kropek (`.`) we `float`ach (`1.` lub `1.0`, a nie `1`), jeżeli nie chcesz spędzić godzin przy debugowaniu. Poniższy kod nie zawsze będzie działa: + +```glsl +void main() { + gl_FragColor = vec4(1,0,0,1); // ERROR +} +``` + +Czas + +* Spróbuj zamienić `float`y na `int`y. Jeśli kod się nie kompiluje, to twoja karta graficzna nie toleruje + +* Zakomentuj linię 8 + +* Stwórz osobną funckję, która zwraca dowolny kolor i użyj jej w `main()`. Wskazówka: poniższy kod zwraca kolor czerwony: + +```glsl +vec4 red(){ + return vec4(1.0,0.0,0.0,1.0); +} +``` + +* Jest wiele sposobów tworzenia typu `vec4` - spróbuj je znaleźć. Jeden z nich wygląda tak: + +```glsl +vec4 color = vec4(vec3(1.0,0.0,1.0),1.0); +``` + +Choć przykład ten nie jest zbyt ekscytujący +W następnych rozdziałach zobaczymy, jak zmienić kolor piksela z pomocą inputu przestrzennego (położenie piksela na ekranie) i temporalnego (okres czasu od momentu załadowania się strony) + + diff --git a/03/README-pl.md b/03/README-pl.md new file mode 100644 index 0000000..640b69d --- /dev/null +++ b/03/README-pl.md @@ -0,0 +1,98 @@ +## Uniformy + +Do tej pory widzieliśmy jak GPU zarządza wieloma równoległymi wątkami, z który każdy odpowiada za kolor części renderowanego obrazu. Choć wątki nie komunikują się między sobą, to jednak muszą jakoś otrzymywać input z CPU. Ze względu na architekturę karty graficznej taki input musi być jednakowy (ang. *uniform*) dla wszystkich wątków i, z konieczności, tylko do odczytu. Innymi słowy, każdy wątek otrzymuje takie same dane, które może odczytać, ale nie nadpisać, zmienić. + +~~So far we have seen how the GPU manages large numbers of parallel threads, each one responsible for assigning the color to a fraction of the total image. Although each parallel thread is blind to the others, we need to be able to send some inputs from the CPU to all the threads. Because of the architecture of the graphics card those inputs are going to be equal (*uniform*) to all the threads and necessarily set as *read only*. In other words, each thread receives the same data which it can read but cannot change.~~ + +Inputy te nazywamy `uniform`ami i mogę być większości wspieranych typów: `float`, `vec2`, `vec3`, `vec4`, `mat2`, `mat3`, `mat4`, `sampler2D` i `samplerCube`. Uniformy definiowane są zwykle na górze shaderu zaraz po przypisaniu domyślnej precyzji floatów. + +~~These inputs are called `uniform` and come in most of the supported types: `float`, `vec2`, `vec3`, `vec4`, `mat2`, `mat3`, `mat4`, `sampler2D` and `samplerCube`. Uniforms are defined with the corresponding type at the top of the shader right after assigning the default floating point precision.~~ + +```glsl +#ifdef GL_ES +precision mediump float; +#endif + +uniform vec2 u_resolution; // wielkość/rozdzielczość kanwy (szerokość, wysokość) +uniform vec2 u_mouse; // pozycja myszy na kanwie (wyrażona w pikselach) +uniform float u_time; // czas w sekundach od załadowania shadera +``` + +Wyobraź sobie te uniformy jak małe mosty między CPU i GPU. Ich nazwy bywają różne, ale w tej książce używam: `u_time`, `u_resolution` i `u_mouse` (przeczytaj komentarze w kodzie, aby wiedzieć, co robią). Podążam za konwencją dodawnaia `u_` przed nazwą uniformów, aby było wiadomo, że nie są to zwykłe zmienne, ale ostatecznie jest to kwestia gustu. Przykładowo, [ShaderToy.com](https://www.shadertoy.com/) używa takich samych uniformów, ale z następującym nazewnictwem: + +~~You can picture the uniforms like little bridges between the CPU and the GPU. The names will vary from implementation to implementation but in this series of examples I’m always passing: `u_time` (time in seconds since the shader started), `u_resolution` (billboard size where the shader is being drawn) and `u_mouse` (mouse position inside the billboard in pixels). I’m following the convention of putting `u_` before the uniform name to be explicit about the nature of this variable but you will find all kinds of names for uniforms. For example [ShaderToy.com](https://www.shadertoy.com/) uses the same uniforms but with the following names:~~ + +```glsl +uniform vec3 iResolution; +uniform vec4 iMouse; +uniform float iTime; +``` +(zwróć uwagę, że `iResolution` jest typu `vec3`, a `iMouse` typu `vec4`; uniformy te zawierają po prostu dodatkowe informacje, np.: stosunek szerokości do wysokości pikseli na ekranie, czy któryś z przycisków myszy został kliknięty albo czy jest przytrzymywany) + +Koniec gadania, czas zobaczyć uniformy w akcji. W pożniszym kodzie używamy `u_time` (liczby sekund od uruchomienia shadera) razem z funkcją sinus, aby stworzyć animację przejścia od koloru czerwonego do czarnego. + + + +
+ +Jak widać GLSL skrywa wiele niespodzianek, na przykład w postaci specjalnych, zaimplementowanych w hardware'rze, funkcji trygonometryczne czy wykładniczych. Tutaj podaję część z nich: [`sin()`](../glossary/?search=sin), [`cos()`](../glossary/?search=cos), [`tan()`](../glossary/?search=tan), [`asin()`](../glossary/?search=asin), [`acos()`](../glossary/?search=acos), [`atan()`](../glossary/?search=atan), [`pow()`](../glossary/?search=pow), [`exp()`](../glossary/?search=exp), [`log()`](../glossary/?search=log), [`sqrt()`](../glossary/?search=sqrt), [`abs()`](../glossary/?search=abs), [`sign()`](../glossary/?search=sign), [`floor()`](../glossary/?search=floor), [`ceil()`](../glossary/?search=ceil), [`fract()`](../glossary/?search=fract), [`mod()`](../glossary/?search=mod), [`min()`](../glossary/?search=min), [`max()`](../glossary/?search=max) i [`clamp()`](../glossary/?search=clamp). + + +Pobawmy się powyższym kodem: + +* Zmniejsz częstotliwość tak bardzo, aby zmiany koloru stały się nie zauważalne. + +* Zwiększ częstotliwość do takiego stopnia, aby ujrzeć stały kolor bez migotania. + +* Wstaw funkcje sinus o różnych częstotliowściach do pozostałych kanałów (zielonego i niebieskiego), aby uzyskać ciekawe efekty. + + + +## gl_FragCoord + +GLSL daje nam nie tylko domyślny output `vec4 gl_FragColor`, ale również domyślny input w postaci `vec4 gl_FragCoord`, który przechowuje współrzędne *piksela* (inaczej: *fragmentu*), nad którym aktualnie pracuje wątek - dzięki `vec4 gl_FragCoord` wiemy, gdzie wątek pracuje wewnątrz kanwy. Nie nazywamy go `uniform`em, ponieważ jego wartość różni się między wątkami. Zamiast tego `gl_FragCoord` nazywamy *varying* (z ang. "zmieniający się", "różniący się"). + + + +
+ +W powyższy kodzie, *normalizujemy* współrzędne fragmentu poprzez podzielenie go przez rozdzielczość kanwy. W ten sposó otrzymujemy wartości z przedziału od `0.0` do `1.0`, co ułatwia zmapowanie współrzędnych x i y do, odpowiednio, czerwonego i zielonego kanału. + + + +W świecie shaderów nie mamy zbyt dużo sposóbów debuggowania poza przypisywaniem jaskrawych kolorów do zmiennych i wyciągania wniosków o działaniu shadera, na podstawie tego, co widzimy. Odkryjesz, że programowania GLSL jest często jak wkładanie miniaturowych statków do butelki - jest to trudne, ale tez piękne i satysfakcjonujące. + + + +![](08.png) + +Czas przetestować nasze rozumienie kodu: + +* Czy jesteś w stanie powiedzieć, gdzie na naszej kanwie znajduje się fragment o znormalizowanych współrzędnych `(0.0, 0.0)`? + +* Co z framgentami o znormalizowanych współrzędnych `(1.0, 0.0)`, `(0.0, 1.0)`, `(0.5, 0.5)` i `(1.0, 1.0)`? + +* Czy jesteś w stanie użyć uniforma `u_mouse` wiedząc, że wartości są nieznormalizowane? Spróbuj użyć go do manipulacji kolorem za pomocą ruchów myszki. + +* Czy jesteś sobie w stanie wyobrazić ciekawy sposób zmieniania koloru, łącząc współrzędne `u_mouse` z `u_time`? + +Po wykonaniu tych ćwiczeń, zapewne zastanawiasz się, gdzie jeszcze można użyć twoich nowych shaderowych mocy. W następnym rozdziale zobaczymy jak stworzyć swój własny shader w three.js, Processing i openFrameworks. + + diff --git a/04/README-pl.md b/04/README-pl.md new file mode 100644 index 0000000..44397c3 --- /dev/null +++ b/04/README-pl.md @@ -0,0 +1,276 @@ + +## Korzystanie z shaderów + +W ramach prac nad tą książką stworzyłem ekosystem narzędzi do tworzenia, wyświetlania, udostępniania i organizowania shaderów. Narzędzia te działają, bez konieczności dostosowywania kodu, na systemach Linux, MacOS, Windows i [Raspberry Pi](https://www.raspberrypi.org/) oraz w przeglądarce. + + + + + +## Korzystanie z shaderów w przeglądarce + +**Wyświetlaj**: wszystkie interaktywne przykłady w tej książce wyświetlane są dzięki [glslCanvas](https://github.com/patriciogonzalezvivo/glslCanvas), który znacząco ułatwia proces korzystania z shaderów. + + + +```html + +``` + +Jak widać, `glslCanvas` wymaga jedynie elementu `canvas` z `class="glslCanvas"` oraz URL do twojego shadera w `data-fragment-url`. Aby dowiedzieć się więcej, kliknij [tutaj](https://github.com/patriciogonzalezvivo/glslCanvas). + + + +Jeśli podobnie jak ja chciałbyś móć korzysatć z shaderów w konsoli, to [glslViewer](https://github.com/patriciogonzalezvivo/glslViewer) powinien cie zainteresować. Aplikacja ta pozwala zintegrować shadery z `bash`owymi skryptami i Unixowymi pipeline'ami, podobnie jak [ImageMagick](http://www.imagemagick.org/script/index.php). Ponadto, [glslViewer](https://github.com/patriciogonzalezvivo/glslViewer) pozwala ci kompilować shadery na [Raspberry Pi](https://www.raspberrypi.org/) - właśnie dlatego [openFrame.io](http://openframe.io/) używa go do wyświetalania swoich shaderowych dział sztuki. Kliknij [tutaj](https://github.com/patriciogonzalezvivo/glslViewer), aby dowiedzieć się więcej. + + + +```bash +glslViewer yourShader.frag yourInputImage.png —w 500 -h 500 -E screenshot,yourOutputImage.png +``` + +**Twórz**: w celu usprawnienia procesu pisania shaderów stworzyłem edytor online [glslEditor](https://github.com/patriciogonzalezvivo/glslEditor). Edytor ten jest wykorzystywany w interaktywnych przykładach tej książki. Dodaje on poręczne widżety, czyniące abstrakcyjne doświadczenie pracy z kodem GLSL bardziej uchwytnym. Możesz również korzystać z niego jako samodzielnej aplikacji webowej pod adresem [editor.thebookofshaders.com/](http://editor.thebookofshaders.com/). Kliknij [tutaj](https://github.com/patriciogonzalezvivo/glslEditor), aby dowiedzieć się więcej. + + + + +![](glslEditor-01.gif) + +Jeśli preferujesz pracę offline z wykorzystaniem [SublimeText](https://www.sublimetext.com/), [rozszerzenie glslViewer](https://packagecontrol.io/packages/glslViewer) może cie zainteresować. Dowiedz się o nim więcej [tutaj](https://github.com/patriciogonzalezvivo/sublime-glslViewer). + + + +![](glslViewer.gif) + +**Udostępniaj**: dzięki edytorowi online ([editor.thebookofshaders.com/](http://editor.thebookofshaders.com/)) możesz udstępniać swoje shadery! Zarówno webowa jak i stacjonarna wersja ma funkcję eksportu, generującą unikalny URL do twojego shadera. Ponadto, ma też funkcję bezpośredniego eksportu do [openFrame.io](http://openframe.io/). + + + +![](glslEditor-00.gif) + +**Organizuj**: udostępnianie kodu stanowi początek dzielenia się twoimi shaderowymi dziełami! Poza opcją eksportu do [openFrame.io](http://openframe.io/) stworzyłem narzędzie do organizowania twoich shaderów w galerię, którą można wstawić na dowolną stronę internetową; nazywa się [glslGallery](https://github.com/patriciogonzalezvivo/glslGallery). Kliknij [tutaj](https://github.com/patriciogonzalezvivo/glslGallery), aby dowiedzieć się więcej. + + + +![](glslGallery.gif) + + + +## Korzystanie shaderów w twoim ulubionym frameworku + +Jeżeli programowanie we frameworkach jak [Processing](https://processing.org/), [Three.js](http://threejs.org/), [OpenFrameworks](http://openframeworks.cc/) or [SFML](https://www.sfml-dev.org/) nie jest ci obce, to opcja wypróbowania w nich swoich shaderów zapewne cie zainteresuje. Poniżej znajdziesz przykłady, jak wykorzystać shadery w każdym z nich (z takimi samymi uniformami jak w tej książce). (W [repozytorium GitHub'owym dla tego rozdziału](https://github.com/patriciogonzalezvivo/thebookofshaders/tree/master/04) znajdziesz pełny kod źródłowy dla tych frameworków. + + + +### W **Three.js** + +Znakomity i bardzo skromny Ricardo Cabello (aka [MrDoob](https://twitter.com/mrdoob) ) razem z [kontrybutorami](https://github.com/mrdoob/three.js/graphs/contributors) tworzą prawdopodobnie najbardziej popularny framework WebGL'owy zwany [Three.js](http://threejs.org/). Znajdziesz wiele przykładów, tutoriali i książek, które uczą, jak wykorzstać tę JavaScriptową bibliotekę do tworzenia odjazdowej grafiki 3D. + + + +Poniżej znajduje się przykład kodu w HTML i JS potrzebny do rozpoczęcia przygody z shaderami w three.js. Zwróć uwage na skrypt z `id="fragmentShader"` - do niego możesz wstawiać kod shaderów, które znajdziesz, przykładowo, w tej książce. + + + +```html + +
+ + + + + +``` + +### W **Processing** + +Stworzony przez [Ben Fry](http://benfry.com/) i [Casey Reas](http://reas.com/) w 2001, [Processing](https://processing.org/) jest nadzwyczaj prostym i potężnym środowiskiem, w którym możesz zacząć swoją przygodę z programowaniem (tak było w moim wypadku). [Andres Colubri](https://codeanticode.wordpress.com/) wniósł istotne zmiany do OpenGL i funkcji wideo w Processing, znacząco ułatwiając wykorzystanie w nim shaderów GLSL. Processing szuka pliku `shader.frag` w folderze `data`. Zatem, jeśli chcesz spróbować uruchomić przykłady z tej książki w Processing, to pamiętaj umieścić je w tym folderze i odpowiednio nazwać. + + + +```cpp +PShader shader; + +void setup() { + size(640, 360, P2D); + noStroke(); + + shader = loadShader("shader.frag"); +} + +void draw() { + shader.set("u_resolution", float(width), float(height)); + shader.set("u_mouse", float(mouseX), float(mouseY)); + shader.set("u_time", millis() / 1000.0); + shader(shader); + rect(0,0,width,height); +} +``` + +Aby shader działał na wersjach wcześniejszych niż 2.1, dodaj poniższą linijkę na początku shadera: `#define PROCESSING_COLOR_SHADER`. Powinno to wyglądać tak: + + + +```glsl +#ifdef GL_ES +precision mediump float; +#endif + +#define PROCESSING_COLOR_SHADER + +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); +} +``` + +Jeśli chcesz wiedzieć więcej o sahderach w Processing, sprawdź ten [tutorial](https://processing.org/tutorials/pshader/). + + + +### W **openFrameworks** + +Każda ma takie miejsce, gdzie czuje się najabrdziej komfortowo. W moim wypadku jest to społeczność [openFrameworks](http://openframeworks.cc/). Ten C++'owy framework jest wrapperem OpenGL i innych open source'owych bibliotek C++. Pod pewnym względem jest całkiem podobny do Processing, ale z dodanym utrudnieniem radzenia sobie z kompilatorami C++. + + + +```cpp +void ofApp::draw(){ + ofShader shader; + shader.load("","shader.frag"); + + shader.begin(); + shader.setUniform1f("u_time", ofGetElapsedTimef()); + shader.setUniform2f("u_resolution", ofGetWidth(), ofGetHeight()); + ofRect(0,0,ofGetWidth(), ofGetHeight()); + shader.end(); +} +``` + +Polecam addon [ofxShader](https://github.com/patriciogonzalezvivo/ofxshader) do openFrameworks, jeśli potrzbujesz takiego zestawu uniformów jak w GlslViewer i GlslCanvas, wsparcia dla "multiple buffering", "material shaders", hot reload'owania oraz automatycznej konwersji do OpenGL ES na Raspberry Pi. Twój kod stanie się tak prosty jak poniżej: + + + +```cpp +//-------------------------------------------------------------- +void ofApp::setup(){ + ofDisableArbTex(); + + sandbox.allocate(ofGetWidth(), ofGetHeight()); + sandbox.load("grayscott.frag"); +} + +//-------------------------------------------------------------- +void ofApp::draw(){ + sandbox.render(); + sandbox.draw(0, 0); +} +``` + +Po więcej informacji na temat shaderów w openFrameworks zajrzyj do znakomitego [tutoriala](http://openframeworks.cc/ofBook/chapters/shaders.html) autorstwa [Joshua Noble](http://thefactoryfactory.com/). + + + +### W **Blender** + +[GlslTexture](https://github.com/patriciogonzalezvivo/glslTexture) to addon pozwalający programistycznie generować textury z użyciem shaderó GLSL. Jest on w pełni kompatybilny z resztą sandboxów w tym rozdziale. Jak go użyć? + + + + +1. Operator Search: `F3` (lub `Spacja`, w zależności od twojego setupu ). Wpisz `GlslTexture` + +![](blender/00.png) + +2. Zmień pola `width` (szerokość), `height` (wysokość) oraz `Source` (ścieżka pliku źródłowego; może być ścieżką do zewnętrznego pliku). + +![](blender/01.png) + +3. Wykorzystaj węzeł Image w zakładce Materials. Nazwa węzła Image będzie taka sama jak nazwa pliku źródłowego. + + +![](blender/02.png) + +4. Idź do zakładki Scripting (lub zewnętrznego edytora, jeśli twój plik źródłowy jest zewnętrzny) i zacznij edytować shader. Będzie hot reload'owany. + + +![](blender/03.png) diff --git a/Questions_to_author.txt b/Questions_to_author.txt new file mode 100644 index 0000000..ba283c8 --- /dev/null +++ b/Questions_to_author.txt @@ -0,0 +1,8 @@ +"Modern computers usually have groups of four processors that work like these pipes, completing tasks one after another" +- what is meant here by groups of four processors? Four CPU cores? +- fixed according to German version + + +Podać polskie tłumaczenie słowa pipeline +Podać angielskie tłumaczenie wejście i wyjście +Wytłumaczyć "hot reloading" (04) \ No newline at end of file From 10b35823b5240d5f5516ccc0fd07bfe11a418e81 Mon Sep 17 00:00:00 2001 From: Wojtek Date: Tue, 17 Jan 2023 16:35:27 +0100 Subject: [PATCH 06/23] 06 --- 06/README-pl.md | 219 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 219 insertions(+) create mode 100644 06/README-pl.md diff --git a/06/README-pl.md b/06/README-pl.md new file mode 100644 index 0000000..95bd046 --- /dev/null +++ b/06/README-pl.md @@ -0,0 +1,219 @@ +![Paul Klee - Color Chart (1931)](klee.jpg) + +## Kolory + + +Nie mieliśmy zbytnio okazji porozmawiać o typach wektorowych w GLSL. +Zanim przejdziemy dalej, ważne jest żebyśmy dowiedzieli się o nich więcej, a temat kolorów może być w tym bardzo pomocny. + + + +Jeżeli paradgymat programowania obiektowego jest ci bliski, to prawdopodobnie zauważyłeś, że proces wyciągania danych z wektorów wygląda podobnie przy C-podobnych `struct`'ach. + + + +```glsl +vec3 red = vec3(1.0,0.0,0.0); +red.x = 1.0; +red.y = 0.0; +red.z = 0.0; +``` + +Definiowanie kolor za pomocą notacji *x*, *y* i *z* jest trochę mylące, prawda? Właśnie dlatego istnieją inne sposoby dostępu do tej samej informacji, ale za pomocą różncyh nazw. Wartości `.x`, `.y` i `.z` mogą być również uzyskane za pomocą `.r`, `.g` i `.b`, jak i `.s`, `.t` i `.p` (`.s`, `.t` i `.p` są zwykle używane przy współrzędnych tekstur, które zobaczymy w następnych rozdziałach). Możesz również uzyskać dane wektora za pomocą indeksów `[0]`, `[1]` i `[2]`. + + + +Następujący kod przedstawia wszystkkie sposoby uzysakania tych samych danych: + + + +```glsl +vec4 vector; +vector[0] = vector.r = vector.x = vector.s; +vector[1] = vector.g = vector.y = vector.t; +vector[2] = vector.b = vector.z = vector.p; +vector[3] = vector.a = vector.w = vector.q; +``` + +Ta mnogość metod uzyskiwania tych samych danych jest tylko po to, aby ułatwić pisanie zrozumiałego kodu. Ta elastyczność wbudowana w język shadingowy stanowi też okazję, żebyś zaczął myśleć o współrzędnych koloru i przestrzeni jako zamiennych. + + + +Inną świetną własnością typów wektorowych w GLSL jest to, że współrzędne mogą być mieszane w dowolnej kolejności, co ułatwia castowanie i mieszanie wartości. Właśność ta nazywana jest *swizzle*'owaniem. + + + +```glsl +vec3 yellow, magenta, green; + +// Tworzenie żółtego +yellow.rg = vec2(1.0); // Przypisanie 1. do kanału czerwonego i zielonego +yellow[2] = 0.0; // Przypisanie 0. do kanału niebieskiego + +// Tworzenie magenty +magenta = yellow.rbg; // Przypisanie wektora z przestawionym kanałem zielonym i niebieskim + +// Tworzenie zielonego +green.rgb = yellow.bgb; // Przypisanie kanału niebieskiego do kanału czerwonego i niebieskiego +``` + + +### Mieszanie koloru + +Teraz, gdy już wiesz jak definiuje się kolory, pora na połączenie tego z naszą wcześniejszą wiedzą. W GLSL istnieje bardzo przydatna funkcja [`mix()`](../glossary/?search=mix), która pozwala mieszać dwie wartości wobec określonego stosunku wyrażonego w procentach. Potrafisz zgadnąć jaki jest zakres procentów? Oczywiście, że 0.0 i 1.0! Czas na wykorzystanie naszego shadingowego karate! + + + +![](mix-f.jpg) + +Sprawdź linijkę 18 poniższego kodu i zoabcz jak używamy wartości bezwględnej z sinusa od czasu, aby mieszać `colorA` i `colorB`. + + + +
+ +Pokaż na co cie stać: + + + +* Stwórz ekspresywną tranzycje między kolorami. Pomyśl o konkretnej emocji. Jaki kolor najlepiej ją reprezentuje? Jak wygląda? Jak zanika? Pomyśl o innej emocji i pasującym do niej kolorze. Zmień `colorA` i `colorB` w kodzie powyżej, aby pasowały do tych emocji. Następnie zanimuj tę tranzycję za pomocą funkcji kształtujących. Robert Penner stworzył serię popularnych funkcji kształtujących, z zasotoswaniami w animacji komputerowej, zwanych [easing functions](http://easings.net/), skorzystaj z [tego przykładu](../edit.php#06/easing.frag) jako inspiracji, ale najlepsze rezultaty osiągniesz tworząc własne tranzycje. + + + +### Zabawa z gradientem + +Funkcja [`mix()`](../glossary/?search=mix) ma więcej do zaoferowania. Zamiast pojedynczego `float`a, możemy podać zmienną tego samego typu, co dwa pierwsze argumenty; w naszym wypadku jest to `vec3`. W ten sposób zdobywamy kontrolę nad stosunkiem mieszania każdego indywidualnego kanału koloru, `r`, `g` i `b`. + + + +![](mix-vec.jpg) + +Spójrz na poniższy przykład. Tak jak w przykładach z poprzedniego rozdziału, podłączamy tranzycję do znormalizowanej współrzędnej `x` i wizualizujemy za pomocą linii. Aktualnie, wszystkie kanały leżą na tej samej linii. + + +Odkomentuj linjkę 25 i zobacz, co się stanie. Następnie odkomentuj linijki 26 i 27. Pamiętaj, że linie wizualizują stosunek mieszania każdego z kanałów wektorów `colorA` i `colorB`. + + + +
+ +Prawdopodobnie rozpoznajesz trzy funkcje kształtującego, które używamy w linijkach 25 i 27. Baw się nimi! Czas pokazać swoje umiejętności z poprzednich rozdziałów, tworząc interesujące gradienty. Spróbuj następujących ćwiczeń: + +![William Turner - The Fighting Temeraire (1838)](turner.jpg) + +* Skomponuj gradient przypominający zachód słońca Williama Turnera. + +* Zanimuj tranzycje między wschodem i zachodem za pomocą `u_time`. + +* Czy potrafisz stworzyć tęczę korzystając z tego, czego nauczyliśmy się dotychaczas? + +* Użyj `step()`, by stworzyć kolorową flagę. + + + +### HSB + +Nie da się mówić o kolorze bez poruszenia tematu przestrzeni barw. Jak prawdopodobnie wiesz, istnieją też inne sposoby reprezentacji koloru poza RGB (z kanałem czerwonym, zielonym i niebieskim). + +[HSB](http://en.wikipedia.org/wiki/HSL_and_HSV) oznacza Hue (pol. "barwa"), Saturation (pol. "nasycenie") i Brightness (pol. "jasność) i jest o wiele bardziej intuicyjną reprezentacją koloru niż RGB. Czasem zamiast Brightness używa sie Value, stąd zamiast HSB można spotkać się też z HSV. Przyjrzyj się funkcjom `rgb2hsv()` i `hsv2rgb()` w następującym kodzie: + + + + + +Mapując pozycję na osi x do barwy i pozycję na osi y do jasności, otrzymujemy spektrum widzialnych kolorów. O wiele bardziej intuicyjnie wybiera się kolor HSB niż RGB. + + + +
+ +### HSB we współrzędnych biegunowych + +Oryginalnie, HSB miało być reprezentowane z pomocą współrzędnych biegunowych (opartych na kącie i promieniu), a nie kartezjańskich (opartych na x i y). By zpamować naszą funkcję HSB do współrzędnych biegunowych, musimy otrzymać kąt i dystans wektora od centrum kanwy do współrzędnej piksela. W tym celu użyjemy funkcje [`length()`](../glossary/?search=length) i [`atan(y,x)`](../glossary/?search=atan) (który jest odpowiednikami `atan2(y,x)` w GLSL). + + + + + + + +**Uwaga:** Jest weięcej funkcji geometrycznych poza [`length`](../glossary/?search=length) jak: [`distance()`](../glossary/?search=distance), [`dot()`](../glossary/?search=dot), [`cross`](../glossary/?search=cross), [`normalize()`](../glossary/?search=normalize), [`faceforward()`](../glossary/?search=faceforward), [`reflect()`](../glossary/?search=reflect) i [`refract()`](../glossary/?search=refract). Ponadto, GLSL ma specjalne funkcje do porównywania wektorów: [`lessThan()`](../glossary/?search=lessThan), [`lessThanEqual()`](../glossary/?search=lessThanEqual), [`greaterThan()`](../glossary/?search=greaterThan), [`greaterThanEqual()`](../glossary/?search=greaterThanEqual), [`equal()`](../glossary/?search=equal) i [`notEqual()`](../glossary/?search=notEqual). + + + +Gdy już zdobędziemy kąt i promień, musimy znormalizować ich wartości do zakresu od 0.0 do 1.0. W linijce 27, [`atan(y,x)`](../glossary/?search=atan) zwróci kąt w radianach między -PI a PI (-3.14 a 3.14), więc musimy podzielić tę liczbę przez `TWO_PI` (zdefiniowane na górze kodu), uzyskując wartości między -0.5 i 0.5, które, przez proste dodawanie, mapujemy dalej do zakresu od 0.0 do 1.0. Promień ma długość 0.5 (ponieważ liczymy odległość od środka TODO kanwy), więc musimy podwoić ten zakres (mnożąc przez 2), by uzyskać 1.0. + + + +Jak widzisz, sedno leży w transformowaniu i mapowaniu zakresów do 0.0 i 1.0. + + + +
+ +Spróuj poniższych ćwiczeń: + + + +* Zmodyfikuj przykład ze współrzędnymi biegunowymi, aby uzyskać kręcące się (jak w ikonce czekania myszki) koło barw. + +* Użyj funkcji kształtującej razem z funkcją konwersji z HSB do RGB, aby rozszerzyć jedną barwę i zwężyć inną. + + + + +![William Home Lizars - Red, blue and yellow spectra, with the solar spectrum (1834)](spectrums.jpg) + +* Jeśli przyjrzysz się uważnie kołom barw używanym w narzędziach do wybierania koloru (ang "color picker") (spójrz na obrazek poniżej), zobaczysz, że używają innego sepktrum koloru, zgodnego z przestrzenią barw RYB. Przykładowo, kolorem przeciwnym do czerwonego powienien być zielony, ale w naszym przykładzie jest cyjan. Czy potrafiłbyś zrekonstruować poniższy obrazek? [Wskazówka: to dobry moment, by użyć funkcji kształtujących] + + + +![](colorwheel.png) + +* Przeczytaj [książkę Josefa Albersa _Interaction of Color_](http://www.goodreads.com/book/show/111113.Interaction_of_Color) i przestudiuj poniższe przykłady shaderów. + + + +
+ +#### Uwaga o funkcjach i ich argumentach + +Zanim przeskoczysz do następnego rozdziału, zatrzymajmy się na chwilę. Wróć do funkcji `hsb2rgb` z poprzedniego interaktywnego przykładu. Zauważysz `in` przed typem argumentu. Jest to [*kwalifikator*](http://www.shaderific.com/glsl-qualifiers/#inputqualifier) (ang. "qualifier") i akurat ten oznacza, że zmienna jest tylko do odczytu. W przyszłości zobaczymy, że jest również możliwe, by poprzedzić argumenty kwalifikatorami `out` i `inout`. `out` określa, że argument jest tylko do zapisu, natomiast `inout` działa podobnie jak przekazywanie argumentu przez referencje, co umożliwia modyfikowanie go. + + + +```glsl +int newFunction(in vec4 aVec4, // read-only + out vec3 aVec3, // write-only + inout int aInt); // read-write +``` + +Może w to nie uwierzysz, ale mamy wszystkie składniki potrzbne do tworzenia fajnych rysunków. W następnym rozdziale nauczymy się jak połączyć wszystkie poznane tricki, by stworzyć geometryczne formy przez *blendowanie* przestrzeni. Dobrze słyszysz... *blendowanie* przestrzeni. + +You may not believe it but now we have all the elements to make cool drawings. In the next chapter we will learn how to combine all our tricks to make geometric forms by *blending* the space. Yep... *blending* the space. From 01d01fe0c958f033a2bceee6294a29ce47cc24d3 Mon Sep 17 00:00:00 2001 From: Wojtek Date: Fri, 20 Jan 2023 16:21:00 +0100 Subject: [PATCH 07/23] half 07 --- 06/README-pl.md | 2 +- 07/README-pl.md | 293 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 294 insertions(+), 1 deletion(-) create mode 100644 07/README-pl.md diff --git a/06/README-pl.md b/06/README-pl.md index 95bd046..908493b 100644 --- a/06/README-pl.md +++ b/06/README-pl.md @@ -216,4 +216,4 @@ int newFunction(in vec4 aVec4, // read-only Może w to nie uwierzysz, ale mamy wszystkie składniki potrzbne do tworzenia fajnych rysunków. W następnym rozdziale nauczymy się jak połączyć wszystkie poznane tricki, by stworzyć geometryczne formy przez *blendowanie* przestrzeni. Dobrze słyszysz... *blendowanie* przestrzeni. -You may not believe it but now we have all the elements to make cool drawings. In the next chapter we will learn how to combine all our tricks to make geometric forms by *blending* the space. Yep... *blending* the space. + diff --git a/07/README-pl.md b/07/README-pl.md new file mode 100644 index 0000000..401dbf7 --- /dev/null +++ b/07/README-pl.md @@ -0,0 +1,293 @@ +![Alice Hubbard, Providence, USA, ca. 1892. Zdjęcie: Zindman/Freemont.](froebel.jpg) + +## Kształty + +Nareszcie! Czekaliśmy na ten moment! Poznałeś większość podstaw GLSL, jego typów i funkcji. Ćwiczyłeś również wykorzystanie funkcji kształtujących. Teraz nadszedł czas, aby połączyć to wszystko w całość. Jesteś w stanie sprostać temu wyzwaniu! W tym rozdziale dowiesz się, jak procedrualnie i równolegle rysować proste kształty. + + + +### Prostokąt + +Wyobraźmy sobie, że mamy papier w kratkę, taki jaki używaliśmy na lekcjach matematyki i naszym zadaniem domowym jest narysowanie kwadratu. Rozmiar papieru to 10x10, a kwadrat ma mieć wymiary 8x8. Co zrobisz? + + + +![](grid_paper.jpg) + +Zamalowałbyś wszystko poza pierwszym i ostatnim rzędem oraz pierwszą i ostatnią kolumną, tak? + + + +Jak to się ma do shaderów? Każdy mały kwadracik naszego papieru siatkowego to wątek (piksel). Każdy mały kwadrat zna swoje położenie, podobne do współrzędnych na szachownicy. W poprzednich rozdziałach zmapowaliśmy *x* i *y* na kanały kolorów *czerwony* i *zielony* oraz nauczyliśmy się korzystać z ciasnego dwuwymiarowego terytorium pomiędzy 0.0 a 1.0. Jak możemy tę wiedzę wykorzystać, aby narysować wyśrodkowany kwadrat na środku naszej kanwy? + + + +Zacznijmy od naszkicowania pseudokodu, który używa `if`ów na współrzędnych kanwy. Zasady, aby to zrobić, są nadzwyczaj podobne do tego, jak myślimy o sytuacji z papieram w kratke. + + + +```glsl +if ( (X WIĘKSZE NIŻ 1) ORAZ (Y WIĘKSZE NIŻ 1) ) + pomaluj na biało +else + pomaluj na czarno +``` + +Teraz, gdy mamy lepsze wyobrażenie o tym, jak to będzie działać, zastąpmy `if`a funkcją [`step()`](../glossary/?search=step), a zamiast używać współrzędnych 10x10 użyjmy znormalizowanych odpowiedników pomiędzy 0.0 a 1.0: + + + +```glsl +uniform vec2 u_resolution; + +void main(){ + vec2 st = gl_FragCoord.xy/u_resolution.xy; + vec3 color = vec3(0.0); + + // Obie linijki zwracają 1.0 (biały) lub 0.0 (czarny). + float left = step(0.1,st.x); // Równoważnie: (X WIĘKSZE NIŻ 0.1) + float bottom = step(0.1,st.y); // Równoważnie: (Y WIĘKSZE NIŻ 0.1) + + // Mnożenie left*bottom jest podobne do logicznego AND. + color = vec3( left * bottom ); + + gl_FragColor = vec4(color,1.0); +} +``` + +Funkcja [`step()`](../glossary/?search=step) "pomaluje" każdy piksel poniżej 0.1 na czarno (`vec3(0.0)`) a resztę na biało (`vec3(1.0)`). Mnożenie pomiędzy `left` i `bottom` działa jak logiczna operacja `AND`, gdzie obie muszą być 1.0 aby zwrócić 1.0, a gdy przynajmniej jedna jest 0.0, to obie są 0.0. W efekcie otrzymujemy dwie czarne linie, jedną na dole, a drugą po lewej stronie kanwy. + + + +![](rect-01.jpg) + +W poprzednim kodzie powtarzamy funkcję [`step()`](../glossary/?search=step) dla każdej osi (lewej i dolnej). Możemy zaoszczędzić kilka linii kodu, przekazując obie wartości razem zamiast pojedynczo. Wygląda to następująco: + + + +```glsl +vec2 borders = step(vec2(0.1),st); +float pct = borders.x * borders.y; +``` + +Do tej pory narysowaliśmy tylko dwie krawędzie (dolna-lewa) naszego prostokąta. Dorysujmy teraz dwie pozostałe (górna-prawa). Sprawdź następujący kod: + + + +
+ +Odkomentuj *linijki 21-22* i zobacz jak odwracamy współrzędne `st` - w ten sposób `vec2(0,0,0)` znajdzie się w prawym górnym rogu. Otrzymaliśmy odbicie lustrzane. Teraz wystarczy przekazać te odwrócone współrzędne do [`step()`](../glossary/?search=step). + + + +![](rect-02.jpg) + +Zwróć uwagę, że w *linijkach 18 i 22* wszystkie boki są mnożone przez siebie. Jest to równoznaczne z napisaniem: + + + +```glsl +vec2 bl = step(vec2(0.1),st); // bottom-left +vec2 tr = step(vec2(0.1),1.0-st); // top-right +color = vec3(bl.x * bl.y * tr.x * tr.y); +``` + +Ciekawe, prawda? W tej technice chodzi o wykorzystanie [`step()`](../glossary/?search=step), przerzucania współrzędnych oraz mnożenia (do operacji logicznych). + + + +Zanim przejdziesz dalej, spróbuj wykonać następujące ćwiczenia: + +* Zmień rozmiar i proporcje prostokąta. + +* Użyj [`smoothstep()`](../glossary/?search=smoothstep) zamiast [`step()`](../glossary/?search=step). Zauważ, że zmieniając wartości, możesz przejść od rozmytych krawędzi do eleganckich gładkich granic. + +* Zaimplementuj to samo, ale za pomocą [`floor()`](../glossary/?search=floor)(+ mnożenia i dzielenia). + +* Wybierz implementację, którą najbardziej lubisz i zrób z niej funkcję, którą możesz ponownie wykorzystać w przyszłości. Spraw, aby twoja funkcja była elastyczna i wydajna. + +* Zrób inną funkcję, która po prostu rysuje kontur prostokąta. + +* Jak myślisz, jak można narysować różne prostokąty na tej samej kanwie? Jeśli wymyślisz jak, pochwal się swoimi umiejętnościami, tworząc kompozycję z prostokątów i kolorów, która przypomina obraz [Pieta Mondriana](http://en.wikipedia.org/wiki/Piet_Mondrian). + + + +![Piet Mondrian - Tableau (1921)](mondrian.jpg) + +### Koła + +Łatwo jest rysować kwadraty na papierze w kratkę i prostokąty na współrzędnych kartezjańskich, ale okręgi wymagają innego podejścia, zwłaszcza że potrzebujemy algorytmu działającego na każdym pikselu z osobna. Jednym z rozwiązań jest *zmapowanie* współrzędnych tak, abyśmy mogli użyć funkcji [`step()`](../glossary/?search=step) do narysowania okręgu. + +Jak to zrobić? Przypomnijmy sobie lekcje matematyki, gdzie rozpościeraliśmy ramiona cyrkla na promień okręgu, wciskaliśmy jedno ramię cyrkla w środek okręgu, a następnie obrysowywaliśmy krawędź okręgu obracając drugie ramię. + + + +![](compass.jpg) + +Przełożenie tego na shader, w którym każdy piksel jast jak kratka na papierze, implikuje *zadawanie* każdemu pikselowi (wątkowi) pytania, czy znajduje się wewnątrz obszaru koła. Robimy to poprzez obliczenie odległości od danego piksela do środka okręgu. + + + +![](circle.jpg) + +Istnieje kilka sposobów na obliczenie tej odległości. Najprostszy z nich wykorzystuje funkcję [`distance()`](../glossary/?search=distance), która oblicza [`length()`](../glossary/?search=length) różnicy pomiędzy dwoma punktami (w naszym przypadku współrzędną piksela i środkiem kanwy). Funkcja `length()` to nic innego jak przekształcone twierdzenie Pitagorasa: + + + +![](hypotenuse.png) + +Możesz użyć [`distance()`](../glossary/?search=distance), [`length()`](../glossary/?search=length) lub [`sqrt()`](../glossary/?search=sqrt) aby obliczyć odległość do centrum kanwy. Poniższy kod zawiera te trzy funkcje i nie zaskakuje fakt, że każda z nich zwraca dokładnie taki sam wynik. + + + +Komentuj i odkomentuj linijki, aby wypróbować różne sposoby uzyskania tego samego wyniku. + + + +
+ +W powyższym przykładzie mapujemy odległość do centrum kanwy na jasność piksela. Im bliżej centrum znajduje się piksel, tym niższą (ciemniejszą) ma wartość. Zauważ, że wartości nie są zbyt wysokie, ponieważ od centrum ( `vec2(0.5, 0.5)` ) maksymalna odległość ledwo przekracza 0.5. Pokontempluj nad dokonanym mapowaniem i pomyśl: + + + +* Co można z niego wywnioskować? + +* Jak możemy je użyć do narysowania koła? + +* Zmodyfikuj powyższy kod, aby zawrzeć cały gradient wewnątrz kanwy. (Wskazówka: użyj mnożenia) + + + +### Distance field + +Możemy również myśleć o powyższym przykładzie jako o mapie wysokości, gdzie ciemniejszy kolor oznacza wyższy. Gradient pokazuje nam coś podobnego do wzoru tworzonego przez stożek. Wyobraź sobie, że jesteś na szczycie tego stożka. Pozioma odległość do krawędzi stożka wynosi 0,5. Będzie ona stała we wszystkich kierunkach. Wybierając miejsce "przecięcia" stożka otrzymamy większą lub mniejszą powierzchnię kołową. + + + +![](distance-field.jpg) + +Basically we are using a re-interpretation of the space (based on the distance to the center) to make shapes. This technique is known as a “distance field” and is used in different ways from font outlines to 3D graphics. + +Try the following exercises: + +* Use [`step()`](../glossary/?search=step) to turn everything above 0.5 to white and everything below to 0.0. + +* Inverse the colors of the background and foreground. + +* Using [`smoothstep()`](../glossary/?search=smoothstep), experiment with different values to get nice smooth borders on your circle. + +* Once you are happy with an implementation, make a function of it that you can reuse in the future. + +* Add color to the circle. + +* Can you animate your circle to grow and shrink, simulating a beating heart? (You can get some inspiration from the animation in the previous chapter.) + +* What about moving this circle? Can you move it and place different circles in a single billboard? + +* What happens if you combine distances fields together using different functions and operations? + +```glsl +pct = distance(st,vec2(0.4)) + distance(st,vec2(0.6)); +pct = distance(st,vec2(0.4)) * distance(st,vec2(0.6)); +pct = min(distance(st,vec2(0.4)),distance(st,vec2(0.6))); +pct = max(distance(st,vec2(0.4)),distance(st,vec2(0.6))); +pct = pow(distance(st,vec2(0.4)),distance(st,vec2(0.6))); +``` + +* Make three compositions using this technique. If they are animated, even better! + +#### For your tool box + +In terms of computational power the [`sqrt()`](../glossary/?search=sqrt) function - and all the functions that depend on it - can be expensive. Here is another way to create a circular distance field by using [`dot()`](../glossary/?search=dot) product. + +
+ +### Useful properties of a Distance Field + +![Zen garden](zen-garden.jpg) + +Distance fields can be used to draw almost everything. Obviously the more complex a shape is, the more complicated its equation will be, but once you have the formula to make distance fields of a particular shape it is very easy to combine and/or apply effects to it, like smooth edges and multiple outlines. Because of this, distance fields are popular in font rendering, like [Mapbox GL Labels](https://blog.mapbox.com/drawing-text-with-signed-distance-fields-in-mapbox-gl-b0933af6f817), [Matt DesLauriers](https://twitter.com/mattdesl) [Material Design Fonts](http://mattdesl.svbtle.com/material-design-on-the-gpu) and [as is described on Chapter 7 of iPhone 3D Programming, O’Reilly](http://chimera.labs.oreilly.com/books/1234000001814/ch07.html#ch07_id36000921). + +Take a look at the following code. + +
+ +We start by moving the coordinate system to the center and shrinking it in half in order to remap the position values between -1 and 1. Also on *line 24* we are visualizing the distance field values using a [`fract()`](../glossary/?search=fract) function making it easy to see the pattern they create. The distance field pattern repeats over and over like rings in a Zen garden. + +Let’s take a look at the distance field formula on *line 19*. There we are calculating the distance to the position on `(.3,.3)` or `vec3(.3)` in all four quadrants (that’s what [`abs()`](../glossary/?search=abs) is doing there). + +If you uncomment *line 20*, you will note that we are combining the distances to these four points using the [`min()`](../glossary/?search=min) to zero. The result produces an interesting new pattern. + +Now try uncommenting *line 21*; we are doing the same but using the [`max()`](../glossary/?search=max) function. The result is a rectangle with rounded corners. Note how the rings of the distance field get smoother the further away they get from the center. + +Finish uncommenting *lines 27 to 29* one by one to understand the different uses of a distance field pattern. + +### Polar shapes + +![Robert Mangold - Untitled (2008)](mangold.jpg) + +In the chapter about color we map the cartesian coordinates to polar coordinates by calculating the *radius* and *angles* of each pixel with the following formula: + +```glsl +vec2 pos = vec2(0.5)-st; +float r = length(pos)*2.0; +float a = atan(pos.y,pos.x); +``` + +We use part of this formula at the beginning of the chapter to draw a circle. We calculated the distance to the center using [`length()`](../glossary/?search=length). Now that we know about distance fields we can learn another way of drawing shapes using polar coordinates. + +This technique is a little restrictive but very simple. It consists of changing the radius of a circle depending on the angle to achieve different shapes. How does the modulation work? Yes, using shaping functions! + +Below you will find the same functions in the cartesian graph and in a polar coordinates shader example (between *lines 21 and 25*). Uncomment the functions one-by-one, paying attention the relationship between one coordinate system and the other. + +
+ +
+ +Try to: + +* Animate these shapes. +* Combine different shaping functions to *cut holes* in the shape to make flowers, snowflakes and gears. +* Use the `plot()` function we were using in the *Shaping Functions Chapter* to draw just the contour. + +### Combining powers + +Now that we've learned how to modulate the radius of a circle according to the angle using the [`atan()`](../glossary/?search=atan) to draw different shapes, we can learn how use `atan()` with distance fields and apply all the tricks and effects possible with distance fields. + +The trick will use the number of edges of a polygon to construct the distance field using polar coordinates. Check out [the following code](http://thndl.com/square-shaped-shaders.html) from [Andrew Baldwin](https://twitter.com/baldand). + +
+ +* Using this example, make a function that inputs the position and number of corners of a desired shape and returns a distance field value. + +* Mix distance fields together using [`min()`](../glossary/?search=min) and [`max()`](../glossary/?search=max). + +* Choose a geometric logo to replicate using distance fields. + +Congratulations! You have made it through the rough part! Take a break and let these concepts settle - drawing simple shapes in Processing is easy but not here. In shader-land drawing shapes is twisted, and it can be exhausting to adapt to this new paradigm of coding. + +Down at the end of this chapter you will find a link to [PixelSpirit Deck](https://patriciogonzalezvivo.github.io/PixelSpiritDeck/) this deck of cards will help you learn new SDF functions, compose them into your designs and use on your shaders. The deck has a progressive learning curve, so taking one card a day and working on it will push and challenge your skills for months. + +Now that you know how to draw shapes I'm sure new ideas will pop into your mind. In the following chapter you will learn how to move, rotate and scale shapes. This will allow you to make compositions! From 90f687832fdf1028646f5dd8b30795b57f372b9c Mon Sep 17 00:00:00 2001 From: Wojtek Date: Tue, 24 Jan 2023 16:11:48 +0100 Subject: [PATCH 08/23] 07 --- 07/README-pl.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/07/README-pl.md b/07/README-pl.md index 401dbf7..348514e 100644 --- a/07/README-pl.md +++ b/07/README-pl.md @@ -178,7 +178,7 @@ W powyższym przykładzie mapujemy odległość do centrum kanwy na jasność pi ### Distance field -Możemy również myśleć o powyższym przykładzie jako o mapie wysokości, gdzie ciemniejszy kolor oznacza wyższy. Gradient pokazuje nam coś podobnego do wzoru tworzonego przez stożek. Wyobraź sobie, że jesteś na szczycie tego stożka. Pozioma odległość do krawędzi stożka wynosi 0,5. Będzie ona stała we wszystkich kierunkach. Wybierając miejsce "przecięcia" stożka otrzymamy większą lub mniejszą powierzchnię kołową. +Możemy również myśleć o powyższym przykładzie jako o mapie wysokości, gdzie im ciemniej tym wyżej. Gradient pokazuje nam coś podobnego do wzoru tworzonego przez stożek. Wyobraź sobie, że jesteś na szczycie tego stożka. Pozioma odległość do krawędzi stożka wynosi 0.5. Będzie ona stała we wszystkich kierunkach. Wybierając miejsce "przecięcia" stożka otrzymamy większą lub mniejszą powierzchnię kołową. From 70bc132fc0aec618696ef8fba9d393329ee8ca28 Mon Sep 17 00:00:00 2001 From: Wojtek Date: Tue, 24 Jan 2023 16:11:56 +0100 Subject: [PATCH 09/23] 07 --- 07/README-pl.md | 128 +++++++++++++++++++++++++++++++--------- Questions_to_author.txt | 3 +- 2 files changed, 101 insertions(+), 30 deletions(-) diff --git a/07/README-pl.md b/07/README-pl.md index 348514e..00f621d 100644 --- a/07/README-pl.md +++ b/07/README-pl.md @@ -184,9 +184,30 @@ Możemy również myśleć o powyższym przykładzie jako o mapie wysokości, gd ![](distance-field.jpg) -Basically we are using a re-interpretation of the space (based on the distance to the center) to make shapes. This technique is known as a “distance field” and is used in different ways from font outlines to 3D graphics. +Zasadniczo używamy reinterpretacji przestrzeni (w oparciu o odległość do centrum), aby tworzyć kształty. Ta technika jest znana jako "pole odległości" (ang "distance field") i jest używana na różne sposoby, od konturów czcionek do grafiki 3D. -Try the following exercises: + + +Spróbuj następujących ćwiczeń: + +* Użyj [`step()`](../glossary/?search=step), aby zamienić wszystko powyżej 0.5 na białe, a wszystko poniżej na czarne. + +* Odwróć kolory tła i pierwszego planu. + +* Używając [`smoothstep()`](../glossary/?search=smoothstep), poeksperymentuj z różnymi wartościami, aby uzyskać ładne, gładkie granice na swoim okręgu. + +* Gdy już będziesz zadowolony ze swojej implementacji, stwórz z niej funkcję, którą będziesz mógł ponownie wykorzystać w przyszłości. + +* Dodaj kolor do koła. + +* Czy możesz zanimować swój krąg, aby rosnął i kurczył się, symulując bijące serce? (Możesz zaczerpnąć inspirację z animacji w poprzednim rozdziale). + +* A co z przesuwaniem tego okręgu? Czy możesz go przesuwać i umieszczać różne okręgi na jednej kanwie? + +* Co się stanie, jeśli połączysz pola odległości razem, używając różnych funkcji i operacji? + + + ```glsl pct = distance(st,vec2(0.4)) + distance(st,vec2(0.6)); @@ -212,51 +233,76 @@ pct = max(distance(st,vec2(0.4)),distance(st,vec2(0.6))); pct = pow(distance(st,vec2(0.4)),distance(st,vec2(0.6))); ``` -* Make three compositions using this technique. If they are animated, even better! +* Zrób trzy kompozycje z wykorzystaniem tej techniki. Jeśli są one animowane, jeszcze lepiej! + + + +#### Twoja skrzynka z narzędziami -#### For your tool box +Pod względem mocy obliczeniowej funkcja [`sqrt()`](../glossary/?search=sqrt) - i wszystkie funkcje, które od niej zależą - mogą być kosztowne. Oto inny sposób tworzenia okrągłego pola odległości za pomocą produktu skalarnego [`dot()`](../glossary/?search=dot): -In terms of computational power the [`sqrt()`](../glossary/?search=sqrt) function - and all the functions that depend on it - can be expensive. Here is another way to create a circular distance field by using [`dot()`](../glossary/?search=dot) product. +
-### Useful properties of a Distance Field +### Przydatne własności Pól Odległości -![Zen garden](zen-garden.jpg) +![ogórd Zen](zen-garden.jpg) -Distance fields can be used to draw almost everything. Obviously the more complex a shape is, the more complicated its equation will be, but once you have the formula to make distance fields of a particular shape it is very easy to combine and/or apply effects to it, like smooth edges and multiple outlines. Because of this, distance fields are popular in font rendering, like [Mapbox GL Labels](https://blog.mapbox.com/drawing-text-with-signed-distance-fields-in-mapbox-gl-b0933af6f817), [Matt DesLauriers](https://twitter.com/mattdesl) [Material Design Fonts](http://mattdesl.svbtle.com/material-design-on-the-gpu) and [as is described on Chapter 7 of iPhone 3D Programming, O’Reilly](http://chimera.labs.oreilly.com/books/1234000001814/ch07.html#ch07_id36000921). +Pola odległości mogą być używane do rysowania prawie wszystkiego. Oczywiście im bardziej złożony jest kształt, tym bardziej skomplikowane będzie jego równanie, ale gdy już masz formułę do tworzenia pól odległości danego kształtu, bardzo łatwo jest połączyć i/lub zastosować do niego efekty, takie jak gładkie krawędzie i wiele konturów. Z tego powodu, pola odległości są popularne w renderowaniu czcionek, takich jak [Mapbox GL Labels](https://blog.mapbox.com/drawing-text-with-signed-distance-fields-in-mapbox-gl-b0933af6f817), [Matt DesLauriers](https://twitter.com/mattdesl) [Material Design Fonts](http://mattdesl.svbtle.com/material-design-on-the-gpu) i [jak to jest opisane w rozdziale 7 iPhone 3D Programming, O'Reilly](http://chimera.labs.oreilly.com/books/1234000001814/ch07.html#ch07_id36000921). -Take a look at the following code. +Przyjrzyj się następującemu kodowi. + +
-We start by moving the coordinate system to the center and shrinking it in half in order to remap the position values between -1 and 1. Also on *line 24* we are visualizing the distance field values using a [`fract()`](../glossary/?search=fract) function making it easy to see the pattern they create. The distance field pattern repeats over and over like rings in a Zen garden. +Zaczynamy od przeniesienia układu współrzędnych na środek i skurczenia go o połowę, mapując wartości pozycji pomiędzy -1 a 1. W *linijce 24* wizualizujemy wartości pola odległości za pomocą funkcji [`fract()`](../glossary/?search=fract) ułatwiając dostrzeżenie tworzonego przez nie wzoru. Wzór pola odległości powtarza się jak pierścienie w ogrodzie Zen. + +Przyjrzyjmy się wzorowi pola odległości w *linijce 19*. Obliczamy tam odległość do współrzędnej `(.3,.3)` lub `vec3(.3)` we wszystkich czterech kwadrantach (właśnie po to jest tam [`abs()`](../glossary/?search=abs)). + + -If you uncomment *line 20*, you will note that we are combining the distances to these four points using the [`min()`](../glossary/?search=min) to zero. The result produces an interesting new pattern. +Jeśli odkomentujesz *linijkę 20*, zauważysz, że łączymy odległości do tych czterech punktów za pomocą [`min()`](../glossary/?search=min) do zera. W rezultacie otrzymujemy nowy interesujący wzór. + +Spróbuj teraz odkomentować *linijkę 21*; robimy to samo, ale używamy funkcji [`max()`](../glossary/?search=max). Rezultatem jest prostokąt z zaokrąglonymi rogami. Zauważ, jak pierścienie pola odległości stają się gładsze, im bardziej oddalają się od środka. + +Dokończ odkomentowywanie *linijek 27 do 29* jedna po drugiej, aby zrozumieć różne zastosowania wzorca pola odległości. + + -### Polar shapes +### Krzywe biegunowe ![Robert Mangold - Untitled (2008)](mangold.jpg) -In the chapter about color we map the cartesian coordinates to polar coordinates by calculating the *radius* and *angles* of each pixel with the following formula: +W rozdziale o kolorze mapujemy współrzędne kartezjańskie na współrzędne biegunowe, obliczając *promień* i *kąt* każdego piksela za pomocą następującego wzoru: + + ```glsl vec2 pos = vec2(0.5)-st; float r = length(pos)*2.0; float a = atan(pos.y,pos.x); ``` +Część tego wzoru wykorzystaliśmy na początku rozdziału do narysowania okręgu. Odległość do środka obliczyliśmy za pomocą [`length()`](../glossary/?search=length). Teraz, gdy wiemy już o polach odległości, możemy poznać inny sposób rysowania kształtów za pomocą współrzędnych biegunowych. + +Technika ta jest nieco restrykcyjna, ale bardzo prosta. Polega ona na zmianie promienia okręgu w zależności od kąta, aby uzyskać różne kształty. Jak dokonuje się ta zmiana? Z użyciem funkcji kształtujących! -We use part of this formula at the beginning of the chapter to draw a circle. We calculated the distance to the center using [`length()`](../glossary/?search=length). Now that we know about distance fields we can learn another way of drawing shapes using polar coordinates. +Poniżej znajdziesz dwa interaktywne przykłady, w których te same funkcje występują we współrzędnych kartezjańskich i w biegunowych (pomiędzy *linijkami 21 i 25*). Odkomentuj te funkcje jedna za drugą, zwracając uwagę na zależności między jednym układem współrzędnych a drugim. + +
-Try to: +Spróbuj: + + -* Animate these shapes. +* Zanimować te kształty +* Połącz różne funkcje kształtujące by *zrobić dziury* w kształtach, aby powstały kwiaty, płatki śniegu i zębatki. +* Użyj funkcji `plot()` z rodziału *Funkcje kształtujące* i narysuj sam kontur (bez wypełnienia) + + ### Combining powers -Now that we've learned how to modulate the radius of a circle according to the angle using the [`atan()`](../glossary/?search=atan) to draw different shapes, we can learn how use `atan()` with distance fields and apply all the tricks and effects possible with distance fields. +### Łączenie + +Teraz gdy wiemy, jak zmieniać promień koła w zależności od kąta z użyciem [`atan()`](../glossary/?search=atan), możemy spróbować połączyć `atan()` z polami odległości. -The trick will use the number of edges of a polygon to construct the distance field using polar coordinates. Check out [the following code](http://thndl.com/square-shaped-shaders.html) from [Andrew Baldwin](https://twitter.com/baldand). + + +Trik polega na wykorzystanie liczby krawędzi wielokąta, by skonstruować pole odległości z użyciem współrzędnych polarnych. Sprawdź [następujący kod](http://thndl.com/square-shaped-shaders.html) od [Andrew Baldwin](https://twitter.com/baldand). + +
-* Using this example, make a function that inputs the position and number of corners of a desired shape and returns a distance field value. +* Korzystając z tego przykładu, stwórz funkcję, która przyjmuje położenie i liczbę kątów pożądanego wielokąta, a zwraca wartość pola odległości. + + + +* Połącz pola odległości ze sobą z użyciem [`min()`](../glossary/?search=min) i [`max()`](../glossary/?search=max). + + + +* Zreplikuj dowolne logo z użyciem pól odległości + + + +Gratulacje! Udało ci się przebrnąć przez trudny materiał! Odpocznij i pozwól - choć rysowanie prostych kształtów jest proste w Processing, to tutaj już nie. W świecie shaderów rysowanie kształtów jest zawiłe; przestawienie się na ten nowy sposób programowania może być męczące. -* Mix distance fields together using [`min()`](../glossary/?search=min) and [`max()`](../glossary/?search=max). + -* Choose a geometric logo to replicate using distance fields. +Na dole strony znajdziesz link do [PixelSpirit Deck](https://patriciogonzalezvivo.github.io/PixelSpiritDeck/). Jest to talia kart, która pomoże ci nauczyć się nowych funkcji SDF (ang. "Signed distance field" - pole odległości z uwzględnieniem wartości ujemnych), które wykorzystasz w swoich pracach i shaderach. Poziom trudności jest progresywny, więc praca nad jedną kartą dziennie zapewni ci wyzwania na kolejne miesiące. -Congratulations! You have made it through the rough part! Take a break and let these concepts settle - drawing simple shapes in Processing is easy but not here. In shader-land drawing shapes is twisted, and it can be exhausting to adapt to this new paradigm of coding. + -Down at the end of this chapter you will find a link to [PixelSpirit Deck](https://patriciogonzalezvivo.github.io/PixelSpiritDeck/) this deck of cards will help you learn new SDF functions, compose them into your designs and use on your shaders. The deck has a progressive learning curve, so taking one card a day and working on it will push and challenge your skills for months. +Wiedząc jak rysować kształty, z pewnością przyjdą ci do głowy nowe pomysły. W następnym rozdziale nauczysz się przesuwać, obracać i skalować kształty. Pozwoli ci to tworzyć kompozycje! -Now that you know how to draw shapes I'm sure new ideas will pop into your mind. In the following chapter you will learn how to move, rotate and scale shapes. This will allow you to make compositions! + diff --git a/Questions_to_author.txt b/Questions_to_author.txt index ba283c8..92b47bd 100644 --- a/Questions_to_author.txt +++ b/Questions_to_author.txt @@ -5,4 +5,5 @@ Podać polskie tłumaczenie słowa pipeline Podać angielskie tłumaczenie wejście i wyjście -Wytłumaczyć "hot reloading" (04) \ No newline at end of file +Wytłumaczyć "hot reloading" (04) +Distance field - pole odległości \ No newline at end of file From a4c6fbb0a06f8ff10cb4f9808cbf76a5e11f89c9 Mon Sep 17 00:00:00 2001 From: Wojtek Date: Wed, 25 Jan 2023 11:10:18 +0100 Subject: [PATCH 10/23] 08 --- 08/README-pl.md | 165 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 165 insertions(+) create mode 100644 08/README-pl.md diff --git a/08/README-pl.md b/08/README-pl.md new file mode 100644 index 0000000..7e62cce --- /dev/null +++ b/08/README-pl.md @@ -0,0 +1,165 @@ +## Macierze 2D + + + +### Translacja + +W poprzednim rozdziale dowiedzieliśmy się, jak tworzyć różne kształty - sztuczka z przesuwaniem tych kształtów polega na przesuwaniu samego układu współrzędnych. Możemy to osiągnąć poprzez proste dodanie wektora do zmiennej ``st``, zawierającej położenie każdego fragmentu. Powoduje to przesunięcie całego układu współrzędnych. + + + +![](translate.jpg) + +Łatwiej jest to zobaczyć niż wytłumaczyć, zatem: + +*Odkomentuj linijkę 35 poniższego kodu, by zobaczyć jak przestrzeń się przesuwa. + + + +
+ +Spróbuj teraz wykonać następujące ćwiczenie: + +* Używając ``u_time`` wraz z funkcjami kształtującymi poruszaj małym krzyżem w ciekawy sposób. Poszukaj interesującego cię ruchu i spróbuj sprawić, by krzyż poruszał się w ten sam sposób. Przydatne może być nagranie najpierw czegoś z "prawdziwego świata" - może to być przypływ i odpływ fal, ruch wahadła, odbijająca się piłka, przyspieszający samochód, zatrzymujący się rower. + +### Rotacja + +Aby obracać obiekty musimy również poruszać całym układem przestrzennym. Do tego celu będziemy używać [macierzy](http://en.wikipedia.org/wiki/Matrix_%28mathematics%29). Macierz to uporządkowany zbiór liczb w kolumnach i wierszach. Wektory są mnożone przez macierze według ściśle określonych reguł w celu zmodyfikowania wartości wektora w określony sposób. + +[![wpis Wikipedii dotyczący macierzy](matrixes.png)](https://en.wikipedia.org/wiki/Matrix) + +GLSL posiada natywne wsparcie dla dwu, trzy i czterowymiarowych macierzy: [``mat2``](../glossary/?search=mat2) (2x2), [``mat3``](../glossary/?search=mat3) (3x3) i [``mat4``](../glossary/?search=mat4) (4x4). GLSL obsługuje również mnożenie macierzy (``*``) oraz funkcję specyficzną dla macierzy ([``matrixCompMult()``](../glossary/?search=matrixCompMult)). + +Na podstawie tego, jak zachowują się macierze, możliwe jest skonstruowanie macierzy w celu wytworzenia określonych zachowań. Na przykład możemy użyć macierzy do translacji wektora: + + + +![](3dtransmat.png) + +Co ciekawsze, możemy użyć macierzy do obrócenia całego układu współrzędnych + + + +![](rotmat.png) + +Spójrz na poniższy kod funkcji, która konstruuje dwuwymiarową macierz rotacji. Funkcja ta oparta jest na [wzorze](http://en.wikipedia.org/wiki/Rotation_matrix) dla dwuwymiarowych wektorów, aby obrócić współrzędne wokół punktu ``vec2(0,0)``. + + + +```glsl +mat2 rotate2d(float _angle){ + return mat2(cos(_angle),-sin(_angle), + sin(_angle),cos(_angle)); +} +``` + +Zgodnie ze sposobem, w jaki rysowaliśmy kształty, nie jest to dokładnie to, czego chcemy. Nasz krzyż jest rysowany w centrum płótna, co odpowiada pozycji ``vec2(0.5)``. Tak więc, zanim obrócimy przestrzeń musimy przenieść ten krzyż z `centrum` na współrzędną ``vec2(0.0)``, obrócić przestrzeń, a następnie ostatecznie przenieść go z powrotem na pierwotne miejsce. + + + +![](rotate.jpg) + +Co odpowiada ponizszemu kodowi: + + + +
+ +Spróbuj wykonać następujące ćwiczenia: + +* Odkomentuj linię 45 powyższego kodu i zwróć uwagę na to, co się stanie. + +* Zakomentuj translacje przed i po rotacji, w liniach 37 i 39, i zaobserwuj konsekwencje. + +* Użyj rotacji, aby poprawić ruch, który zasymulowałeś w ćwiczeniu z podrozdziału "Translcją". + +### Skalowanie + +Widzieliśmy już, jak macierze służą do translacji i rotacji obiektów w przestrzeni. (A dokładniej do przekształcania układu współrzędnych w celu obracania i przesuwania obiektów). Jeśli używałeś programów do modelowania 3D albo funkcji macierzowych push i pop w Processing, to pewnie wiesz, że macierze mogą być również używane do skalowania rozmiaru obiektu. + + + +![](scale.png) + +Na podstawie powyższego wzoru, możemy stworzyć 2D macierz skalowania w GLSL: + + + +```glsl +mat2 scale(vec2 _scale){ + return mat2(_scale.x,0.0, + 0.0,_scale.y); +} +``` + +
+ +Spróbuj następujących ćwiczeń, aby głębiej zrozumieć, jak to działa. + +* Odkomentuj linię 42 powyższego kodu, aby zobaczyć skalowaną współrzędną przestrzeni. + +* Zobacz, co się stanie, gdy zakomentujesz translacje przed i po skalowaniu w liniach 37 i 39. + +* Spróbuj połączyć macierz rotacji wraz z macierzą skalowania. Bądź świadomy, że kolejność ma znaczenie. Najpierw pomnóż przez macierz, a potem pomnóż wektory. + +* Teraz, gdy wiesz już, jak rysować różne kształty oraz przesuwać, obracać i skalować je, czas na stworzenie ładnej kompozycji. Zaprojektuj i skonstruuj [UI lub HUD](https://www.pinterest.com/patriciogonzv/huds/) (ang. "heads up display"). Użyj następującego przykładu ShaderToy autorstwa [Ndel](https://www.shadertoy.com/user/ndel) jako inspiracji. + + + + + +### Inne zastosowania macierzy: Kolor YUV + +[YUV](http://en.wikipedia.org/wiki/YUV) to przestrzeń barw stosowana do analogowego kodowania zdjęć i filmów, która uwzględnia ludzką percepcję w celu zmniejszenia redundantnych informacji zawartych w reprezentacji RGB. + +Poniższy kod jest ciekawą okazją do wykorzystania operacji macierzowych w GLSL do transformacji kolorów z jednej przestrzeni do drugiej. + +
+ +Jak widać traktujemy kolory jak wektory, które można mnożyć przez macierze. W ten sposób mapujemy wartości. + +W tym rozdziale dowiedzieliśmy się, jak używać przekształceń macierzowych do przesuwania, obracania i skalowania wektorów. Przekształcenia te będą niezbędne do tworzenia kompozycji z kształtów, które poznaliśmy w poprzednim rozdziale. W następnym rozdziale zastosujemy wszystko, czego dotychczas się nauczyliśmy, do tworzenia pięknych proceduralnych wzorów. Zobaczysz, że programowanie powtórzeń i wariacji może być bardzo ekscytujące. + + From d9c55a1bdae7d7f6bf6486fafe0bd7cfe3ebc4a7 Mon Sep 17 00:00:00 2001 From: Wojtek Date: Tue, 31 Jan 2023 14:29:39 +0100 Subject: [PATCH 11/23] 09 10 --- 09/README-pl.md | 200 ++++++++++++++++++++++++++++++++++++++++++++++++ 10/README-pl.md | 152 ++++++++++++++++++++++++++++++++++++ 2 files changed, 352 insertions(+) create mode 100644 09/README-pl.md create mode 100644 10/README-pl.md diff --git a/09/README-pl.md b/09/README-pl.md new file mode 100644 index 0000000..62a08e2 --- /dev/null +++ b/09/README-pl.md @@ -0,0 +1,200 @@ +## Wzory kafelkowe + +Ponieważ shadery wykonywane są piksel po pikselu, więc niezależnie od tego, jak często powtarzasz (duplikujesz) dany kształt, liczba obliczeń pozostaje stała. Oznacza to, że fragment shadery nadają się szczególnie do wzorów kafelkowych. + +[ ![Nina Warmerdam - The IMPRINT Project (2013)](warmerdam.jpg) ](../edit.php#09/dots5.frag) + +W tym rozdziale zamierzamy zastosować to, czego nauczyliśmy się do tej pory, ale powtarzając to wzdłuż kanwy. Podobnie jak w poprzednich rozdziałach, nasza strategia będzie opierała się na mnożeniu współrzędnych przestrzeni (z przedziału 0.0 a 1.0), dzięki czemu kształty, które narysujemy pomiędzy wartościami 0.0 a 1.0, będą się powtarzać, tworząc siatkę. + +*Siatka zapewnia ramy, w których może działać ludzka intuicja i inwencja, i które może obalić. W chaosie natury wzory zapewniają kontrast i obietnicę porządku. Od wczesnych wzorów na ceramice do geometrycznych mozaik w rzymskich łaźniach, ludzie od dawna używali siatek, by wzbogacić swoje życie o dekoracje. "* [*10 PRINT*, Mit Press, (2013)](http://10print.org/) + +Najpierw przypomnijmy sobie funkcję [``fract()``](../glossary/?search=fract). Zwraca ona część ułamkową liczby, dzięki czemu ``fract()`` to w istocie funkcja modulo jeden ([``mod(x,1.0)``](../glossary/?search=mod)). Innymi słowy, [``fract()``](../glossary/?search=fract) zwraca liczbę po przecinku. Nasza zmienna znormalizowanego układu współrzędnych (``st``) już znajduje sie w zakresie od 0.0 do 1.0, więc nie ma sensu robić czegoś takiego jak: + + + +```glsl +void main(){ + vec2 st = gl_FragCoord.xy/u_resolution; + vec3 color = vec3(0.0); + st = fract(st); + color = vec3(st,0.0); + gl_FragColor = vec4(color,1.0); +} +``` + +Ale jeśli przeskalujemy znormalizowany układ współrzędnych w górę - powiedzmy o trzy - otrzymamy trzy sekwencje interpolacji liniowych między 0-1: pierwszą między 0-1, drugą dla punktów między 1-2 i trzecią dla punktów między 2-3. + + + +
+ +Teraz nadszedł czas, aby narysować coś w każdej podprzestrzeni, odkomentowując linię 27. (Ponieważ mnożymy x i y po równo, współczynnik proporcji przestrzeni nie zmienia się i kształty będą zgodne z oczekiwaniami). + +Spróbuj wykonać niektóre z poniższych ćwiczeń, aby uzyskać głębsze zrozumienie: + + + +* Pomnóż przestrzeń przez różne liczby. Spróbuj z wartościami zmiennoprzecinkowymi, a także z różnymi wartościami dla x i y. + +* Zrób funkcję z tej kafelkowej sztuczki, abyś mógł ją ponownie wykorzystać. + +* Podziel przestrzeń na 3 wiersze i 3 kolumny. Znajdź sposób identyfikowania, w której kolumnie i rzędzie znajduje się wątek (piksel). Użyj tego, aby zmienić kształt, który jest wyświetlany. Spróbuj stworzyć mecz Kółko i krzyżyk + + + +### Macierze wewnątrz kafelków + +Ponieważ każdy kafelek jest pomniejszą wersją znormalizowanego układu współrzędnych, którego już używaliśmy, więc możemy zastosować do niego przekształcenie macierzowe w celu translacji, obrotu lub skalowania przestrzeni wewnątrz. + + + +
+ +* Pomyśl o ciekawych sposobach animacji tego wzoru. Rozważ animowanie koloru, kształtu i ruchu. Wykonaj trzy różne animacje. + +* Odtwórz bardziej skomplikowane wzory poprzez skomponowanie różnych kształtów. + + + + +[![](diamondtiles-long.png)](../edit.php#09/diamondtiles.frag) + +* Połącz różne warstwy wzorów, aby skomponować własny [szkocki tartan](https://www.google.com/search?q=scottish+patterns+fabric&tbm=isch&tbo=u&source=univ&sa=X&ei=Y1aFVfmfD9P-yQTLuYCIDA&ved=0CB4QsAQ&biw=1399&bih=799#tbm=isch&q=Scottish+Tartans+Patterns). + + + +[ ![Vector Pattern Scottish Tartan By Kavalenkava](tartan.jpg) ](http://graphicriver.net/item/vector-pattern-scottish-tartan/6590076) + +### Przesunięcia kafelków + +Powiedzmy, że chcemy odtworzyć mur z cegły. Patrząc na ścianę, można zauważyć przesunięcie pół cegły na osi x w co drugim rzędzie. Jak możemy to zrobić? + +![](brick.jpg) + +Jako pierwszy krok musimy wiedzieć, czy rząd naszego wątku (piksela) jest liczbą parzystą czy nieparzystą, co pomoże określić, czy musimy przesunąć x w tym rzędzie. W tym celu użyjemy [``mod()``](../glossary/?search=mod) z ``2.0``, a następnie zobaczymy, czy wynik jest mniejszy niż ``1.0`` czy nie. Spójrz na poniższy kod i odkomentuj dwie ostatnie linie. + + + +
+ +Jak widać możemy użyć [operatora warunkowego](https://en.wikipedia.org/wiki/%3F:) do sprawdzenia czy [``mod()``](../glossary/?search=mod) z ``2.0`` jest mniejszy od ``1.0`` (druga linia) lub podobnie możemy użyć funkcji [``step()``](../glossary/?search=step), która wykonuje tę samą operację, ale szybciej. Dlaczego? Chociaż trudno jest wiedzieć jak każda karta graficzna optymalizuje i kompiluje kod, to można bezpiecznie założyć, że funkcje wbudowane są szybsze od tych niewbudowanych. Zawsze, gdy możesz użyć wbudowanej funkcji, użyj jej! + +Korzystając z powyższej metody wykrywania liczb nieparzystych, możemy przesunąć nieparzyste rzędy, aby upodobnić naszą kawnę do ceglanej ściany. W linii 14 poniższego kodu identyfikujemy parzystość rzędów i nadajemy im przesunięcie na ``x``. Zauważ, że dla parzystych rzędów, wynikiem obliczeń w `step()` jest ``0.0``, co, mnożąc przez ``0.5``, daje przesunięcie ``0.0``. Natomiast w nieparzystych rzędach mnożymy ``1.0`` przez ``0.5``, co powoduje przesunięcie osi ``x`` układu współrzędnych o ``0.5``. + + + +Teraz spróbuj odkomentować linię 32 - rozciąga ona proporcje układu współrzędnych, aby odtworzyć wymiary "nowoczesnej cegły". Odkomentowując linię 40 możesz zobaczyć jak wygląda układ współrzędnych zmapowany na kolor czerwony i zielony. + + + +
+ +* Zanimuj ten przykład, zwiększając przesunięcie w zależności od czasu. + +* Zrób kolejną animację, w której parzyste wiersze przesuwają się w lewo, a nieparzyste w prawo. + +* Czy możesz powtórzyć ten efekt, ale z kolumnami? + +* Spróbuj połączyć przesunięcie na osi ``x`` i ``y``, aby uzyskać coś takiego: + + + + + +## Kafelki Truchet'a + +Teraz, gdy dowiedzieliśmy się, jak określić, czy nasza komórka znajduje się w parzystym czy nieparzystym wierszu lub kolumnie, możliwe jest ponowne wykorzystanie pojedynczego elementu projektu w zależności od jego pozycji. Rozważmy przypadek [kafelków Truchet'a](http://en.wikipedia.org/wiki/Truchet_tiles), gdzie pojedynczy kafelek może być przedstawiony na cztery różne sposoby: + + + +![](truchet-00.png) + +Zmieniając wzór na kafelkach, można zbudować nieskończony zestaw skomplikowanych wzorów. + + + +![](truchet-01.png) + +Zwróć uwagę na funkcję ``rotateTilePattern()``, która dzieli przestrzeń na cztery komórki i każdej z nich przypisuje kąt obrotu. + + + +
+ +* Zakomentowywuj, odkomentowywuj i powielaj linie od 69 do 72, aby komponować nowe wzory. + +* Zmień czarno-biały trójkąt na inny element, taki jak: półkola, obrócone kwadraty lub linie. + +* Zakoduj inne wzory, w których elementy są obracane w zależności od ich położenia. + +* Zrób wzór, który zmienia inne właściwości w zależności od położenia elementów. + +* Pomyśl o czymś innym, co niekoniecznie jest wzorem, gdzie możesz zastosować zasady z tego działu. (Na przykład: heksagramy I Ching) + + + + + +## Tworzenie własnych reguł + +Tworzenie wzorców proceduralnych to ćwiczenie umysłowe polegające na znajdowaniu minimalnych elementów wielokrotnego użytku. Praktyka ta jest stara; my jako gatunek od dawna używamy siatek i wzorów do dekorowania tkanin, podłóg i obramowań obiektów: od meandrowych wzorów w starożytnej Grecji, po chińskie wzory kratowe, przyjemność z powtórzeń i wariacji przykuwa naszą uwagę i pobudza wyobraźnię. Poświęć trochę czasu, aby spojrzeć na [dekoracyjne](https://archive.org/stream/traditionalmetho00chririch#page/130/mode/2up) [wzory](https://www.pinterest.com/patriciogonzv/paterns/) i zobacz długą historię tego, jak artyści i projektanci poruszają się po cienkiej krawędzi między przewidywalnością porządku a niespodzianką zmienności i chaosu. Od arabskich wzorów geometrycznych do wspaniałych afrykańskich wzorów tkanin, istnieje cały wszechświat wzorów, z których można się uczyć. + + + +![Franz Sales Meyer - A handbook of ornament (1920)](geometricpatters.png) + +Tym rozdziałem kończymy część poświęconą Rysowaniu Algorytmicznemu. W kolejnych rozdziałach dowiemy się, jak wprowadzić trochę entropii do naszych shaderów, tworząc generatywny design. + + diff --git a/10/README-pl.md b/10/README-pl.md new file mode 100644 index 0000000..f6d98a1 --- /dev/null +++ b/10/README-pl.md @@ -0,0 +1,152 @@ +# Design generatywny + +Nie jest zaskoczeniem, że po tylu zagadnieniach ładu i porządku autor zmuszony jest wprowadzić trochę chaosu. + +## Losowość + +[![Ryoji Ikeda - test pattern (2008) ](ryoji-ikeda.jpg) ](http://www.ryojiikeda.com/project/testpattern/#testpattern_live_set) + +Losowość jest maksymalnym wyrazem entropii. Jak możemy wygenerować losowość wewnątrz pozornie przewidywalnego i sztywnego środowiska kodu? + +Zacznijmy od analizy następującej funkcji: + + + +
+ +Powyżej wyodrębniamy zawartość ułamkową sinusoidy. Wartości [``sin()``](../glossary/?search=sin), które oscylują pomiędzy ``-1.0`` a ``1.0`` zostały posiekane, zwracając wszystkie dodatnie wartości pomiędzy ``0.0`` a ``1.0``. Możemy wykorzystać ten efekt do uzyskania pseudolosowych wartości. W jaki sposób? Mnożąc wypadkową [``sin(x)``](../glossary/?search=sin) przez większe liczby. Śmiało, zmodyfikuj powyższą funkcję, dodając zera do `1.0`. + +Do czasu, gdy dojdziesz do ``100000.0`` (i równanie będzie wyglądało tak: ``y = fract(sin(x)*100000.0)`` ) nie jesteś już w stanie odróżnić sinusoidy. Ziarnistość części ułamkowej zepsuła falę sinusoidy w pseudolosowy chaos. + + + +## Kontrolowanie chaosu + +Używanie losowości może być trudne - czasami jest ona zbyt chaotyczna, a czasami niewystarczająco losowa. Przyjrzyj się poniższemu wykresowi. Aby go stworzyć, używamy funkcji ``rand()``, która jest zaimplementowana dokładnie tak, jak opisaliśmy powyżej. + +Przyglądając się bliżej, możesz zobaczyć [```sin()``](../glossary/?search=sin) grzebień fali przy ``-1,5707`` i ``1,5707``. Założę się, że teraz rozumiesz dlaczego - to właśnie tam występuje maksimum i minimum fali sinusoidalnej. + +Jeśli przyjrzysz się bliżej rozkładowi losowemu, zauważysz, że istnieje pewne skupienie wokół środka w porównaniu do krawędzi. + + + +
+ +Jakiś czas temu [Pixelero](https://pixelero.wordpress.com) opublikował [ciekawy artykuł o rozkładzie losowym](https://pixelero.wordpress.com/2008/04/24/various-functions-and-various-distributions-with-mathrandom/). Dodałem kilka funkcji, których używa, na poprzednim wykresie, abyś mógł zobaczyć, jak można ten rozkład zmienić. Odkomentuj te funkcje i zobacz, co się stanie. + +Czytając [artykuł Pixelero](https://pixelero.wordpress.com/2008/04/24/various-functions-and-various-distributions-with-mathrandom/), ważne jest, aby pamiętać, że nasza funkcja ``rand()`` jest deterministyczna, pseudolosowa. Co oznacza, że na przykład ``rand(1.)`` zawsze zwróci tę samą wartość. [Pixelero](https://pixelero.wordpress.com/2008/04/24/various-functions-and-various-distributions-with-mathrandom/) odwołuje się do funkcji ActionScript ``Math.random()``, która jest niedeterministyczna - każde jej wywołanie zwróci inną wartość. + + + +## Losowość 2D + +Teraz, gdy mamy już lepsze zrozumienie losowości, czas zastosować ją w dwóch wymiarach, zarówno na osi ``x`` jak i ``y``. W tym celu potrzebujemy sposobu na przekształcenie dwuwymiarowego wektora w jednowymiarową wartość zmiennoprzecinkową. Można to zrobić na różne sposoby, ale szczególnie pomocna w tym przypadku jest funkcja [``dot()``](../glossary/?search=dot). Zwraca ona pojedynczą wartość zmiennoprzecinkową pomiędzy ``0.0`` a ``1.0`` w zależności od wzajemnej orientacji dwóch wektorów. + + + +
+ +Przyjrzyj się liniom od 13 do 15 i zauważ, jak porównujemy ``vec2 st`` z innym dwuwymiarowym wektorem ( ``vec2(12,9898,78,233)``). + +* Spróbuj zmienić wartości w liniach 14 i 15. Zobacz, jak zmienia się wyświetlany losowy wzór i zastanów się, czego możemy się z tego nauczyć. + +* Uzależnij tę funkcję losową od myszy (``u_mouse``) i czasu (``u_time``), aby lepiej zrozumieć, jak działa. + + + +## Wykorzystanie chaosu + +Losowość w dwóch wymiarach wygląda bardzo podobnie do szumu telewizyjnego, prawda? To trudne do wykorzystania narzędzie do komponowania obrazów. Nauczmy się, jak zrobić z niego użytek. + +Naszym pierwszym krokiem jest stworzenie tablicy kafelków; używając funkcji [``floor()``](../glossary/?search=floor) wygenerujemy tablicę, w której każdemu kafelkowi przyporządkowany jest unikalny wektor liczb całkowitych. Przyjrzyj się poniższemu kodowi, szczególnie liniom 22 i 23. + + + +
+ +Po przeskalowaniu przestrzeni przez 10 (w linii 21) oddzielamy część całkowitą współrzędnych od części ułamkowej. Operacja uzyskiwania części ułamkowej jest nam dobrze znana, ponieważ używaliśmy jej do dzielenia przestrzeni na mniejsze kafelki o wartościach od ``0.0`` do ``1.0``. Uzyskując część całkowitą współrzędnej wyodrębniamy wspólną wartość dla całego kafelka. Następnie możemy użyć tej wspólnej liczby całkowitej, aby uzyskać losową wartość dla tego kafelka. Ponieważ nasza funkcja losowa jest deterministyczna, zwrócona wartość losowa będzie stała dla wszystkich pikseli w tym kafelku. + +Odkomentuj linię 29, aby zobaczyć, że zachowujemy część ułamkową współrzędnej, więc możemy nadal używać jej jako układu współrzędnych do rysowania rzeczy wewnątrz każdego kafelka. + + + +Połączenie tych dwóch wartości - części całkowitej i części ułamkowej współrzędnej - pozwoli ci wymieszać zmienność i porządek. + +Spójrz na poniższy GLSL'owy port słynnego generatora labiryntów ``10 PRINT CHR$(205,5+RND(1)); : GOTO 10``. + + + +
+ +Tutaj wykorzystuję losowe wartości kafelków do rysowania linii w jednym lub drugim kierunku, używając funkcji ``truchetPattern()`` z poprzedniego rozdziału (linie 41 do 47). + +Możesz uzyskać inny ciekawy wzór, odkomentowując blok linii między 50 a 53, natomiast odkomentowując linie 35 i 36 dodasz animację. + + + +## Ujarzmij losowość + +[Ryoji Ikeda](http://www.ryojiikeda.com/), japoński kompozytor elektroniczny i artysta wizualny, ujarzmił losowość - trudno nie być poruszonym i zahipnotyzowanym przez jego prace. Jego użycie losowości w mediach audio-wizualnych to nie irytujący chaos, ale lustro złożoności naszej technologicznej kultury. + + + + + +Zapoznaj się z pracami [Ikedy](http://www.ryojiikeda.com/) i spróbuj wykonać następujące ćwiczenia: + +* Utwórz rzędy ruchomych komórek (w przeciwnych kierunkach) o losowych wartościach. Wyświetlaj tylko komórki z jaśniejszymi wartościami. Spraw, aby prędkość rzędów zmieniała się w czasie. + + + + + +* Podobnie jak poprzednio, stwórz kilka rzędów kafelków, ale każdy z nich z inną prędkością i kierunkiem. Uzależnij próg wyświetlania kafelków od położenia myszy. + + + + + +* Stwórz inne ciekawe efekty. + + + + + +Używanie losowości pod względem estetycznym może być problematyczne, zwłaszcza jeśli chcesz zrobić naturalnie wyglądające symulacje. Losowość jest po prostu zbyt chaotyczna i bardzo niewiele rzeczy wygląda ``random()`` w prawdziwym życiu. Jeśli spojrzysz na wzór deszczu lub wykres giełdowy, które są dość losowe, nie przypominają one w niczym losowego wzoru, który stworzyliśmy na początku tego rozdziału. Powód? Cóż, wartości losowe nie mają żadnej korelacji między sobą, podczas gdy większość naturalnych wzorów ma jakąś pamięć o poprzednim stanie. + +W następnym rozdziale poznamy szum (ang. "noise"), płynny i *naturalnie wyglądający* sposób tworzenia chaosu obliczeniowego. + + From c4ae411017d6e26d15646a01672530ff65100420 Mon Sep 17 00:00:00 2001 From: Wojtek Pachowiak Date: Mon, 6 Feb 2023 17:48:13 +0100 Subject: [PATCH 12/23] 05 --- 05/README-pl.md | 216 ++++++++++++++++++++++++++++++++++++++++ Questions_to_author.txt | 8 +- 2 files changed, 223 insertions(+), 1 deletion(-) create mode 100644 05/README-pl.md diff --git a/05/README-pl.md b/05/README-pl.md new file mode 100644 index 0000000..394fa66 --- /dev/null +++ b/05/README-pl.md @@ -0,0 +1,216 @@ +# Rysowanie algorytmiczne +## Funkcje kształtujące (ang. "shaping functions") + +Rozdział ten mógłby się nazywać "lekcja płota Pana Miyagiego". Poprzednio, mapowaliśmy znormalizowane pozycje *x* i *y* do *czerwonego* i *zielonego* kanału. W skróćie, stworzyliśmy fumkcję, która przyjmuje dwuwymiarowy wektor (x i y) i zwraca czterowymiarowy wektor (r, g, b i a). Jednak zanim zagłębimy się w takie transformacje między wymiarami, wypada najpierw opanować tworzenie jednowymiarowych funkcji w pełni. Im więcej czasu spędzisz na szlifowaniu tej umiejętności, tym lepsze będzie twoje "shader karate". + + + +![The Karate Kid (1984)](mr_miyagi.jpg) + +Poniższy kod będzie naszym płotem. Wizualizujemy w nim znormalizowaną wartość współrzędnej *x* (`st.x`) w dwojaki sposób: poprzez jasność (zauważ płynny gradient od czerni do bieli) oraz przez rysowanie zielonego wykresu funkcji (w poniższym przykładzie funkcji *x* = *y*). Nie przejmuj się za bardzo funkcją `plot` - wrócimy do niej później. + + + +
+ +**Krótka uwaga**: Konstruktor typu `vec3` "rozumie", że chcesz przypisać tę samą wartość do każdego z trzech kanałów koloru, natomaist typu `vec4` rozumie, że chcesz stworzyć czterowymiarowy wektor z wektora trójwymiarowego i czwartej wartości (w tym wypadku wartość ta controluje alphę, czyli przezroczystość). Spójrz na linjki 19 i 25 powyżej. + + + +Kod jest twoim płotem - ważne, żebyś umiał na niego spojrzeć i go zrozumieć. Będziesz zakres od *0.0* do *1.0* będzie ci stale towarzyszył. Opanujesz sztukę blendowania (pol. "mieszania", "łączenia") i kształtowaniatej linii + +This code is your fence; it's important to observe and understand it. You will come back over and over to this space between *0.0* and *1.0*. You will master the art of blending and shaping this line. += + +Tę wzajmnie jednoznaczną (ang. "one-to-one") funkcję między *x* i *y* (lub jasnością) nazywamy *interpolacją liniową*. Możemy użyć funkcji matematycznych by *uformować* tę linię. Przykładowo, możemy podnieść *x* do potęgi 5, aby utworzyć *krzywą* linię. + + + +
+ +Ciekawe, prawda? W linijce 22 spróbuj użyć następujących wykładników: 20.0, 2.0, 1.0, 0.0, 0.2 czy 0.02. Zrozumienie związków między końcową wartością a wykładnikiem będzie bardzo porzydatne. Używanie tego typu funkcji matematycznych tu i tam da ci pełnię kontroli nad twoim kodem. + + + +[`pow()`](../glossary/?search=pow) są natywnymi funkcjami w GLSL. Większość z nich zaimplementowana jest na poziomie hardware'u, co oznacza, że odpowiednie ich użycie przypiszy twój kod. + + + +Zastąp funkcję potęgową w linijce 22 inną funkcją. Spróbuj [`exp()`](../glossary/?search=exp), [`log()`](../glossary/?search=log) i [`sqrt()`](../glossary/?search=sqrt). W wypadku funkcji trygonometrycznych warto użyć liczby PI. Jest ona zdefiniowana w 8 linijce za pomocą makra, który zastąpi każde użycie `PI` wartością `3.14159265359`. + + + +### Step i Smoothstep + +GLSL posiada też unikalne natywne funckje interpolacyjne wykorzystujące akcelerację sprzętową. + + +Funkcja [`step()`](../glossary/?search=step) otrzymuje dwa argumenty. Pierwszy z nich to limit lub próg, natomiast drugi to wartość, którą chcemy sprawdzić lub przekazać. Każda wartość poniżej limitu zwróci `0.0`, natomiast wszystko powyżej limitu zwróci `1.0`. + + + + +Spróbuj zmienić tę wartość progową w linijce 20 poniższego kodu. + +
+ +Druga unikalna funkcja znana jest jako [`smoothstep()`](../glossary/?search=smoothstep) i otrzymuje trzy argumenty Dwa pierwsze argumenty służą do określenia początku i końca przejścia (interpolacji), natomiast trzeci jest wartością interpolowaną. + + + +
+ +W poprzednim przykładzie, w linii 12, zauważ, że użyliśmy smoothstep wewnątrz funkcji `plot()` do narysowania zielonej linii. Dla każdej pozycji wzdłuż osi x funkcja ta zwraca odpowiednią wartość y. Jak? Poprzez połączenie ze sobą dwóch [`smoothstep()`](../glossary/?search=smoothstep). Spójrz na poniżśzy fragment kodu i wstaw go w linijce 20 powyższego przykładu; pomyśl, że dokonane została pionowe cięcie - tło wygląda jak linia, prawda? + + + +```glsl +float y = smoothstep(0.2,0.5,st.x) - smoothstep(0.5,0.8,st.x); +``` + +### Sinus i Cosinus + +Kiedy chcesz użyć matematyki do animacji, kształtowania lub blendowania wartości, nie ma nic lepszego niż zaprzyjaźnienie się z sinusem i cosinusem. + + + +Te dwie podstawowe funkcje trygonometryczne współpracują ze sobą, aby skonstruować okręgi, które są tak poręczne jak szwajcarski scyzoryk MacGyvera. Warto wiedzieć, jak się zachowują i na jakie sposoby można je łączyć. W skrócie, przyjąwszy kąt (w radianach), zwrócą one współrzędne *x* ([cosinus](../glossary/?search=cos)) i *y* ([sinus](../glossary/?search=sin)) punktu na brzegu okręgu o promieniu równym 1. Jednak fakt, że zwracają one znormalizowane wartości (wartości pomiędzy -1 a 1) w tak gładki sposób, czyni z nich niesamowite narzędzie. + + + +![](sincos.gif) + +Choć trudno opisać wszystkie związki między funkcjami trygonometrycznymi i okręgami, powyższa animacja pięknie wizualizuje te związki. + + + +
+ +Przyjrzyj się uważnie powyższej fali sinusoidalnej. Zauważ, jak wartości *y* oscylują płynnie między +1 a -1. Jak widzieliśmy w przykładzie z czasem w poprzednim rozdziale, możesz wykorzystać to rytmiczne zachowanie [`sin()`](../glossary/?search=sin) do animowania dowolnych wartości. Jeśli czytasz ten przykład w przeglądarce, spróbuj zmienić kod w powyższym jedno-linjkowym przykładzie i zaobserwuj, jak zmienia się fala. (Uwaga: nie zapomnij o średniku na końcu linii). + + + + +Spróbuj następnujących ćwiczeń i zobacz, co się stanie + +* Dodaj czas (`u_time`) do *x* wewnątrz funkcji `sin`. Zapamiętaj ten **ruch** wzdłuż *x*. + +* Pomnóż *x* przez `PI` wewnątrz funkcji `sin`. Zauważ, jak okres sinusa **zmniejsza się** do 2. Zwiększyliśmy w ten sposób częstotliwość. + +* Pomnóż czas (`u_time`) przez *x* wewnątrz funkcji `sin`. Zobacz jak **częstotliwość** zwiększa się, a okres maleje. Możliwe że u_time może być już bardzo duży, co czyni wykres trudnym do odczytania - odśwież stronę i spróbuj ponownie. + +* Dodaj 1.0 do [`sin(x)`](../glossary/?search=sin). Zobacz jak cała fala jest **przesunięta** w górę i wszystkie wartości są pomiędzy 0.0 a 2.0. + +* Pomnóż [`sin(x)`](../glossary/?search=sin) przez 2.0. Zobacz jak **amplituda** podwaja się. + +* Oblicz wartość bezwzględną ([`abs()`](../glossary/?search=abs)) funkcji `sin(x)`. Wygląda to jak ślad **odbijającej się** piłki. + +* Wyciągnij tylko część ułamkową ([`fract()`](../glossary/?search=fract)) z funkcji [`sin(x)`](../glossary/?search=sin). + +* Dodaj sufit ([`ceil()`](../glossary/?search=ceil)) oraz podłogę ([`floor()`](../glossary/?search=floor)) z [`sin(x)`](../glossary/?search=sin), aby otrzymać falę cyfrową o wartościach 1 i -1. + + + + +### Kilka dodatkowych przydatnych funkcji + +Pod koniec ostatniego ćwiczenia wprowadziliśmy kilka nowych funkcji. Teraz czas na eksperymentowanie z każdą z nich poprzez odkomentowanie poniższych linii po kolei. Poznaj te funkcje i zbadaj jak się zachowują. Wiem, zastanawiasz się... dlaczego? Szybkie wyszukiwanie w google "generative art" powie Ci to. Pamiętaj, że te funkcje to nasz płot. Opanowujemy ruch w jednym wymiarze, w górę i w dół. Już niedługo przyjdzie czas na dwa, trzy i cztery wymiary! + + + +![Anthony Mattox (2009)](anthony-mattox-ribbon.jpg) + +
+ + + +### Zaawansowane funkcje kształtujące + +[Golan Levin](http://www.flong.com/) ma świetną dokumentację bardziej złożonych funkcji kształtujących, które są niezwykle pomocne. Samodzielene przeniesienie ich do GLSL jest dobrym krokiem w stronę budowania własnego zasobu snippetów kodu. + + + +* Wielomianowe Funkcje Kształtujące: [www.flong.com/archive/texts/code/shapers_poly](http://www.flong.com/archive/texts/code/shapers_poly/) + +* Wykładnicze Funkcje Kształtujące: [www.flong.com/archive/texts/code/shapers_exp](http://www.flong.com/archive/texts/code/shapers_exp/) + +* Kołowe i Eliptyczne Funkcje Kształtujące: [www.flong.com/archive/texts/code/shapers_circ](http://www.flong.com/archive/texts/code/shapers_circ/) + +* Parametryczne (Beziera) Funkcje Kształtujące: [www.flong.com/archive/texts/code/shapers_bez](http://www.flong.com/archive/texts/code/shapers_bez/) + + + + +
+ +Podobnie jak szefowie kuchni, którzy zbierają przyprawy i egzotyczne składniki, artyści cyfrowi i kreatywni koderzy mają szczególne zamiłowanie do pracy nad własnymi funkcjami kształtującymi. + + + +[Iñigo Quiles](http://www.iquilezles.org/) ma wspaniałą kolekcję [użytecznych funkcji](http://www.iquilezles.org/www/articles/functions/functions.htm). Po przeczytaniu [tego artykułu](http://www.iquilezles.org/www/articles/functions/functions.htm) spójrz na poniższe tłumaczenie tych funkcji na GLSL. Zwróć uwagę na wymagane małe zmiany, jak stawianie "." (kropki) na liczbach zmiennoprzecinkowych i używanie nazw GLSL dla funkcji *C*; na przykład zamiast `powf()` użyj `pow()`: + +[Iñigo Quiles](http://www.iquilezles.org/) has a great collection of [useful functions](http://www.iquilezles.org/www/articles/functions/functions.htm). After reading [this article](http://www.iquilezles.org/www/articles/functions/functions.htm) take a look at the following translation of these functions to GLSL. Pay attention to the small changes required, like putting the "." (dot) on floating point numbers and using the GLSL name for *C functions*; for example instead of `powf()` use `pow()`: + +
+ +To keep your motivation up, here is an elegant example (made by [Danguafer](https://www.shadertoy.com/user/Danguafer)) of mastering the shaping-functions karate. + + + +In the *Next >>* chapter we will start using our new moves. First with mixing colors and then drawing shapes. + +#### Exercise + +Take a look at the following table of equations made by [Kynd](http://www.kynd.info/log/). See how he is combining functions and their properties to control the values between 0.0 and 1.0. Now it's time for you to practice by replicating these functions. Remember the more you practice the better your karate will be. + +![Kynd - www.flickr.com/photos/kynd/9546075099/ (2013)](kynd.png) + +#### For your toolbox + +Here are some tools that will make it easier for you to visualize these types of functions. + +* Grapher: if you have a MacOS computer, type `grapher` in your spotlight and you'll be able to use this super handy tool. + +![OS X Grapher (2004)](grapher.png) + +* [GraphToy](http://www.iquilezles.org/apps/graphtoy/): once again [Iñigo Quilez](http://www.iquilezles.org) made a tool to visualize GLSL functions in WebGL. + +![Iñigo Quilez - GraphToy (2010)](graphtoy.png) + +* [Shadershop](http://tobyschachman.com/Shadershop/): this amazing tool created by [Toby Schachman](http://tobyschachman.com/) will teach you how to construct complex functions in an incredible visual and intuitive way. + +![Toby Schachman - Shadershop (2014)](shadershop.png) diff --git a/Questions_to_author.txt b/Questions_to_author.txt index ba283c8..695b5c6 100644 --- a/Questions_to_author.txt +++ b/Questions_to_author.txt @@ -5,4 +5,10 @@ Podać polskie tłumaczenie słowa pipeline Podać angielskie tłumaczenie wejście i wyjście -Wytłumaczyć "hot reloading" (04) \ No newline at end of file +Wytłumaczyć "hot reloading" (04) +użyć "akceleracja sprzętowa" zamiast "zaimplementowane w hardware" +"linii" vs "linijce" +blending - blending +shapin - kształtowanie +shaping functions - funkcje kształtujące +kreatywni koderzy \ No newline at end of file From d010ba0ad63f0161f32ddb87e0962d680a488b8c Mon Sep 17 00:00:00 2001 From: Wojtek Date: Tue, 7 Feb 2023 16:58:19 +0100 Subject: [PATCH 13/23] prepare 11 and 12 --- 11/README-pl.md | 340 ++++++++++++++++++++++++++++++++++++++++++++++++ 12/README-pl.md | 260 ++++++++++++++++++++++++++++++++++++ 2 files changed, 600 insertions(+) create mode 100644 11/README-pl.md create mode 100644 12/README-pl.md diff --git a/11/README-pl.md b/11/README-pl.md new file mode 100644 index 0000000..2f25c08 --- /dev/null +++ b/11/README-pl.md @@ -0,0 +1,340 @@ + +![NASA / WMAP science team](mcb.jpg) + +## Szum (ang. "noise") + +Czas na przerwę! Bawiliśmy się losowymi funkcjami, które wyglądają jak telewizyjny biały szum, w głowie wciąż się kręci myśląc o shaderach, a oczy są zmęczone. Czas wyjść na spacer! + +Czujemy powietrze na skórze, słońce na twarzy. Świat jest tak żywym i bogatym miejscem. Kolory, tekstury, dźwięki. Podczas spaceru nie możemy nie zauważyć powierzchni dróg, skał, drzew i chmur. + + + +![](texture-00.jpg) +![](texture-01.jpg) +![](texture-02.jpg) +![](texture-03.jpg) +![](texture-04.jpg) +![](texture-05.jpg) +![](texture-06.jpg) + +Nieprzewidywalność tych tekstur można by nazwać "losową", ale nie przypominają one losowości, z którą bawiliśmy się wcześniej. "Prawdziwy świat" jest tak bogatym i złożonym miejscem! Jak możemy przybliżyć tę różnorodność obliczeniowo? + +To było pytanie, które [Ken Perlin](https://mrl.nyu.edu/~perlin/) próbował rozwiązać we wczesnych latach 80-tych, kiedy otrzymał zlecenie wygenerowania bardziej realistycznych tekstur do filmu "Tron". W odpowiedzi na to wymyślił elegancki *Oscar winning* algorytm szumu. (No biggie.) + + + +![Disney - Tron (1982)](tron.jpg) + +Poniższe nie jest klasycznym algorytmem szumu Perlina, ale jest dobrym punktem wyjścia do zrozumienia sposobu generowania szumu. + + + +
+ +W tych liniach robimy coś podobnego do tego, co robiliśmy w poprzednim rozdziale. Dzielimy ciągłą liczbę zmiennoprzecinkową (``x``) na jej składowe całkowitą (``i``) i ułamkową (``f``). Używamy [``floor()``](../glossary/?search=floor) aby uzyskać ``i`` oraz [``fract()``](../glossary/?search=fract) aby uzyskać ``f```. Następnie stosujemy ``rand()`` do części całkowitej ``x``, co daje unikalną wartość losową dla każdej liczby całkowitej. + +Po tym widzisz dwie skomentowane linie. Pierwsza z nich interpoluje liniowo każdą wartość losową. + + + + +```glsl +y = mix(rand(i), rand(i + 1.0), f); +``` + +Idź dalej i odkomentuj tę linię, aby zobaczyć jak to wygląda. Używamy [``fract()``](../glossary/?search=fract) wartości przechowywanych w `f` do [``mix()``](../glossary/?search=mix) dwóch losowych wartości. + +W tym momencie książki nauczyliśmy się, że możemy zrobić coś lepszego niż interpolacja liniowa, prawda? +Spróbuj teraz odkomentować następującą linię, która używa interpolacji [``smoothstep()``](../glossary/?search=smoothstep) zamiast liniowej. + + + +```glsl +y = mix(rand(i), rand(i + 1.0), smoothstep(0.,1.,f)); +``` + +Po odkomentowaniu go zauważ, jak przejście między szczytami staje się gładkie. W niektórych implementacjach szumu można zauważyć, że programiści wolą kodować własne krzywe sześcienne (jak poniższy wzór) zamiast używać [``smoothstep()``](../glossary/?search=smoothstep). + + + +```glsl +float u = f * f * (3.0 - 2.0 * f ); // custom cubic curve +y = mix(rand(i), rand(i + 1.0), u); // using it in the interpolation +``` + +Ta *płynna losowość* jest przełomem dla inżynierów graficznych i artystów - daje możliwość generowania obrazów i geometrii z organicznym uczuciem. Algorytm Szumu Perlina był wielokrotnie implementowany w różnych językach i wymiarach, aby stworzyć hipnotyzujące dzieła dla wszystkich rodzajów kreatywnych zastosowań. + + + +![Robert Hodgin - Written Images (2010)](robert_hodgin.jpg) + +Teraz twoja kolej: + +* Stwórz własną funkcję ``float noise(float x)``. + +* Użyj swojej funkcji szumu do animowania kształtu poprzez przesuwanie go, obracanie lub skalowanie. + +* Zrób animowaną kompozycję kilku kształtów "tańczących" razem przy użyciu szumu. + +* Skonstruuj "organicznie wyglądające" kształty używając funkcji noise. + +* Gdy masz już swoje "stworzenie", spróbuj rozwinąć je w postać, przypisując mu określony ruch. + + + +## 2D Noise + +![](02.png) + +Teraz, gdy wiemy jak zrobić szum w 1D, czas przejść do 2D. W 2D zamiast interpolować między dwoma punktami linii (``fract(x)`` i ``fract(x)+1. 0``), będziemy interpolować pomiędzy czterema narożnikami kwadratowego obszaru płaszczyzny (``fract(st)``, ``fract(st)+vec2(1.,0.)``, ``fract(st)+vec2(0.,1.)``` oraz ``fract(st)+vec2(1.,1.)``). + + + +![](01.png) + +Podobnie, jeśli chcemy uzyskać szum 3D musimy interpolować pomiędzy ośmioma rogami sześcianu. W tej technice chodzi o interpolację losowych wartości, dlatego nazywa się ją **szumem wartościowym**. + + + +![](04.jpg) + +Podobnie jak w przykładzie 1D, ta interpolacja nie jest liniowa, ale sześcienna, która płynnie interpoluje wszelkie punkty wewnątrz naszej kwadratowej siatki. + + + +![](05.jpg) + +Przyjrzyj się następującej funkcji hałasu. + + + +
+ +Zaczynamy od przeskalowania przestrzeni o 5 (linia 45), aby zobaczyć interpolację pomiędzy kwadratami siatki. Następnie wewnątrz funkcji szumu dzielimy przestrzeń na komórki. Przechowujemy całkowitą pozycję komórki wraz z pozycjami ułamkowymi wewnątrz komórki. Używamy pozycji całkowitej do obliczenia współrzędnych czterech narożników i otrzymujemy losową wartość dla każdego z nich (linie 23-26). Na koniec, w linii 35 interpolujemy pomiędzy 4 losowymi wartościami narożników używając pozycji frakcyjnych, które przechowywaliśmy wcześniej. + + + +Teraz twoja kolej. Spróbuj wykonać następujące ćwiczenia: + +* Zmień mnożnik linii 45. Spróbuj go animować. + +* Przy jakim poziomie powiększenia szum zaczyna znowu wyglądać jak losowy? + +* Przy jakim poziomie powiększenia szum jest niezauważalny? + +* Spróbuj podpiąć tę funkcję szumu do współrzędnych myszy. + +* A gdyby tak potraktować gradient szumu jako pole odległości? Zrób z tym coś ciekawego. + +* Teraz, gdy osiągnąłeś już pewną kontrolę nad porządkiem i chaosem, czas wykorzystać tę wiedzę. Stwórz kompozycję z prostokątów, kolorów i szumu, która przypomina nieco złożoność obrazu [Marka Rothko](http://en.wikipedia.org/wiki/Mark_Rothko). + + + +![Mark Rothko - Three (1950)](rothko.jpg) + +## Using Noise in Generative Designs + +Algorytmy szumu zostały pierwotnie zaprojektowane w celu nadania naturalnego *je ne sais quoi* cyfrowym teksturom. Implementacje 1D i 2D, które widzieliśmy do tej pory, były interpolacjami pomiędzy losowymi *wartościami*, dlatego nazywane są **Value Noise**, ale istnieje więcej sposobów na uzyskanie szumu... + + + +[ ![Inigo Quilez - Value Noise](value-noise.png) ](../edit.php#11/2d-vnoise.frag) + +Jak odkryłeś w poprzednich ćwiczeniach, szum wartości ma tendencję do wyglądania "blokowo". Aby zmniejszyć ten blokowy efekt, w 1985 roku [Ken Perlin](https://mrl.nyu.edu/~perlin/) opracował inną implementację algorytmu o nazwie **Gradient Noise**. Ken wymyślił jak interpolować losowe *gradienty* zamiast wartości. Gradienty te były wynikiem funkcji losowej 2D, która zwraca kierunki (reprezentowane przez ``vec2``) zamiast pojedynczych wartości (``float``). Kliknij na poniższy obrazek, aby zobaczyć kod i sposób jego działania. + + + +[ ![Inigo Quilez - Gradient Noise](gradient-noise.png) ](../edit.php#11/2d-gnoise.frag) + +Poświęć chwilę na przyjrzenie się tym dwóm przykładom autorstwa [Inigo Quilez](http://www.iquilezles.org/) i zwróć uwagę na różnice pomiędzy [value noise](https://www.shadertoy.com/view/lsf3WH) a [gradient noise](https://www.shadertoy.com/view/XdXGW8). + +Podobnie jak malarz, który rozumie, jak działają pigmenty jego farb, im więcej wiemy o implementacjach szumu, tym lepiej będziemy mogli z nich korzystać. Na przykład, jeśli użyjemy dwuwymiarowej implementacji szumu do obrócenia przestrzeni, w której renderowane są linie proste, możemy uzyskać następujący efekt swirly, który wygląda jak drewno. Ponownie możesz kliknąć na obrazek, aby zobaczyć, jak wygląda kod. + + + +[ ![Wood texture](wood-long.png) ](../edit.php#11/wood.frag) + +```glsl + pos = rotate2d( noise(pos) ) * pos; // rotate the space + pattern = lines(pos,.5); // draw lines +``` + +Innym sposobem na uzyskanie ciekawych wzorów z szumu jest potraktowanie go jak pola odległości i zastosowanie niektórych sztuczek opisanych w rozdziale [Kształty](../07/). + + + +[ ![Splatter texture](splatter-long.png) ](../edit.php#11/splatter.frag) + +```glsl + color += smoothstep(.15,.2,noise(st*10.)); // Black splatter + color -= smoothstep(.35,.4,noise(st*10.)); // Holes on splatter +``` + +Trzecim sposobem wykorzystania funkcji szumu jest modulowanie kształtu. To również wymaga pewnych technik, które poznaliśmy w [rozdziale o kształtach](../07/). + + + + + +Dla Ciebie do poćwiczenia: + +* Jaki inny wzór generatywny możesz stworzyć? Co z granitem? marmurem? magmą? wodą? Znajdź trzy zdjęcia interesujących Cię tekstur i zaimplementuj je algorytmicznie za pomocą szumu. +* Użyj szumu do modulacji kształtu. +* A co z wykorzystaniem szumu do ruchu? Wróć do rozdziału [Matrix](../08/). Użyj przykładu tłumaczenia, które przesuwa "+" wokół siebie i zastosuj do niego kilka *losowych* i *szumowych* ruchów. +* Zrób generatywnego Jacksona Pollocka. + + + +![Jackson Pollock - Number 14 gray (1948)](pollock.jpg) + +## Improved Noise + +Ulepszeniem Perlina do jego oryginalnego szumu **Simplex Noise**, jest zastąpienie sześciennej krzywej Hermite'a ( _f(x) = 3x^2-2x^3_ , która jest identyczna z funkcją [``smoothstep()``](../glossary/?search=smoothstep)) kwintową krzywą interpolacyjną ( _f(x) = 6x^5-15x^4+10x^3_ ). Dzięki temu oba końce krzywej są bardziej "płaskie", więc każda granica z wdziękiem zszywa się z następną. Innymi słowy, otrzymujesz bardziej ciągłe przejście między komórkami. Możesz to zobaczyć, odkomentowując drugą formułę w poniższym przykładzie wykresu (lub zobacz [dwa równania obok siebie tutaj](https://www.desmos.com/calculator/2xvlk5xp8b)). + + + +
+ +Zauważ, jak zmieniają się końce krzywej. Więcej na ten temat możesz przeczytać w [słowach własnych Kena](http://mrl.nyu.edu/~perlin/paper445.pdf). + + + + +## Simplex Noise + +Dla Kena Perlina sukces jego algorytmu nie był wystarczający. Uważał, że może on działać lepiej. Na Siggraph 2001 zaprezentował "simplex noise", w którym osiągnął następujące ulepszenia w stosunku do poprzedniego algorytmu: + +* Algorytm o mniejszej złożoności obliczeniowej i mniejszej liczbie mnożeń. +* Szum, który skaluje się do wyższych wymiarów przy mniejszym koszcie obliczeniowym. +* Szum bez artefaktów kierunkowych. +* Szum z dobrze zdefiniowanymi i ciągłymi gradientami, które mogą być obliczane dość tanio. +* Algorytm, który jest łatwy do zaimplementowania w sprzęcie. + + + +Wiem, co myślisz... "Kim jest ten człowiek?" Tak, jego praca jest fantastyczna! Ale poważnie, w jaki sposób ulepszył algorytm? Cóż, widzieliśmy jak dla dwóch wymiarów interpolował 4 punkty (rogi kwadratu); możemy więc poprawnie zgadnąć, że dla [trzech (zobacz implementację tutaj)](../edit.php#11/3d-noise.frag) i czterech wymiarów musimy interpolować 8 i 16 punktów. Prawda? Innymi słowy dla N wymiarów musisz płynnie interpolować 2 do N punktów (2^N). Ale Ken sprytnie zauważył, że chociaż oczywistym wyborem dla kształtu wypełniającego przestrzeń jest kwadrat, najprostszym kształtem w 2D jest trójkąt równoboczny. Zaczął więc od zastąpienia siatki kwadratowej (właśnie nauczyliśmy się jej używać) siatką simplex trójkątów równobocznych. + + + +![](simplex-grid-00.png) + +Kształt simplex dla N wymiarów to kształt z N + 1 narożami. Innymi słowy jeden mniejszy narożnik do obliczenia w 2D, 4 mniej narożniki w 3D i 11 mniej narożników w 4D! To ogromna poprawa! + +W dwóch wymiarach interpolacja odbywa się podobnie do zwykłego szumu, poprzez interpolację wartości narożników odcinka. Ale w tym przypadku, dzięki zastosowaniu siatki simplex, musimy tylko interpolować sumę 3 narożników. + + + +![](simplex-grid-01.png) + +Jak powstaje siatka simplex? W kolejnym błyskotliwym i eleganckim posunięciu, siatkę simplex można uzyskać poprzez podział komórek regularnej czteroramiennej siatki na dwa trójkąty równoramienne, a następnie przekrzywianie jej, aż każdy trójkąt będzie równoboczny. + + + +![](simplex-grid-02.png) + + + +Wtedy, jak opisuje [Stefan Gustavson w tej pracy](http://staffwww.itn.liu.se/~stegu/simplexnoise/simplexnoise.pdf): _"...patrząc na części całkowite przekształconych współrzędnych (x,y) dla punktu, który chcemy ocenić, możemy szybko określić, która komórka dwóch prostopadłościanów zawiera ten punkt. Porównując również wielkości x i y, możemy określić, czy punkt znajduje się w górnej czy dolnej prostej i przemierzyć właściwe trzy punkty narożne."_. + +W poniższym kodzie możesz odkomentować linię 44, aby zobaczyć jak siatka jest przekrzywiona, a następnie odkomentować linię 47, aby zobaczyć jak można skonstruować siatkę simpleksową. Zauważ jak w linii 22 dzielimy przekrzywiony kwadrat na dwa trójkąty równoboczne tylko poprzez wykrycie czy ``x > y`` (dolny" trójkąt) lub ``y > x`` (górny" trójkąt). + +
+ + + +Wszystkie te ulepszenia skutkują algorytmicznym arcydziełem znanym jako **Simplex Noise**. Poniżej znajduje się implementacja GLSL tego algorytmu wykonana przez Iana McEwana i Stefana Gustavsona (i przedstawiona w [tym artykule](http://webstaff.itn.liu.se/~stegu/jgt2012/article.pdf)), która jest nadmiernie skomplikowana w celach edukacyjnych, ale z przyjemnością klikniesz na nią i przekonasz się, że jest mniej krypto niż można by się spodziewać, a kod jest krótki i szybki. + +[ ![Ian McEwan of Ashima Arts - Simplex Noise](simplex-noise.png) ](../edit.php#11/2d-snoise-clear.frag) + +Cóż... dość technicznych rozważań, czas na wykorzystanie tego zasobu we własny, ekspresyjny sposób: + +* Kontempluj, jak wygląda każda implementacja szumu. Wyobraź sobie je jako surowy materiał, jak marmurowy kamień dla rzeźbiarza. Co możesz powiedzieć o "uczuciu", jakie ma każda z nich? Zmruż oczy, aby uruchomić wyobraźnię, tak jak wtedy, gdy chcesz znaleźć kształty w chmurze. Co widzisz? Co ci się przypomina? W co wyobrażasz sobie, że każda realizacja hałasu mogłaby zostać wykonana? Podążając za swoimi wnętrznościami i spróbuj zrealizować to w kodzie. + +* Zrób shader, który rzutuje iluzję przepływu. Jak lampa lawowa, krople atramentu, woda itp. + + + + + +* Użyj Simplex Noise, aby dodać trochę tekstury do pracy, którą już wykonałeś. + + + + + +W tym rozdziale wprowadziliśmy pewną kontrolę nad chaosem. Nie była to łatwa praca! Stanie się mistrzem noise-benderów wymaga czasu i wysiłku. + +W następnych rozdziałach zobaczymy kilka dobrze znanych technik, które pozwolą ci udoskonalić swoje umiejętności i wydobyć więcej z szumu, aby zaprojektować wysokiej jakości treść generatywną za pomocą shaderów. Do tego czasu ciesz się czasem na zewnątrz, kontemplując naturę i jej zawiłe wzory. Twoja umiejętność obserwacji wymaga równego (a może nawet większego) poświęcenia niż twoje umiejętności tworzenia. Wyjdź na zewnątrz i ciesz się resztą dnia! + + + +

"Talk to the tree, make friends with it." Bob Ross +

diff --git a/12/README-pl.md b/12/README-pl.md new file mode 100644 index 0000000..436ac5c --- /dev/null +++ b/12/README-pl.md @@ -0,0 +1,260 @@ +![](dragonfly.jpg) + +## Cellular Noise + +W 1996 roku, szesnaście lat po oryginalnym Noise Perlina i pięć lat przed jego Simplex Noise, [Steven Worley napisał pracę zatytułowaną "A Cellular Texture Basis Function"](http://www.rhythmiccanvas.com/research/papers/worley.pdf). Opisuje w niej technikę teksturowania proceduralnego, która jest obecnie szeroko stosowana przez społeczność grafików. + +Aby zrozumieć jej zasady, musimy zacząć myśleć w kategoriach **iteracji**. Zapewne wiesz, co to oznacza: tak, zacznij używać pętli ``for``. Jest tylko jeden haczyk z pętlami ``for`` w GLSL: liczba, którą sprawdzamy musi być stałą (``const``). Tak więc nie ma dynamicznych pętli - liczba iteracji musi być stała. + +Przyjrzyjmy się przykładowi. + + + +### Points for a distance field + +Hałas komórkowy opiera się na polach odległości, czyli odległości do najbliższego ze zbioru punktów charakterystycznych. Załóżmy, że chcemy stworzyć pole odległości składające się z 4 punktów. Co musimy zrobić? Cóż, **dla każdego piksela chcemy obliczyć odległość do najbliższego punktu**. Oznacza to, że musimy iterować po wszystkich punktach, obliczać ich odległości do bieżącego piksela i przechowywać wartość dla tego, który jest najbliższy. + + + +```glsl + float min_dist = 100.; // A variable to store the closest distance to a point + + min_dist = min(min_dist, distance(st, point_a)); + min_dist = min(min_dist, distance(st, point_b)); + min_dist = min(min_dist, distance(st, point_c)); + min_dist = min(min_dist, distance(st, point_d)); +``` + +![](cell-00.png) + +Nie jest to zbyt eleganckie, ale załatwia sprawę. Teraz zaimplementujmy go ponownie, używając tablicy i pętli ``for``. + + + +```glsl + float m_dist = 100.; // minimum distance + for (int i = 0; i < TOTAL_POINTS; i++) { + float dist = distance(st, points[i]); + m_dist = min(m_dist, dist); + } +``` + +Zauważ, jak używamy pętli ``for`` do iteracji przez tablicę punktów i śledzenia minimalnej odległości za pomocą funkcji [``min()``](../glossary/?search=min). Oto krótka działająca implementacja tego pomysłu: + + + +
+ +W powyższym kodzie jeden z punktów jest przypisany do pozycji myszy. Pobaw się nim, abyś mógł intuicyjnie zorientować się, jak zachowuje się ten kod. Następnie spróbuj tego: + +- Jak można animować pozostałe punkty? +- Po przeczytaniu [rozdziału o kształtach](../07/), wyobraź sobie ciekawe sposoby wykorzystania tego pola odległości! +- Co, jeśli chcemy dodać więcej punktów do tego pola odległości? Co jeśli chcemy dynamicznie dodawać/odejmować punkty? + + + +### Tiling and iteration + +Zapewne zauważyłeś, że pętle ``for`` i *arrays* nie są zbyt dobrymi przyjaciółmi GLSL. Jak już wspomnieliśmy, pętle nie akceptują dynamicznych ograniczeń na ich warunek wyjścia. Ponadto, iteracja przez wiele instancji znacznie zmniejsza wydajność twojego shadera. Oznacza to, że nie możemy użyć tego bezpośredniego podejścia dla dużych ilości punktów. Musimy znaleźć inną strategię, taką, która wykorzystuje architekturę przetwarzania równoległego GPU. + + + +![](cell-01.png) + +Jednym ze sposobów podejścia do tego problemu jest podzielenie przestrzeni na płytki. Nie każdy piksel musi sprawdzać odległość do każdego punktu, prawda? Biorąc pod uwagę fakt, że każdy piksel działa w swoim własnym wątku, możemy podzielić przestrzeń na komórki, z których każda ma jeden unikalny punkt do oglądania. Ponadto, aby uniknąć aberracji na krawędziach między komórkami musimy sprawdzić odległości do punktów na sąsiednich komórkach. To jest główna idea brillant [Steven Worley's paper](http://www.rhythmiccanvas.com/research/papers/worley.pdf). Na koniec każdy piksel musi sprawdzić tylko dziewięć pozycji: punkt własnej komórki i punkty w 8 komórkach wokół niego. Przestrzeń na komórki dzielimy już w rozdziałach o: [wzorach](../09/), [losowości](../10/) i [szumie](../11/), więc mam nadzieję, że jesteś już zaznajomiony z tą techniką. + + + +```glsl + // Scale + st *= 3.; + + // Tile the space + vec2 i_st = floor(st); + vec2 f_st = fract(st); +``` + +Jaki jest więc plan? Użyjemy współrzędnych kafla (przechowywanych we współrzędnej całkowitej, ``i_st``) do skonstruowania losowej pozycji punktu. Funkcja ``random2f``, której użyjemy, otrzymuje ``vec2`` i daje nam ``vec2`` z losową pozycją. Tak więc, dla każdego kafla będziemy mieli jeden punkt charakterystyczny w losowej pozycji w obrębie kafla. + + + +```glsl + vec2 point = random2(i_st); +``` + +Każdy piksel wewnątrz tego kafla (przechowywany we współrzędnej float, ``f_st``) sprawdzi swoją odległość do tego losowego punktu. + + + +```glsl + vec2 diff = point - f_st; + float dist = length(diff); +``` + +Wynik będzie wyglądał tak: + + + + + +Nadal musimy sprawdzać odległości do punktów w okolicznych kaflach, a nie tylko do tego w bieżącym kaflu. W tym celu musimy **iterować** po sąsiednich kaflach. Nie wszystkie kafle, tylko te bezpośrednio otaczające bieżący. Czyli od ``-1`` (lewy) do ``1`` (prawy) kafla w osi ``x`` oraz od ``-1`` (dolny) do ``1`` (górny) w osi ``y``. Region 3x3 składający się z 9 płytek może być iterowany przy użyciu podwójnej pętli ``for``, jak ta: + + + +```glsl +for (int y= -1; y <= 1; y++) { + for (int x= -1; x <= 1; x++) { + // Neighbor place in the grid + vec2 neighbor = vec2(float(x),float(y)); + ... + } +} +``` + +![](cell-02.png) + +Teraz możemy obliczyć położenie punktów na każdym z sąsiadów w naszej podwójnej pętli ``for``, dodając przesunięcie sąsiedniego kafla do bieżącej współrzędnej kafla. + + + +```glsl + ... + // Random position from current + neighbor place in the grid + vec2 point = random2(i_st + neighbor); + ... +``` + +Reszta polega na obliczeniu odległości do tego punktu i zapisaniu najbliższego w zmiennej o nazwie ``m_dist`` (dla minimalnej odległości). + + + +```glsl + ... + vec2 diff = neighbor + point - f_st; + + // Distance to the point + float dist = length(diff); + + // Keep the closer distance + m_dist = min(m_dist, dist); + ... +``` + +Powyższy kod jest inspirowany przez [ten artykuł Inigo's Quilez](http://www.iquilezles.org/www/articles/smoothvoronoi/smoothvoronoi.htm), gdzie powiedział: + +*"... może warto zauważyć, że w tym kodzie powyżej jest ładna sztuczka. Większość implementacji cierpi z powodu problemów z precyzją, ponieważ generują swoje losowe punkty w przestrzeni "domeny" (jak przestrzeń "świata" lub "obiektu"), która może być dowolnie daleko od pochodzenia. Można rozwiązać ten problem przenosząc cały kod do typów danych o wyższej precyzji, lub będąc nieco sprytnym. Moja implementacja nie generuje punktów w przestrzeni "domeny", ale w przestrzeni "komórki": po wyodrębnieniu części całkowitych i ułamkowych punktu cieniowania, a zatem zidentyfikowaniu komórki, w której pracujemy, wszystko, co nas obchodzi, to to, co dzieje się wokół tej komórki, co oznacza, że możemy porzucić wszystkie całkowite części naszych współrzędnych, oszczędzając wiele bitów precyzji. W rzeczywistości, w zwykłej implementacji voronoi, całkowite części współrzędnych punktów po prostu znoszą się, gdy losowe punkty charakterystyczne na komórkę są odejmowane od punktu cieniowania. W powyższej implementacji nie pozwalamy nawet na to anulowanie, ponieważ przenosimy wszystkie obliczenia do przestrzeni "komórek". Ta sztuczka pozwala także na obsługę przypadku, gdy chcemy voronoi-shade'ować całą planetę - można po prostu zamienić dane wejściowe na podwójną precyzję, wykonać obliczenia floor() i fract(), a z resztą obliczeń przejść na zmiennoprzecinkowe bez ponoszenia kosztów zmiany całej implementacji na podwójną precyzję. Oczywiście, ta sama sztuczka dotyczy wzorców Perlin Noise (ale nigdy nie widziałem tego zaimplementowanego ani udokumentowanego gdziekolwiek). "* + + + +Rekapitulacja: dzielimy przestrzeń na kafelki; każdy piksel obliczy odległość do punktu w swoim własnym kafelku i otaczających go 8 kafelków; przechowuj najbliższą odległość. Wynikiem jest pole odległości, które wygląda jak w poniższym przykładzie: + + + +
+ +Eksploruj to dalej przez: + +- Skalowanie przestrzeni o różne wartości. +- Czy możesz wymyślić inne sposoby animacji punktów? +- Co jeśli chcemy obliczyć dodatkowy punkt z pozycji myszy? +- Jakie inne sposoby konstruowania tego pola odległości możesz sobie wyobrazić, poza ``m_dist = min(m_dist, dist);``? +- Jakie ciekawe wzory można stworzyć za pomocą tego pola odległości? + + + +Algorytm ten można również interpretować z perspektywy punktów, a nie pikseli. W takim przypadku można go opisać jako: każdy punkt rośnie, dopóki nie znajdzie rosnącego obszaru z innego punktu. Odzwierciedla to niektóre z zasad wzrostu w naturze. Żywe formy są kształtowane przez to napięcie pomiędzy wewnętrzną siłą do rozszerzania się i wzrostu, a ograniczeniami przez siły zewnętrzne. Klasyczny algorytm symulujący to zachowanie nosi nazwę [Georgy Voronoi](https://en.wikipedia.org/wiki/Georgy_Voronoy). + + + +![](monokot_root.jpg) + +### Voronoi Algorithm + +Konstruowanie diagramów Voronoi z szumu komórkowego jest mniej trudne niż mogłoby się wydawać. Musimy tylko *zachować* pewną dodatkową informację o dokładnym punkcie, który jest najbliżej piksela. Do tego celu użyjemy ``vec2`` o nazwie ``m_point``. Przechowując kierunek wektora do środka najbliższego punktu, zamiast tylko odległości, będziemy "przechowywać" "unikalny" identyfikator tego punktu. + + + +```glsl + ... + if( dist < m_dist ) { + m_dist = dist; + m_point = point; + } + ... +``` + +Zauważ, że w poniższym kodzie nie używamy już ``min`` do obliczania najbliższej odległości, ale zwykłej deklaracji ``if``. Dlaczego? Ponieważ tak naprawdę chcemy zrobić coś więcej za każdym razem, gdy pojawi się nowy bliższy punkt, a mianowicie zapisać jego pozycję (linie 32 do 37). + + + +
+ +Zauważ, jak kolor komórki ruchomej (związanej z pozycją myszy) zmienia kolor w zależności od jej położenia. To dlatego, że kolor jest przypisywany przy użyciu wartości (pozycji) najbliższego punktu. + +Tak jak zrobiliśmy to wcześniej, teraz nadszedł czas, aby to przeskalować, przechodząc na podejście [Steven Worley's paper's approach](http://www.rhythmiccanvas.com/research/papers/worley.pdf). Spróbuj zaimplementować to samodzielnie. Możesz skorzystać z pomocy poniższego przykładu, klikając na niego. Zauważ, że oryginalne podejście Stevena Worleya używa zmiennej liczby punktów cech dla każdego kafla, więcej niż jeden w większości kafli. W jego implementacji programowej w C, jest to używane do przyspieszenia pętli poprzez wykonanie wczesnych wyjść. Pętle GLSL nie pozwalają na zmienną liczbę iteracji, więc prawdopodobnie chcesz trzymać się jednego punktu charakterystycznego na kafel. + + + + + +Gdy już rozgryziesz ten algorytm, pomyśl o ciekawych i kreatywnych jego zastosowaniach. + + + +![Extended Voronoi - Leo Solaas (2011)](solas.png) + +![Cloud Cities - Tomás Saraceno (2011)](saraceno.jpg) + +![Accretion Disc Series - Clint Fulkerson](accretion.jpg) + +![Vonoroi Puzzle - Reza Ali (2015)](reza.png) + +### Improving Voronoi + +W 2011 roku [Stefan Gustavson zoptymalizował algorytm Stevena Worleya dla GPU](http://webstaff.itn.liu.se/~stegu/GLSL-cellular/GLSL-cellular-notes.pdf), wykonując iterację tylko przez macierz 2x2 zamiast 3x3. To znacznie zmniejsza ilość pracy, ale może tworzyć artefakty w postaci nieciągłości na krawędziach między płytkami. Przyjrzyj się poniższym przykładom. + + + +
+ +Później w 2012 roku [Inigo Quilez napisał artykuł o tym, jak zrobić precyzyjne granice Voronoi](http://www.iquilezles.org/www/articles/voronoilines/voronoilines.htm). + + + + + +Eksperymenty Inigo z Voronoi nie skończyły się na tym. W 2014 roku napisał ten ładny artykuł o tym, co nazywa [voro-noise](http://www.iquilezles.org/www/articles/voronoise/voronoise.htm), funkcją, która pozwala na stopniowe mieszanie się między zwykłym szumem a voronoi. Jego słowami: + +*"Pomimo tego podobieństwa, faktem jest, że sposób użycia siatki w obu wzorach jest inny. Szum interpoluje/uśrednia wartości losowe (jak w szumie wartościowym) lub gradienty (jak w szumie gradientowym), podczas gdy Voronoi oblicza odległość do najbliższego punktu charakterystycznego. Teraz, interpolacja gładko-biliniowa i ocena minimalna to dwie bardzo różne operacje, czy... są? Czy być może można je połączyć w bardziej ogólną metrykę? Gdyby tak było, to zarówno Szum jak i Wzory Voronoi mogłyby być postrzegane jako szczególne przypadki bardziej ogólnego generatora wzorów opartego na siatce? "*. + + + + + +Teraz nadszedł czas, abyś przyjrzał się bliżej rzeczom, zainspirował się naturą i znalazł swoje własne ujęcie tej techniki! + + + +![Deyrolle glass film - 1831](DeyrolleFilm.png) + +
From a6b06a176da275689d5efe19ce739c084fcd45f4 Mon Sep 17 00:00:00 2001 From: Wojtek Date: Fri, 10 Feb 2023 16:33:18 +0100 Subject: [PATCH 14/23] 11 --- 11/README-pl.md | 97 ++++++++++++++++++++++++------------------------- 1 file changed, 48 insertions(+), 49 deletions(-) diff --git a/11/README-pl.md b/11/README-pl.md index 2f25c08..4b58d69 100644 --- a/11/README-pl.md +++ b/11/README-pl.md @@ -3,9 +3,9 @@ ## Szum (ang. "noise") -Czas na przerwę! Bawiliśmy się losowymi funkcjami, które wyglądają jak telewizyjny biały szum, w głowie wciąż się kręci myśląc o shaderach, a oczy są zmęczone. Czas wyjść na spacer! +Czas na przerwę! Bawiliśmy się losowymi funkcjami, które wyglądają jak biało-czarny szum telewizyjny (tzw. "szum biały", ang. "white noise"), w głowie wciąż się kręci od myślenia o shaderach, a oczy są po prostu zmęczone. Czas wyjść na spacer! -Czujemy powietrze na skórze, słońce na twarzy. Świat jest tak żywym i bogatym miejscem. Kolory, tekstury, dźwięki. Podczas spaceru nie możemy nie zauważyć powierzchni dróg, skał, drzew i chmur. +Czujemy powietrze na skórze, słońce na twarzy. Świat jest tak żywym i bogatym miejscem. Kolory, tekstury, dźwięki. Podczas spaceru widzimy powierzchnię dróg, skał, drzew i chmur. @@ -45,7 +45,7 @@ y = rand(i); //rand() is described in the previous chapter W tych liniach robimy coś podobnego do tego, co robiliśmy w poprzednim rozdziale. Dzielimy ciągłą liczbę zmiennoprzecinkową (``x``) na jej składowe całkowitą (``i``) i ułamkową (``f``). Używamy [``floor()``](../glossary/?search=floor) aby uzyskać ``i`` oraz [``fract()``](../glossary/?search=fract) aby uzyskać ``f```. Następnie stosujemy ``rand()`` do części całkowitej ``x``, co daje unikalną wartość losową dla każdej liczby całkowitej. -Po tym widzisz dwie skomentowane linie. Pierwsza z nich interpoluje liniowo każdą wartość losową. +Spójrz na dwie skomentowane linie. Pierwsza z nich interpoluje liniowo każdą wartość losową. ```glsl -float u = f * f * (3.0 - 2.0 * f ); // custom cubic curve -y = mix(rand(i), rand(i + 1.0), u); // using it in the interpolation +float u = f * f * (3.0 - 2.0 * f ); // spersonalizowana funkcja sześcienna +y = mix(rand(i), rand(i + 1.0), u); // interpolacja z jej pomocą ``` -Ta *płynna losowość* jest przełomem dla inżynierów graficznych i artystów - daje możliwość generowania obrazów i geometrii z organicznym uczuciem. Algorytm Szumu Perlina był wielokrotnie implementowany w różnych językach i wymiarach, aby stworzyć hipnotyzujące dzieła dla wszystkich rodzajów kreatywnych zastosowań. +Ta *płynna losowość* jest przełomem dla programistów grafiki i artystów - daje możliwość generowania organicznych obrazów i geometrii. Algorytm Szumu Perlina był wielokrotnie implementowany w różnych językach i wymiarach, aby móc tworzyć hipnotyzujące dzieła w celach kreatywnych. @@ -96,8 +96,6 @@ Teraz twoja kolej: * Skonstruuj "organicznie wyglądające" kształty używając funkcji noise. -* Gdy masz już swoje "stworzenie", spróbuj rozwinąć je w postać, przypisując mu określony ruch. - -## 2D Noise +## Szum 2D ![](02.png) -Teraz, gdy wiemy jak zrobić szum w 1D, czas przejść do 2D. W 2D zamiast interpolować między dwoma punktami linii (``fract(x)`` i ``fract(x)+1. 0``), będziemy interpolować pomiędzy czterema narożnikami kwadratowego obszaru płaszczyzny (``fract(st)``, ``fract(st)+vec2(1.,0.)``, ``fract(st)+vec2(0.,1.)``` oraz ``fract(st)+vec2(1.,1.)``). +Teraz, gdy wiemy jak zrobić szum w 1D, czas przejść do 2D. W 2D zamiast interpolować między dwoma punktami linii (``rand(x)`` i ``rand(x)+1.0``), będziemy interpolować pomiędzy czterema narożnikami kwadratowego obszaru płaszczyzny (``rand(st)``, ``rand(st)+vec2(1.,0.)``, ``rand(st)+vec2(0.,1.)`` oraz ``rand(st)+vec2(1.,1.)``). ![](01.png) -Podobnie, jeśli chcemy uzyskać szum 3D musimy interpolować pomiędzy ośmioma rogami sześcianu. W tej technice chodzi o interpolację losowych wartości, dlatego nazywa się ją **szumem wartościowym**. +Podobnie, jeśli chcemy uzyskać szum 3D musimy interpolować pomiędzy ośmioma rogami sześcianu. W tej technice chodzi o interpolację losowych wartości ang. (ang. "random **value**s"), dlatego nazywa się ją **value noise**. ![](04.jpg) -Podobnie jak w przykładzie 1D, ta interpolacja nie jest liniowa, ale sześcienna, która płynnie interpoluje wszelkie punkty wewnątrz naszej kwadratowej siatki. +Podobnie jak w przykładzie 1D, interpolacja ta nie jest liniowa, ale sześcienna, więc płynnie interpoluje wszelkie punkty wewnątrz naszego kwadratowego obszaru. ![](05.jpg) -Przyjrzyj się następującej funkcji hałasu. +Przyjrzyj się następującej funkcji szumu.
-Zaczynamy od przeskalowania przestrzeni o 5 (linia 45), aby zobaczyć interpolację pomiędzy kwadratami siatki. Następnie wewnątrz funkcji szumu dzielimy przestrzeń na komórki. Przechowujemy całkowitą pozycję komórki wraz z pozycjami ułamkowymi wewnątrz komórki. Używamy pozycji całkowitej do obliczenia współrzędnych czterech narożników i otrzymujemy losową wartość dla każdego z nich (linie 23-26). Na koniec, w linii 35 interpolujemy pomiędzy 4 losowymi wartościami narożników używając pozycji frakcyjnych, które przechowywaliśmy wcześniej. +Zaczynamy od przeskalowania przestrzeni o 5 (linia 45). Następnie wewnątrz funkcji szumu dzielimy przestrzeń na kafellki. Przechowujemy pozycję kafelka jako cześć całkowitą oraz pozycje wewnątrz kafelka jako część ułamkową. Używamy części całkowitej do obliczenia współrzędnych czterech narożników, otrzymując losową wartość dla każdego z nich (linie 23-26). Na koniec, w linii 35 interpolujemy pomiędzy 4 losowymi wartościami narożników używając części ułamkowej. Teraz twoja kolej. Spróbuj wykonać następujące ćwiczenia: -* Zmień mnożnik linii 45. Spróbuj go animować. +* Zmień mnożnik w linii 45. Spróbuj go zanimować. -* Przy jakim poziomie powiększenia szum zaczyna znowu wyglądać jak losowy? +* Przy jakim poziomie powiększenia szum zaczyna znowu wyglądać kompletnie losowo (jak, wspomniany na początku rozdziału, biały szum)? * Przy jakim poziomie powiększenia szum jest niezauważalny? @@ -172,7 +170,7 @@ Teraz twoja kolej. Spróbuj wykonać następujące ćwiczenia: ![Mark Rothko - Three (1950)](rothko.jpg) -## Using Noise in Generative Designs +## Szum a design generatywny Algorytmy szumu zostały pierwotnie zaprojektowane w celu nadania naturalnego *je ne sais quoi* cyfrowym teksturom. Implementacje 1D i 2D, które widzieliśmy do tej pory, były interpolacjami pomiędzy losowymi *wartościami*, dlatego nazywane są **Value Noise**, ale istnieje więcej sposobów na uzyskanie szumu... @@ -180,7 +178,7 @@ Algorytmy szumu zostały pierwotnie zaprojektowane w celu nadania naturalnego *j [ ![Inigo Quilez - Value Noise](value-noise.png) ](../edit.php#11/2d-vnoise.frag) -Jak odkryłeś w poprzednich ćwiczeniach, szum wartości ma tendencję do wyglądania "blokowo". Aby zmniejszyć ten blokowy efekt, w 1985 roku [Ken Perlin](https://mrl.nyu.edu/~perlin/) opracował inną implementację algorytmu o nazwie **Gradient Noise**. Ken wymyślił jak interpolować losowe *gradienty* zamiast wartości. Gradienty te były wynikiem funkcji losowej 2D, która zwraca kierunki (reprezentowane przez ``vec2``) zamiast pojedynczych wartości (``float``). Kliknij na poniższy obrazek, aby zobaczyć kod i sposób jego działania. +Jak odkryłeś w poprzednich ćwiczeniach, value noise ma tendencję do wyglądania "blokowo". Aby zmniejszyć ten blokowy efekt, w 1985 roku [Ken Perlin](https://mrl.nyu.edu/~perlin/) opracował inną implementację algorytmu o nazwie **Gradient Noise**. Ken wymyślił jak interpolować losowe *gradienty* zamiast wartości. Gradienty te były wynikiem funkcji losowej 2D, która zwraca kierunki (reprezentowane przez ``vec2``) zamiast pojedynczych wartości (``float``). Kliknij na poniższy obrazek, aby zobaczyć kod i sposób jego działania. @@ -188,7 +186,7 @@ Jak odkryłeś w poprzednich ćwiczeniach, szum wartości ma tendencję do wygl Poświęć chwilę na przyjrzenie się tym dwóm przykładom autorstwa [Inigo Quilez](http://www.iquilezles.org/) i zwróć uwagę na różnice pomiędzy [value noise](https://www.shadertoy.com/view/lsf3WH) a [gradient noise](https://www.shadertoy.com/view/XdXGW8). -Podobnie jak malarz, który rozumie, jak działają pigmenty jego farb, im więcej wiemy o implementacjach szumu, tym lepiej będziemy mogli z nich korzystać. Na przykład, jeśli użyjemy dwuwymiarowej implementacji szumu do obrócenia przestrzeni, w której renderowane są linie proste, możemy uzyskać następujący efekt swirly, który wygląda jak drewno. Ponownie możesz kliknąć na obrazek, aby zobaczyć, jak wygląda kod. +Podobnie jak malarz, który rozumie, jak działają pigmenty jego farb, im więcej wiemy o implementacjach szumu, tym lepiej będziemy mogli z nich korzystać. Na przykład, jeśli użyjemy dwuwymiarowej implementacji szumu do obrócenia przestrzeni, w której renderowane są linie proste, możemy uzyskać następujący drewno-podobny efekt. Ponownie możesz kliknąć na obrazek, aby zobaczyć, jak wygląda kod. @@ -247,7 +245,7 @@ y = x*x*(3.0-2.0*x); //y = x*x*x*(x*(x*6.-15.)+10.); "> -Zauważ, jak zmieniają się końce krzywej. Więcej na ten temat możesz przeczytać w [słowach własnych Kena](http://mrl.nyu.edu/~perlin/paper445.pdf). +Zauważ, jak zmieniają się końce krzywej. Więcej na ten temat możesz usłyszeć [z ust Kena Perlina](http://mrl.nyu.edu/~perlin/paper445.pdf). @@ -259,8 +257,8 @@ Dla Kena Perlina sukces jego algorytmu nie był wystarczający. Uważał, że mo * Algorytm o mniejszej złożoności obliczeniowej i mniejszej liczbie mnożeń. * Szum, który skaluje się do wyższych wymiarów przy mniejszym koszcie obliczeniowym. * Szum bez artefaktów kierunkowych. -* Szum z dobrze zdefiniowanymi i ciągłymi gradientami, które mogą być obliczane dość tanio. -* Algorytm, który jest łatwy do zaimplementowania w sprzęcie. +* Szum z dobrze zdefiniowanymi i ciągłymi gradientami, o niskim koszcie obliczeniowym. +* Algorytm, który jest łatwy do zaimplementowania w hardware'rze. -Wiem, co myślisz... "Kim jest ten człowiek?" Tak, jego praca jest fantastyczna! Ale poważnie, w jaki sposób ulepszył algorytm? Cóż, widzieliśmy jak dla dwóch wymiarów interpolował 4 punkty (rogi kwadratu); możemy więc poprawnie zgadnąć, że dla [trzech (zobacz implementację tutaj)](../edit.php#11/3d-noise.frag) i czterech wymiarów musimy interpolować 8 i 16 punktów. Prawda? Innymi słowy dla N wymiarów musisz płynnie interpolować 2 do N punktów (2^N). Ale Ken sprytnie zauważył, że chociaż oczywistym wyborem dla kształtu wypełniającego przestrzeń jest kwadrat, najprostszym kształtem w 2D jest trójkąt równoboczny. Zaczął więc od zastąpienia siatki kwadratowej (właśnie nauczyliśmy się jej używać) siatką simplex trójkątów równobocznych. +Wiem, co myślisz... "Kim jest ten człowiek?" Tak, jego praca jest fantastyczna! Ale poważnie, w jaki sposób ulepszył ten algorytm? Cóż, widzieliśmy jak dla dwóch wymiarów interpolował 4 punkty (rogi kwadratu); możemy więc poprawnie zgadnąć, że dla [trzech (zobacz implementację tutaj)](../edit.php#11/3d-noise.frag) i czterech wymiarów musimy interpolować 8 i 16 punktów. Prawda? Innymi słowy dla N wymiarów musisz płynnie interpolować 2 do N punktów (2^N). Ale Ken sprytnie zauważył, że chociaż oczywistym wyborem dla kształtu wypełniającego przestrzeń jest kwadrat, najprostszym kształtem w 2D jest trójkąt równoboczny. Zaczął więc od zastąpienia siatki kwadratowej (niedawno nauczyliśmy się jej używać) siatką trójkątów równobocznych (inaczej zwaną *siatką sympleksową*). ![](simplex-grid-00.png) -Kształt simplex dla N wymiarów to kształt z N + 1 narożami. Innymi słowy jeden mniejszy narożnik do obliczenia w 2D, 4 mniej narożniki w 3D i 11 mniej narożników w 4D! To ogromna poprawa! +Kształt dla N wymiarów to kształt z N + 1 wierzchołkami. Innymi słowy jeden wierzchołek mniej do obliczenia w 2D, 4 wierzchołki mniej w 3D i 11 wierzchołków mniej w 4D! To ogromna poprawa! -W dwóch wymiarach interpolacja odbywa się podobnie do zwykłego szumu, poprzez interpolację wartości narożników odcinka. Ale w tym przypadku, dzięki zastosowaniu siatki simplex, musimy tylko interpolować sumę 3 narożników. +W dwóch wymiarach interpolacja odbywa się podobnie do zwykłego szumu, poprzez interpolację wartości wierzchołków odcinka. Ale w tym przypadku, dzięki zastosowaniu siatki sympleksowej, musimy tylko interpolować sumę 3 wierzchołków. @@ -296,23 +294,24 @@ Jak powstaje siatka simplex? W kolejnym błyskotliwym i eleganckim posunięciu, In the following code you can uncomment line 44 to see how the grid is skewed, and then uncomment line 47 to see how a simplex grid can be constructed. Note how on line 22 we are subdividing the skewed square into two equilateral triangles just by detecting if ```x > y``` ("lower" triangle) or ```y > x``` ("upper" triangle). --> -Wtedy, jak opisuje [Stefan Gustavson w tej pracy](http://staffwww.itn.liu.se/~stegu/simplexnoise/simplexnoise.pdf): _"...patrząc na części całkowite przekształconych współrzędnych (x,y) dla punktu, który chcemy ocenić, możemy szybko określić, która komórka dwóch prostopadłościanów zawiera ten punkt. Porównując również wielkości x i y, możemy określić, czy punkt znajduje się w górnej czy dolnej prostej i przemierzyć właściwe trzy punkty narożne."_. -W poniższym kodzie możesz odkomentować linię 44, aby zobaczyć jak siatka jest przekrzywiona, a następnie odkomentować linię 47, aby zobaczyć jak można skonstruować siatkę simpleksową. Zauważ jak w linii 22 dzielimy przekrzywiony kwadrat na dwa trójkąty równoboczne tylko poprzez wykrycie czy ``x > y`` (dolny" trójkąt) lub ``y > x`` (górny" trójkąt). + + +W poniższym kodzie możesz odkomentować linię 44, aby zobaczyć jak siatka jest przekrzywiona, a następnie odkomentować linię 47, aby zobaczyć siatkę simpleksową. Zauważ jak w linii 22 dzielimy przekrzywiony kwadrat na dwa trójkąty równoboczne poprzez wykrycie czy ``x > y`` (dolny" trójkąt) lub ``y > x`` (górny" trójkąt).
-Wszystkie te ulepszenia skutkują algorytmicznym arcydziełem znanym jako **Simplex Noise**. Poniżej znajduje się implementacja GLSL tego algorytmu wykonana przez Iana McEwana i Stefana Gustavsona (i przedstawiona w [tym artykule](http://webstaff.itn.liu.se/~stegu/jgt2012/article.pdf)), która jest nadmiernie skomplikowana w celach edukacyjnych, ale z przyjemnością klikniesz na nią i przekonasz się, że jest mniej krypto niż można by się spodziewać, a kod jest krótki i szybki. +Wszystkie te ulepszenia skutkują algorytmicznym arcydziełem, jakim jest **Simplex Noise**. Poniżej znajduje się implementacja GLSL tego algorytmu wykonana przez Iana McEwana i Stefana Gustavsona (i przedstawiona w [tym artykule](http://webstaff.itn.liu.se/~stegu/jgt2012/article.pdf)), która jest nadmiernie skomplikowana w celach edukacyjnych, ale przekonasz się, że jest mniej enigmatyczna niż można by się spodziewać, a kod jest krótki i szybki. [ ![Ian McEwan of Ashima Arts - Simplex Noise](simplex-noise.png) ](../edit.php#11/2d-snoise-clear.frag) -Cóż... dość technicznych rozważań, czas na wykorzystanie tego zasobu we własny, ekspresyjny sposób: +Cóż... dość technicznych rozważań, czas na wykorzystanie tego narzędzia we własny, ekspresyjny sposób: -* Kontempluj, jak wygląda każda implementacja szumu. Wyobraź sobie je jako surowy materiał, jak marmurowy kamień dla rzeźbiarza. Co możesz powiedzieć o "uczuciu", jakie ma każda z nich? Zmruż oczy, aby uruchomić wyobraźnię, tak jak wtedy, gdy chcesz znaleźć kształty w chmurze. Co widzisz? Co ci się przypomina? W co wyobrażasz sobie, że każda realizacja hałasu mogłaby zostać wykonana? Podążając za swoimi wnętrznościami i spróbuj zrealizować to w kodzie. +* Kontempluj, jak wygląda każda implementacja szumu. Wyobraź sobie je jako surowy materiał, jak marmurowy kamień dla rzeźbiarza. Co możesz powiedzieć o "uczuciu", jakie ma każda z nich? Zmruż oczy, aby uruchomić wyobraźnię, tak jak wtedy, gdy chcesz znaleźć kształty w chmurze. Co widzisz? Co ci się przypomina? W co każda implementacja szumu mogłaby zostać przeobrażana? Podążając za swoją intuicją, spróbuj zrealizować to w kodzie. -* Zrób shader, który rzutuje iluzję przepływu. Jak lampa lawowa, krople atramentu, woda itp. +* Zrób shader, który tworzy iluzję przepływu. Jak lampa lawowa, krople atramentu, woda itp. + +
+ +* Spróbuj zmienić wartości częstotliwości i amplitudy, aby zrozumieć, jak się zachowują. +* Używając funkcji kształtujących, spróbuj zmienić amplitudę w czasie. +* Używając funkcji kształtujących, spróbuj zmienić częstotliwość w czasie. + + + +Wykonując dwa ostatnie ćwiczenia udało Ci się "zmodulować" sinusoidę i właśnie stworzyłeś fale AM (modulowaną amplitudą) i FM (modulowaną częstotliwością). Gratulacje!!! + +Inną ciekawą właściwością fal jest ich zdolność do sumowania się, co formalnie nazywa się superpozycją. Skomentuj/nieskomentuj i podrasuj kolejne linie. Zwróć uwagę, jak zmienia się ogólny wygląd, gdy dodajemy do siebie fale o różnych amplitudach i częstotliwościach. + + + +
+ +* Eksperymentuj, zmieniając częstotliwość i amplitudę dla dodatkowych fal. +* Czy jest możliwe, aby dwie fale wzajemnie się zniosły? Jak to będzie wyglądało? +* Czy można dodać fale w taki sposób, że będą się one wzajemnie wzmacniać? + +W muzyce każda nuta jest związana z określoną częstotliwością. Częstotliwości tych nut układają się we wzór, który nazywamy skalą, gdzie podwojenie lub zmniejszenie częstotliwości o połowę odpowiada skokowi o jedną oktawę. + + + +Teraz użyjmy szumu Perlina zamiast sinusoidy! Szum Perlina w swojej podstawowej formie ma taki sam ogólny wygląd i odczucia jak sinusoida. Jego amplituda i częstotliwość różnią się nieco, ale amplituda pozostaje w miarę stała, a częstotliwość jest ograniczona do dość wąskiego zakresu wokół częstotliwości środkowej. Nie jest to jednak tak regularne jak sinusoida i łatwiej jest stworzyć pozory losowości poprzez zsumowanie kilku przeskalowanych wersji szumu. Można sprawić, że suma fal sinusoidalnych również będzie wyglądać na przypadkową, ale potrzeba wielu różnych fal, aby ukryć ich okresową, regularną naturę. + +Poprzez dodanie różnych iteracji szumu (*oktaw*), gdzie kolejno zwiększamy częstotliwości w regularnych krokach (*lacunarity*) i zmniejszamy amplitudę (*gain*) **szumu** możemy uzyskać drobniejszą ziarnistość szumu i uzyskać więcej szczegółów. Technika ta nazywana jest "fraktalnym ruchem Browna" (*fBM*), lub po prostu "fraktalnym szumem", i w najprostszej formie może być stworzona przez następujący kod: + + + +
+ +* Stopniowo zmieniaj liczbę oktaw do iteracji z 1 do 2, 4, 8 i 10. Zobacz, co się stanie. +* Gdy masz więcej niż 4 oktawy, spróbuj zmienić wartość lacunarity. +* Również przy >4 oktawach zmień wartość wzmocnienia i zobacz, co się stanie. + + + +Zauważ, że z każdą dodatkową oktawą krzywa wydaje się być bardziej szczegółowa. Zauważ też, że w miarę dodawania kolejnych oktaw następuje samopodobieństwo. Jeśli powiększysz krzywą, mniejsza część wygląda mniej więcej tak samo jak całość, a każda sekcja wygląda mniej więcej tak samo jak każda inna. Jest to ważna właściwość fraktali matematycznych, a my symulujemy tę właściwość w naszej pętli. Nie tworzymy *prawdziwego* fraktala, ponieważ zatrzymujemy sumowanie po kilku iteracjach, ale teoretycznie rzecz biorąc, uzyskalibyśmy prawdziwy fraktal matematyczny, gdybyśmy pozwolili pętli trwać w nieskończoność i dodawali nieskończoną liczbę składowych szumu. W grafice komputerowej zawsze mamy limit najmniejszych szczegółów, które możemy rozwiązać, na przykład gdy obiekty stają się mniejsze niż piksel, więc nie ma potrzeby wykonywania nieskończonych sum, aby stworzyć wygląd fraktala. Czasami może być potrzebna duża ilość określeń, ale nigdy nieskończona liczba. + + + +Poniższy kod jest przykładem tego, jak fBm może być zaimplementowany w dwóch wymiarach, aby stworzyć wzór wyglądający jak fraktal: + + + +
+ +* Zmniejsz liczbę oktaw poprzez zmianę wartości na linii 37 +* Zmodyfikuj lakoniczność fBm na linii 47 +* Eksploruj poprzez zmianę wzmocnienia na linii 48 + + + +Ta technika jest powszechnie używana do konstruowania proceduralnych krajobrazów. Samopodobieństwo fBm jest idealne dla gór, ponieważ procesy erozji, które tworzą góry, działają w sposób, który daje ten rodzaj samopodobieństwa w dużym zakresie skali. Jeśli jesteś zainteresowany tym zastosowaniem, powinieneś koniecznie przeczytać [ten świetny artykuł Inigo Quilesa o zaawansowanym szumie](http://www.iquilezles.org/www/articles/morenoise/morenoise.htm). + + + +![Blackout - Dan Holdsworth (2010)](holdsworth.jpg) + +Używając mniej więcej tej samej techniki, możliwe jest również uzyskanie innych efektów, takich jak to, co jest znane jako **turbulencja**. Jest to w zasadzie fBm, ale skonstruowane z wartości bezwzględnej podpisanego szumu, aby stworzyć ostre doliny w funkcji. + + + +```glsl +for (int i = 0; i < OCTAVES; i++) { + value += amplitude * abs(snoise(st)); + st *= 2.; + amplitude *= .5; +} +``` + + + +Innym członkiem tej rodziny algorytmów jest **ridge**, w którym ostre doliny są odwrócone do góry nogami, tworząc zamiast nich ostre grzbiety: + + + +```glsl + n = abs(n); // create creases + n = offset - n; // invert so creases are at top + n = n * n; // sharpen creases +``` + + + +Innym wariantem, który może tworzyć użyteczne wariacje, jest mnożenie składowych szumu razem zamiast ich dodawania. Interesujące jest również skalowanie kolejnych funkcji szumu za pomocą czegoś, co zależy od poprzednich terminów w pętli. Kiedy robimy takie rzeczy, odchodzimy od ścisłej definicji fraktala i wchodzimy w stosunkowo nieznaną dziedzinę "multifraktali". Multifraktale nie są tak ściśle zdefiniowane matematycznie, ale to nie czyni ich mniej użytecznymi dla grafiki. W rzeczywistości symulacje multifraktalne są bardzo powszechne we współczesnym komercyjnym oprogramowaniu do generowania terenu. Aby przeczytać więcej, możesz przeczytać rozdział 16 książki "Texturing and Modeling: a Procedural Approach" (3rd edition), autorstwa Kentona Musgrave. Niestety, książka ta jest już od kilku lat niedostępna w druku, ale wciąż można ją znaleźć w bibliotekach i na rynku wtórnym. (Istnieje wersja PDF pierwszego wydania dostępna do kupienia online, ale nie kupuj tego - to strata pieniędzy. Jest z 1994 roku i nie zawiera żadnych rzeczy związanych z modelowaniem terenu z 3 edycji). + + + +### Domain Warping + +[Inigo Quiles napisał ten inny fascynujący artykuł](http://www.iquilezles.org/www/articles/warp/warp.htm) o tym jak można użyć fBm do wypaczenia przestrzeni fBm. Zdumiewające, prawda? To jak sen wewnątrz snu o Incepcji. + + + +![ f(p) = fbm( p + fbm( p + fbm( p ) ) ) - Inigo Quiles (2002)](quiles.jpg) + +Mniej ekstremalnym przykładem tej techniki jest następujący kod, w którym owijka jest używana do wytworzenia tej tekstury przypominającej chmury. Zauważ, jak właściwość samopodobieństwa jest nadal obecna w wyniku. + + + +
+ +Wypaczanie współrzędnych tekstury za pomocą szumu w ten sposób może być bardzo użyteczne, daje dużo zabawy i jest diabelnie trudne do opanowania. Jest to potężne narzędzie, ale potrzeba sporo doświadczenia, aby dobrze je wykorzystać. Przydatnym narzędziem do tego jest przemieszczanie współrzędnych za pomocą pochodnej (gradientu) szumu. [Na tym pomyśle opiera się słynny artykuł Kena Perlina i Fabrice'a Neyreta o nazwie "szum przepływu"](http://evasion.imag.fr/Publications/2001/PN01/). Niektóre nowoczesne implementacje szumu Perlina zawierają wariant, który oblicza zarówno funkcję, jak i jej analityczny gradient. Jeśli "prawdziwy" gradient nie jest dostępny dla funkcji proceduralnej, zawsze możesz obliczyć różnice skończone, aby ją przybliżyć, chociaż jest to mniej dokładne i wymaga więcej pracy. + + From 4878cbb9e9b79325971a70886dd282a56e71d036 Mon Sep 17 00:00:00 2001 From: Wojtek Date: Tue, 14 Feb 2023 13:47:18 +0100 Subject: [PATCH 16/23] 12 --- 12/README-pl.md | 99 +++++++++++++++++++++++++++++++------------------ 1 file changed, 63 insertions(+), 36 deletions(-) diff --git a/12/README-pl.md b/12/README-pl.md index 436ac5c..627720e 100644 --- a/12/README-pl.md +++ b/12/README-pl.md @@ -1,10 +1,10 @@ ![](dragonfly.jpg) -## Cellular Noise +## Cellular Noise (pol. "szum komórkowy") -W 1996 roku, szesnaście lat po oryginalnym Noise Perlina i pięć lat przed jego Simplex Noise, [Steven Worley napisał pracę zatytułowaną "A Cellular Texture Basis Function"](http://www.rhythmiccanvas.com/research/papers/worley.pdf). Opisuje w niej technikę teksturowania proceduralnego, która jest obecnie szeroko stosowana przez społeczność grafików. +W 1996 roku, szesnaście lat po oryginalnym algorytmie szumu Perlina i pięć lat przed jego Simplex Noise, [Steven Worley napisał pracę zatytułowaną "A Cellular Texture Basis Function"](http://www.rhythmiccanvas.com/research/papers/worley.pdf). Opisuje w niej technikę teksturowania proceduralnego, która jest obecnie szeroko stosowana przez grafików. -Aby zrozumieć jej zasady, musimy zacząć myśleć w kategoriach **iteracji**. Zapewne wiesz, co to oznacza: tak, zacznij używać pętli ``for``. Jest tylko jeden haczyk z pętlami ``for`` w GLSL: liczba, którą sprawdzamy musi być stałą (``const``). Tak więc nie ma dynamicznych pętli - liczba iteracji musi być stała. +Aby zrozumieć jej zasady, musimy zacząć myśleć w kategoriach **iteracji**. Zapewne wiesz, co to oznacza: używanie pętli ``for``. Jest tylko jeden haczyk z pętlami ``for`` w GLSL: warunek, który sprawdzamy musi być stałą (``const``). Tak więc nie ma dynamicznych pętli - liczba iteracji musi być stała. Przyjrzyjmy się przykładowi. @@ -14,14 +14,14 @@ To understand the principles behind it we need to start thinking in terms of **i Let's take a look at an example. --> -### Points for a distance field +### Punkty w polu odległości -Hałas komórkowy opiera się na polach odległości, czyli odległości do najbliższego ze zbioru punktów charakterystycznych. Załóżmy, że chcemy stworzyć pole odległości składające się z 4 punktów. Co musimy zrobić? Cóż, **dla każdego piksela chcemy obliczyć odległość do najbliższego punktu**. Oznacza to, że musimy iterować po wszystkich punktach, obliczać ich odległości do bieżącego piksela i przechowywać wartość dla tego, który jest najbliższy. +Cellular Noise opiera się na polach odległości, a dokładniej odległości do najbliższego ze zbioru punktów. Załóżmy, że chcemy stworzyć pole odległości składające się z 4 punktów. Co musimy zrobić? Cóż, **dla każdego piksela chcemy obliczyć odległość do najbliższego punktu**. Oznacza to, że musimy iterować po wszystkich punktach, obliczać ich odległości do bieżącego piksela i przechować odległość do tego najbliższego. ```glsl - float min_dist = 100.; // A variable to store the closest distance to a point + float min_dist = 100.; // Zmienna przechowująca odległość do najbliższego punktu min_dist = min(min_dist, distance(st, point_a)); min_dist = min(min_dist, distance(st, point_b)); @@ -29,6 +29,15 @@ Hałas komórkowy opiera się na polach odległości, czyli odległości do najb min_dist = min(min_dist, distance(st, point_d)); ``` + + ![](cell-00.png) Nie jest to zbyt eleganckie, ale załatwia sprawę. Teraz zaimplementujmy go ponownie, używając tablicy i pętli ``for``. @@ -43,13 +52,13 @@ Nie jest to zbyt eleganckie, ale załatwia sprawę. Teraz zaimplementujmy go pon } ``` -Zauważ, jak używamy pętli ``for`` do iteracji przez tablicę punktów i śledzenia minimalnej odległości za pomocą funkcji [``min()``](../glossary/?search=min). Oto krótka działająca implementacja tego pomysłu: +Zauważ, jak używamy pętli ``for`` do iteracji po tablicy punktów i funkcji [``min()``](../glossary/?search=min) do śledzenia odległości do najbliższego punktu. Oto krótka działająca implementacja tego pomysłu:
-W powyższym kodzie jeden z punktów jest przypisany do pozycji myszy. Pobaw się nim, abyś mógł intuicyjnie zorientować się, jak zachowuje się ten kod. Następnie spróbuj tego: +W powyższym kodzie jeden z punktów jest przypisany do pozycji myszy. Pobaw się nim, abyś mógł zrozumieć intuicję stojącą za tym kodem. Następnie spróbuj ćwiczeń: - Jak można animować pozostałe punkty? - Po przeczytaniu [rozdziału o kształtach](../07/), wyobraź sobie ciekawe sposoby wykorzystania tego pola odległości! @@ -61,28 +70,28 @@ W powyższym kodzie jeden z punktów jest przypisany do pozycji myszy. Pobaw si - After reading [the chapter about shapes](../07/), imagine interesting ways to use this distance field! - What if you want to add more points to this distance field? What if we want to dynamically add/subtract points? --> -### Tiling and iteration +### Kafelkowanie i iteracja -Zapewne zauważyłeś, że pętle ``for`` i *arrays* nie są zbyt dobrymi przyjaciółmi GLSL. Jak już wspomnieliśmy, pętle nie akceptują dynamicznych ograniczeń na ich warunek wyjścia. Ponadto, iteracja przez wiele instancji znacznie zmniejsza wydajność twojego shadera. Oznacza to, że nie możemy użyć tego bezpośredniego podejścia dla dużych ilości punktów. Musimy znaleźć inną strategię, taką, która wykorzystuje architekturę przetwarzania równoległego GPU. +Zapewne zauważyłeś, że pętle ``for`` i tablice nie są zbyt dobrymi przyjaciółmi GLSL. Jak już wspomnieliśmy, pętle nie akceptują dynamicznych warunków wyjścia. Ponadto, iteracja przez wiele instancji znacznie zmniejsza wydajność twojego shadera. Oznacza to, że nie możemy użyć tego prostego, brute-force'owego podejścia dla dużych ilości punktów. Musimy znaleźć inną strategię, taką, która wykorzystuje architekturę przetwarzania równoległego GPU. ![](cell-01.png) -Jednym ze sposobów podejścia do tego problemu jest podzielenie przestrzeni na płytki. Nie każdy piksel musi sprawdzać odległość do każdego punktu, prawda? Biorąc pod uwagę fakt, że każdy piksel działa w swoim własnym wątku, możemy podzielić przestrzeń na komórki, z których każda ma jeden unikalny punkt do oglądania. Ponadto, aby uniknąć aberracji na krawędziach między komórkami musimy sprawdzić odległości do punktów na sąsiednich komórkach. To jest główna idea brillant [Steven Worley's paper](http://www.rhythmiccanvas.com/research/papers/worley.pdf). Na koniec każdy piksel musi sprawdzić tylko dziewięć pozycji: punkt własnej komórki i punkty w 8 komórkach wokół niego. Przestrzeń na komórki dzielimy już w rozdziałach o: [wzorach](../09/), [losowości](../10/) i [szumie](../11/), więc mam nadzieję, że jesteś już zaznajomiony z tą techniką. +Jednym ze sposobów podejścia do tego problemu jest podzielenie przestrzeni na rozłączne obszary/komórki. Nie każdy piksel musi sprawdzać odległość do każdego punktu, prawda? Biorąc pod uwagę fakt, że każdy piksel działa w swoim własnym wątku, możemy podzielić przestrzeń na komórki, z których każda ma jeden unikalny punkt do oglądania. Ponadto, aby uniknąć aberracji na krawędziach między komórkami musimy sprawdzić odległości do punktów w sąsiednich komórkach. Jest to główna idea [artykułu Stevena Worleya](http://www.rhythmiccanvas.com/research/papers/worley.pdf). Ostatecznie każdy piksel musi sprawdzić tylko dziewięć pozycji: punkt własnej komórki i punkty w 8 komórkach wokół niego. Dzieliliśmy już przestrzeń na komórki w rozdziałach o: [wzorach kafelkowych](../09/), [losowości](../10/) i [szumie](../11/), więc mam nadzieję, że jesteś już zaznajomiony z tą techniką. ```glsl - // Scale + // skalowanie st *= 3.; - // Tile the space + // dzielenie przestrzeni na kafelki vec2 i_st = floor(st); vec2 f_st = fract(st); ``` -Jaki jest więc plan? Użyjemy współrzędnych kafla (przechowywanych we współrzędnej całkowitej, ``i_st``) do skonstruowania losowej pozycji punktu. Funkcja ``random2f``, której użyjemy, otrzymuje ``vec2`` i daje nam ``vec2`` z losową pozycją. Tak więc, dla każdego kafla będziemy mieli jeden punkt charakterystyczny w losowej pozycji w obrębie kafla. +Jaki jest więc plan? Użyjemy współrzędnych kafelka (przechowywanych w części całkowitej, ``i_st``) do skonstruowania losowej pozycji punktu. Funkcja ``random2f``, której użyjemy, przyjmuje ``vec2`` i zwraca ``vec2`` z losową pozycją (o wartościach z zakresu od 0.0 do 1.0). Tak więc, dla każdego kafla będziemy mogli otrzymać jeden punkt losowo położony wewnątrz tego kafla. @@ -90,7 +99,7 @@ Jaki jest więc plan? Użyjemy współrzędnych kafla (przechowywanych we wspó vec2 point = random2(i_st); ``` -Każdy piksel wewnątrz tego kafla (przechowywany we współrzędnej float, ``f_st``) sprawdzi swoją odległość do tego losowego punktu. +Każdy piksel wewnątrz tego kafla (przechowywany w części ułamkowej, ``f_st``) sprawdzi swoją odległość do tego nowego, losowego punktu. @@ -105,14 +114,14 @@ Wynik będzie wyglądał tak: -Nadal musimy sprawdzać odległości do punktów w okolicznych kaflach, a nie tylko do tego w bieżącym kaflu. W tym celu musimy **iterować** po sąsiednich kaflach. Nie wszystkie kafle, tylko te bezpośrednio otaczające bieżący. Czyli od ``-1`` (lewy) do ``1`` (prawy) kafla w osi ``x`` oraz od ``-1`` (dolny) do ``1`` (górny) w osi ``y``. Region 3x3 składający się z 9 płytek może być iterowany przy użyciu podwójnej pętli ``for``, jak ta: +Musimy też sprawdzić odległości do punktów w okolicznych kafelkach, a nie tylko do tego w bieżącym kafelku. W tym celu **iterujemy** po sąsiednich kafelkach. Nie po wszystkich kafelkach, tylko po tych bezpośrednio otaczających bieżącego. Czyli od ``-1`` (lewy) do ``1`` (prawy) na osi ``x`` oraz od ``-1`` (dolny) do ``1`` (górny) na osi ``y``. Region 3x3 składający się z 9 kafelków może być iterowany przy użyciu podwójnej pętli ``for``, jak poniżej: ```glsl for (int y= -1; y <= 1; y++) { for (int x= -1; x <= 1; x++) { - // Neighbor place in the grid + // Względne położenie sąsiadującego kafelka vec2 neighbor = vec2(float(x),float(y)); ... } @@ -121,18 +130,25 @@ for (int y= -1; y <= 1; y++) { ![](cell-02.png) -Teraz możemy obliczyć położenie punktów na każdym z sąsiadów w naszej podwójnej pętli ``for``, dodając przesunięcie sąsiedniego kafla do bieżącej współrzędnej kafla. +Teraz możemy obliczyć położenie punktów w każdym z sąsiadujących kafelków z pomocą podwójnej pętli ``for``, dodając przesunięcie sąsiedniego kafelka (``neighbor``) do współrzędnej bieżącego kafelka (``i_st``). ```glsl ... - // Random position from current + neighbor place in the grid + // Losowe położenie punktu wewnątrz sąsiedniego kafelka vec2 point = random2(i_st + neighbor); ... ``` -Reszta polega na obliczeniu odległości do tego punktu i zapisaniu najbliższego w zmiennej o nazwie ``m_dist`` (dla minimalnej odległości). + + +Reszta polega na obliczeniu odległości do każdego z sąsiednich punktów i zapisaniu najmniejszej odległości w zmiennej o nazwie ``m_dist`` (z ang. "minimal distance"). @@ -140,31 +156,42 @@ Reszta polega na obliczeniu odległości do tego punktu i zapisaniu najbliższeg ... vec2 diff = neighbor + point - f_st; + // Odległość do punktu + float dist = length(diff); + + // Zachowaj mniejszą odległość + m_dist = min(m_dist, dist); + ... +``` + + -Powyższy kod jest inspirowany przez [ten artykuł Inigo's Quilez](http://www.iquilezles.org/www/articles/smoothvoronoi/smoothvoronoi.htm), gdzie powiedział: +Powyższy kod jest inspirowany [artykułem Inigo Quileza](http://www.iquilezles.org/www/articles/smoothvoronoi/smoothvoronoi.htm), w którym zauważa, jak problemy z precyzją bitową mogą być uniknięte poprzez przejście do stosowanej już przez nas przestrzeni kafelkowej (w przeciwieństwie do robienia obliczeń w domyślnych współrzędnych, niepodzielonych na części całkowite i ułamkowe): -*"... może warto zauważyć, że w tym kodzie powyżej jest ładna sztuczka. Większość implementacji cierpi z powodu problemów z precyzją, ponieważ generują swoje losowe punkty w przestrzeni "domeny" (jak przestrzeń "świata" lub "obiektu"), która może być dowolnie daleko od pochodzenia. Można rozwiązać ten problem przenosząc cały kod do typów danych o wyższej precyzji, lub będąc nieco sprytnym. Moja implementacja nie generuje punktów w przestrzeni "domeny", ale w przestrzeni "komórki": po wyodrębnieniu części całkowitych i ułamkowych punktu cieniowania, a zatem zidentyfikowaniu komórki, w której pracujemy, wszystko, co nas obchodzi, to to, co dzieje się wokół tej komórki, co oznacza, że możemy porzucić wszystkie całkowite części naszych współrzędnych, oszczędzając wiele bitów precyzji. W rzeczywistości, w zwykłej implementacji voronoi, całkowite części współrzędnych punktów po prostu znoszą się, gdy losowe punkty charakterystyczne na komórkę są odejmowane od punktu cieniowania. W powyższej implementacji nie pozwalamy nawet na to anulowanie, ponieważ przenosimy wszystkie obliczenia do przestrzeni "komórek". Ta sztuczka pozwala także na obsługę przypadku, gdy chcemy voronoi-shade'ować całą planetę - można po prostu zamienić dane wejściowe na podwójną precyzję, wykonać obliczenia floor() i fract(), a z resztą obliczeń przejść na zmiennoprzecinkowe bez ponoszenia kosztów zmiany całej implementacji na podwójną precyzję. Oczywiście, ta sama sztuczka dotyczy wzorców Perlin Noise (ale nigdy nie widziałem tego zaimplementowanego ani udokumentowanego gdziekolwiek). "* -Rekapitulacja: dzielimy przestrzeń na kafelki; każdy piksel obliczy odległość do punktu w swoim własnym kafelku i otaczających go 8 kafelków; przechowuj najbliższą odległość. Wynikiem jest pole odległości, które wygląda jak w poniższym przykładzie: +Podsumowując: dzielimy przestrzeń na kafelki; każdy piksel liczy odległość do punktu w swoim własnym kafelku i odległość do punktów z otaczających go 8 kafelków; przechowuje najbliższą odległość. Wynikiem jest pole odległości, które wygląda jak w poniższym przykładzie:
-Eksploruj to dalej przez: +Eksploruj tę ideę dalej: -- Skalowanie przestrzeni o różne wartości. +- Przeskaluj przestrzeń o różne wartości. - Czy możesz wymyślić inne sposoby animacji punktów? - Co jeśli chcemy obliczyć dodatkowy punkt z pozycji myszy? - Jakie inne sposoby konstruowania tego pola odległości możesz sobie wyobrazić, poza ``m_dist = min(m_dist, dist);``? @@ -178,15 +205,15 @@ Eksploruj to dalej przez: - What other ways of constructing this distance field can you imagine, besides ```m_dist = min(m_dist, dist);```? - What interesting patterns can you make with this distance field? --> -Algorytm ten można również interpretować z perspektywy punktów, a nie pikseli. W takim przypadku można go opisać jako: każdy punkt rośnie, dopóki nie znajdzie rosnącego obszaru z innego punktu. Odzwierciedla to niektóre z zasad wzrostu w naturze. Żywe formy są kształtowane przez to napięcie pomiędzy wewnętrzną siłą do rozszerzania się i wzrostu, a ograniczeniami przez siły zewnętrzne. Klasyczny algorytm symulujący to zachowanie nosi nazwę [Georgy Voronoi](https://en.wikipedia.org/wiki/Georgy_Voronoy). +Algorytm ten można również interpretować z perspektywy punktów, a nie bieżących pikseli. W takim przypadku można go opisać jako: każdy punkt rośnie, dopóki nie znajdzie rosnącego obszaru innego punktu. Odzwierciedla to niektóre z zasad wzrostu w naturze. Żywe formy są kształtowane są przez napięcie między wewnętrzną siłą do rozszerzania się i wzrostu oraz zewnętrznymi siłami ograniczającymi. Klasyczny algorytm symulujący to zachowanie nazwany został za [Georgy Voronoi](https://en.wikipedia.org/wiki/Georgy_Voronoy). ![](monokot_root.jpg) -### Voronoi Algorithm +### Algorytm Voronoi -Konstruowanie diagramów Voronoi z szumu komórkowego jest mniej trudne niż mogłoby się wydawać. Musimy tylko *zachować* pewną dodatkową informację o dokładnym punkcie, który jest najbliżej piksela. Do tego celu użyjemy ``vec2`` o nazwie ``m_point``. Przechowując kierunek wektora do środka najbliższego punktu, zamiast tylko odległości, będziemy "przechowywać" "unikalny" identyfikator tego punktu. +Konstruowanie diagramów Voronoi z szumu komórkowego jest mniej trudne niż mogłoby się wydawać. Musimy tylko *zachować* pewną dodatkową informację o punkcie, który jest najbliżej bieżącego piksela. Do tego celu użyjemy ``vec2`` o nazwie ``m_point`` (z ang. "minimal point"). Przechowując wektor od bieżącego piksela do najbliższego punktu, zamiast tylko odległości, będziemy "przechowywać" "unikalny" identyfikator tego punktu. @@ -199,15 +226,15 @@ Konstruowanie diagramów Voronoi z szumu komórkowego jest mniej trudne niż mog ... ``` -Zauważ, że w poniższym kodzie nie używamy już ``min`` do obliczania najbliższej odległości, ale zwykłej deklaracji ``if``. Dlaczego? Ponieważ tak naprawdę chcemy zrobić coś więcej za każdym razem, gdy pojawi się nowy bliższy punkt, a mianowicie zapisać jego pozycję (linie 32 do 37). +Zauważ, że w poniższym kodzie nie używamy już ``min`` do obliczania najbliższej odległości, ale zwykłegpo warunku ``if``. Dlaczego? Ponieważ chcemy zrobić coś więcej za każdym razem, gdy pojawi się nowy bliższy punkt, a mianowicie zapisać jego pozycję (linie 32 do 37).
-Zauważ, jak kolor komórki ruchomej (związanej z pozycją myszy) zmienia kolor w zależności od jej położenia. To dlatego, że kolor jest przypisywany przy użyciu wartości (pozycji) najbliższego punktu. +Zauważ, jak kolor ruchomej komórki (związanej z pozycją myszy) zmienia kolor w zależności od jej położenia. To dlatego, że kolor jest przypisywany przy użyciu wartości (pozycji) najbliższego punktu. -Tak jak zrobiliśmy to wcześniej, teraz nadszedł czas, aby to przeskalować, przechodząc na podejście [Steven Worley's paper's approach](http://www.rhythmiccanvas.com/research/papers/worley.pdf). Spróbuj zaimplementować to samodzielnie. Możesz skorzystać z pomocy poniższego przykładu, klikając na niego. Zauważ, że oryginalne podejście Stevena Worleya używa zmiennej liczby punktów cech dla każdego kafla, więcej niż jeden w większości kafli. W jego implementacji programowej w C, jest to używane do przyspieszenia pętli poprzez wykonanie wczesnych wyjść. Pętle GLSL nie pozwalają na zmienną liczbę iteracji, więc prawdopodobnie chcesz trzymać się jednego punktu charakterystycznego na kafel. +Podnieśmy poprzeczkę, przechodząc na podejście z [artykułu Stevena Worleya](http://www.rhythmiccanvas.com/research/papers/worley.pdf). Spróbuj zaimplementować to samodzielnie. Możesz skorzystać z pomocy poniższego przykładu, klikając na niego. Zauważ, że oryginalne podejście Stevena Worleya używa zmiennej liczby punktów dla każdego kafla, więcej niż jeden w większości kafli. W jego nie-shaderowej implementacji w C, jest to używane do przyspieszenia pętli poprzez wczesne wychodzenie. Pętle GLSL nie pozwalają na zmienną liczbę iteracji, więc prawdopodobnie chcesz trzymać się jednego punktu na kafelek. @@ -241,9 +268,9 @@ Później w 2012 roku [Inigo Quilez napisał artykuł o tym, jak zrobić precyzy -Eksperymenty Inigo z Voronoi nie skończyły się na tym. W 2014 roku napisał ten ładny artykuł o tym, co nazywa [voro-noise](http://www.iquilezles.org/www/articles/voronoise/voronoise.htm), funkcją, która pozwala na stopniowe mieszanie się między zwykłym szumem a voronoi. Jego słowami: +Eksperymenty Inigo z Voronoi nie skończyły się na tym. W 2014 roku napisał artykuł o tym, co nazywa [voro-noise](http://www.iquilezles.org/www/articles/voronoise/voronoise.htm). Jest to funkcja, która pozwala na stopniowe mieszanie między zwykłym szumem a Voronoi. Jego słowami: -*"Pomimo tego podobieństwa, faktem jest, że sposób użycia siatki w obu wzorach jest inny. Szum interpoluje/uśrednia wartości losowe (jak w szumie wartościowym) lub gradienty (jak w szumie gradientowym), podczas gdy Voronoi oblicza odległość do najbliższego punktu charakterystycznego. Teraz, interpolacja gładko-biliniowa i ocena minimalna to dwie bardzo różne operacje, czy... są? Czy być może można je połączyć w bardziej ogólną metrykę? Gdyby tak było, to zarówno Szum jak i Wzory Voronoi mogłyby być postrzegane jako szczególne przypadki bardziej ogólnego generatora wzorów opartego na siatce? "*. +*"Pomimo tego podobieństwa, faktem jest, że sposób użycia kafelkowania w obu metodach jest inny. Szum interpoluje/uśrednia wartości losowe (jak w Value Noise) lub gradienty (jak w Gradient Noise), podczas gdy Voronoi oblicza odległość do najbliższego punktu w kafelku. Teraz, interpolacja dwuliniowa (ang. "bilinear") i wartość minimalna to dwie bardzo różne operacje, ale czy na pewno? Czy można je połączyć w bardziej ogólną metrykę? Gdyby tak było, to zarówno szum jak i Voronoi mogłyby być postrzegane jako szczególne przypadki bardziej ogólnego generatora wzorów kafelkowych?"*. @@ -13,16 +13,16 @@ y = amplitude * sin(x * frequency); "> * Spróbuj zmienić wartości częstotliwości i amplitudy, aby zrozumieć, jak się zachowują. -* Używając funkcji kształtujących, spróbuj zmienić amplitudę w czasie. -* Używając funkcji kształtujących, spróbuj zmienić częstotliwość w czasie. +* Używając shaping functions, spróbuj zmienić amplitudę w czasie. +* Używając shaping functions, spróbuj zmienić częstotliwość w czasie. -Wykonując dwa ostatnie ćwiczenia udało Ci się "zmodulować" sinusoidę i właśnie stworzyłeś fale AM (modulowaną amplitudą) i FM (modulowaną częstotliwością). Gratulacje!!! +Wykonując dwa ostatnie ćwiczenia udało Ci się "zmodulować" sinusoidę i właśnie stworzyłeś fale AM (modulowane amplitudą, ang. "amplitude modulated") i FM (modulowane częstotliwością, ang. "frequency modulated"). Gratulacje!!! -Inną ciekawą właściwością fal jest ich zdolność do sumowania się, co formalnie nazywa się superpozycją. Skomentuj/nieskomentuj i podrasuj kolejne linie. Zwróć uwagę, jak zmienia się ogólny wygląd, gdy dodajemy do siebie fale o różnych amplitudach i częstotliwościach. +Inną ciekawą właściwością fal jest ich zdolność do sumowania się, co formalnie nazywa się superpozycją. Skomentuj/odkomentuj i zmodyfikuj poniższe linijki. Zwróć uwagę, jak zmienia się ogólny wygląd wykresu, gdy dodajemy do siebie fale o różnych amplitudach i częstotliwościach. -Teraz użyjmy szumu Perlina zamiast sinusoidy! Szum Perlina w swojej podstawowej formie ma taki sam ogólny wygląd i odczucia jak sinusoida. Jego amplituda i częstotliwość różnią się nieco, ale amplituda pozostaje w miarę stała, a częstotliwość jest ograniczona do dość wąskiego zakresu wokół częstotliwości środkowej. Nie jest to jednak tak regularne jak sinusoida i łatwiej jest stworzyć pozory losowości poprzez zsumowanie kilku przeskalowanych wersji szumu. Można sprawić, że suma fal sinusoidalnych również będzie wyglądać na przypadkową, ale potrzeba wielu różnych fal, aby ukryć ich okresową, regularną naturę. +Teraz użyjmy szumu Perlina zamiast sinusoidy! Szum Perlina w swojej podstawowej formie wygląda podobnie do sinusoidy. Jego amplituda i częstotliwość różnią się nieco, ale amplituda pozostaje w miarę stała, a częstotliwość jest ograniczona do dość wąskiego zakresu wokół częstotliwości środkowej. Szum nie jest jednak tak regularny jak sinusoida, tym bardziej, gdy zsumujemy jego kilka przeskalowanych wersji. Można sprawić, że suma fal sinusoidalnych również będzie wyglądać na przypadkową, ale potrzeba wielu różnych fal, aby ukryć ich okresową, regularną naturę. -Poprzez dodanie różnych iteracji szumu (*oktaw*), gdzie kolejno zwiększamy częstotliwości w regularnych krokach (*lacunarity*) i zmniejszamy amplitudę (*gain*) **szumu** możemy uzyskać drobniejszą ziarnistość szumu i uzyskać więcej szczegółów. Technika ta nazywana jest "fraktalnym ruchem Browna" (*fBM*), lub po prostu "fraktalnym szumem", i w najprostszej formie może być stworzona przez następujący kod: +Poprzez dodanie różnych iteracji szumu (*octaves*, pol. "oktawy"), gdzie kolejno zwiększamy częstotliwości w regularnych krokach (*lacunarity*, pol. "lakunarność") i zmniejszamy amplitudę (*gain*, pol. "wzmocnienie") make a sum of sine waves appear random as well, but it takes many different waves to hide their periodic, regular nature. - + -->
-* Stopniowo zmieniaj liczbę oktaw do iteracji z 1 do 2, 4, 8 i 10. Zobacz, co się stanie. -* Gdy masz więcej niż 4 oktawy, spróbuj zmienić wartość lacunarity. -* Również przy >4 oktawach zmień wartość wzmocnienia i zobacz, co się stanie. +* Stopniowo zmieniaj liczbę oktaw z 1 do 2, 4, 8 i 10. Zobacz, co się stanie. +* Gdy masz więcej niż 4 oktawy, spróbuj zmienić wartość `lacunarity`. +* Również przy >4 oktawach zmień wartość `gain` i zobacz, co się stanie. -Zauważ, że z każdą dodatkową oktawą krzywa wydaje się być bardziej szczegółowa. Zauważ też, że w miarę dodawania kolejnych oktaw następuje samopodobieństwo. Jeśli powiększysz krzywą, mniejsza część wygląda mniej więcej tak samo jak całość, a każda sekcja wygląda mniej więcej tak samo jak każda inna. Jest to ważna właściwość fraktali matematycznych, a my symulujemy tę właściwość w naszej pętli. Nie tworzymy *prawdziwego* fraktala, ponieważ zatrzymujemy sumowanie po kilku iteracjach, ale teoretycznie rzecz biorąc, uzyskalibyśmy prawdziwy fraktal matematyczny, gdybyśmy pozwolili pętli trwać w nieskończoność i dodawali nieskończoną liczbę składowych szumu. W grafice komputerowej zawsze mamy limit najmniejszych szczegółów, które możemy rozwiązać, na przykład gdy obiekty stają się mniejsze niż piksel, więc nie ma potrzeby wykonywania nieskończonych sum, aby stworzyć wygląd fraktala. Czasami może być potrzebna duża ilość określeń, ale nigdy nieskończona liczba. +Zauważ, że z każdą dodatkową oktawą krzywa wydaje się być bardziej szczegółowa. Zauważ też, że w miarę dodawania kolejnych oktaw występuje efekt samopodobieństwa - jeśli powiększysz krzywą, przybliżona część wygląda mniej więcej tak samo jak całość, a każda część wygląda mniej więcej tak samo jak każda inna. Jest to ważna właściwość fraktali matematycznych, a my symulujemy tę właściwość w naszej pętli. Nie tworzymy *prawdziwego* fraktala, ponieważ zatrzymujemy sumowanie po kilku iteracjach, ale teoretycznie rzecz biorąc, uzyskalibyśmy prawdziwy fraktal matematyczny, gdybyśmy pozwolili pętli trwać w nieskończoność i dodawali nieskończoną liczbę składowych szumu. W grafice komputerowej zawsze mamy limit najmniejszych szczegółów, które możemy wyrenderować, gdyż obiekty stają się mniejsze niż piksel, więc nie ma potrzeby wykonywania nieskończonych sum, aby stworzyć wygląd fraktala. Czasami może być potrzebna duża ilość iteracji, ale nigdy nieskończona liczba. @@ -94,21 +92,21 @@ Poniższy kod jest przykładem tego, jak fBm może być zaimplementowany w dwóc
-* Zmniejsz liczbę oktaw poprzez zmianę wartości na linii 37 -* Zmodyfikuj lakoniczność fBm na linii 47 -* Eksploruj poprzez zmianę wzmocnienia na linii 48 +* Zmniejsz liczbę oktaw poprzez zmianę wartości w linii 37 +* Zmodyfikuj `lacunarity` fBm w linii 47 +* Eksploruj zmianę `gain` na linii 48 -Ta technika jest powszechnie używana do konstruowania proceduralnych krajobrazów. Samopodobieństwo fBm jest idealne dla gór, ponieważ procesy erozji, które tworzą góry, działają w sposób, który daje ten rodzaj samopodobieństwa w dużym zakresie skali. Jeśli jesteś zainteresowany tym zastosowaniem, powinieneś koniecznie przeczytać [ten świetny artykuł Inigo Quilesa o zaawansowanym szumie](http://www.iquilezles.org/www/articles/morenoise/morenoise.htm). +Ta technika jest powszechnie używana do konstruowania proceduralnych krajobrazów. Samopodobieństwo fBm jest idealne dla gór, ponieważ procesy erozji, które tworzą góry, działają w sposób, który daje ten rodzaj samopodobieństwa w dużym zakresie skal. Jeśli jesteś zainteresowany tym zastosowaniem, powinieneś koniecznie przeczytać [ten świetny artykuł Inigo Quilesa o zaawansowanym szumie](http://www.iquilezles.org/www/articles/morenoise/morenoise.htm). ![Blackout - Dan Holdsworth (2010)](holdsworth.jpg) -Używając mniej więcej tej samej techniki, możliwe jest również uzyskanie innych efektów, takich jak to, co jest znane jako **turbulencja**. Jest to w zasadzie fBm, ale skonstruowane z wartości bezwzględnej podpisanego szumu, aby stworzyć ostre doliny w funkcji. +Używając mniej więcej tej samej techniki, możliwe jest również uzyskanie innych efektów, takich jak **turbulencja**. Jest to w zasadzie fBm, ale skonstruowane z wartości bezwzględnej szumu (wariantu zwracającego również ujemne wartości), aby stworzyć ostre doliny w funkcji. @@ -122,36 +120,36 @@ for (int i = 0; i < OCTAVES; i++) { -Innym członkiem tej rodziny algorytmów jest **ridge**, w którym ostre doliny są odwrócone do góry nogami, tworząc zamiast nich ostre grzbiety: +Innym członkiem tej rodziny algorytmów jest **ridge** (pol. "grzbiet"), w którym ostre doliny są odwrócone do góry nogami, tworząc zamiast nich ostre grzbiety: ```glsl - n = abs(n); // create creases - n = offset - n; // invert so creases are at top - n = n * n; // sharpen creases + n = abs(n); // Stwórz doliny + n = offset - n; // Odwróć doliny, aby powstały grzbiety + n = n * n; // Zaostrz grzbiety ``` -Innym wariantem, który może tworzyć użyteczne wariacje, jest mnożenie składowych szumu razem zamiast ich dodawania. Interesujące jest również skalowanie kolejnych funkcji szumu za pomocą czegoś, co zależy od poprzednich terminów w pętli. Kiedy robimy takie rzeczy, odchodzimy od ścisłej definicji fraktala i wchodzimy w stosunkowo nieznaną dziedzinę "multifraktali". Multifraktale nie są tak ściśle zdefiniowane matematycznie, ale to nie czyni ich mniej użytecznymi dla grafiki. W rzeczywistości symulacje multifraktalne są bardzo powszechne we współczesnym komercyjnym oprogramowaniu do generowania terenu. Aby przeczytać więcej, możesz przeczytać rozdział 16 książki "Texturing and Modeling: a Procedural Approach" (3rd edition), autorstwa Kentona Musgrave. Niestety, książka ta jest już od kilku lat niedostępna w druku, ale wciąż można ją znaleźć w bibliotekach i na rynku wtórnym. (Istnieje wersja PDF pierwszego wydania dostępna do kupienia online, ale nie kupuj tego - to strata pieniędzy. Jest z 1994 roku i nie zawiera żadnych rzeczy związanych z modelowaniem terenu z 3 edycji). +Innym użytecznym wariantem jest mnożenie składowych szumu zamiast ich dodawania. Interesujące jest również skalowanie kolejnych funkcji szumu za pomocą czegoś, co zależy od poprzednich terminów w pętli. Kiedy robimy takie rzeczy, odchodzimy od ścisłej definicji fraktala i wchodzimy w stosunkowo nieznaną dziedzinę "multifraktali". Multifraktale nie są tak ściśle zdefiniowane matematycznie, ale to nie czyni ich mniej użytecznymi dla grafiki. W rzeczywistości symulacje multifraktalne są bardzo powszechne we współczesnym komercyjnym oprogramowaniu do generowania terenu. Aby przeczytać więcej, możesz przeczytać rozdział 16 książki "Texturing and Modeling: a Procedural Approach" (3. edycja), autorstwa Kentona Musgrave. Niestety, książka ta jest już od kilku lat niedostępna w druku, ale wciąż można ją znaleźć w bibliotekach i na rynku wtórnym. (Istnieje wersja PDF pierwszego wydania dostępna do kupienia online, ale nie kupuj tego - to strata pieniędzy. Jest z 1994 roku i nie zawiera żadnych rzeczy związanych z modelowaniem terenu z 3. edycji). -### Domain Warping +### Warping (pol. "zakrzywianie") -[Inigo Quiles napisał ten inny fascynujący artykuł](http://www.iquilezles.org/www/articles/warp/warp.htm) o tym jak można użyć fBm do wypaczenia przestrzeni fBm. Zdumiewające, prawda? To jak sen wewnątrz snu o Incepcji. +[Inigo Quiles napisał też inny fascynujący artykuł](http://www.iquilezles.org/www/articles/warp/warp.htm) o tym jak można użyć fBm do zakrzywienia przestrzeni fBm. Zdumiewające, prawda? To jak sen wewnątrz snu o Incepcji. ![ f(p) = fbm( p + fbm( p + fbm( p ) ) ) - Inigo Quiles (2002)](quiles.jpg) -Mniej ekstremalnym przykładem tej techniki jest następujący kod, w którym owijka jest używana do wytworzenia tej tekstury przypominającej chmury. Zauważ, jak właściwość samopodobieństwa jest nadal obecna w wyniku. +Mniej ekstremalnym przykładem tej techniki jest następujący kod, w którym zakrzywienie jest używane do wytworzenia tekstury przypominającej chmury. Zauważ, że właściwość samopodobieństwa jest nadal obecna.
-Wypaczanie współrzędnych tekstury za pomocą szumu w ten sposób może być bardzo użyteczne, daje dużo zabawy i jest diabelnie trudne do opanowania. Jest to potężne narzędzie, ale potrzeba sporo doświadczenia, aby dobrze je wykorzystać. Przydatnym narzędziem do tego jest przemieszczanie współrzędnych za pomocą pochodnej (gradientu) szumu. [Na tym pomyśle opiera się słynny artykuł Kena Perlina i Fabrice'a Neyreta o nazwie "szum przepływu"](http://evasion.imag.fr/Publications/2001/PN01/). Niektóre nowoczesne implementacje szumu Perlina zawierają wariant, który oblicza zarówno funkcję, jak i jej analityczny gradient. Jeśli "prawdziwy" gradient nie jest dostępny dla funkcji proceduralnej, zawsze możesz obliczyć różnice skończone, aby ją przybliżyć, chociaż jest to mniej dokładne i wymaga więcej pracy. +Zakrzywienie współrzędnych tekstury za pomocą szumu może być bardzo użyteczne, daje dużo frajdy, ale jest diabelnie trudne do opanowania. Jest to potężne narzędzie, ale potrzeba sporo doświadczenia, aby dobrze je wykorzystać. Przydatnym narzędziem do tego jest przemieszczanie współrzędnych za pomocą pochodnej (gradientu) szumu. [Na tym pomyśle opiera się słynny artykuł Kena Perlina i Fabrice'a Neyreta o nazwie "flow noise"](http://evasion.imag.fr/Publications/2001/PN01/). Niektóre nowoczesne implementacje szumu Perlina zawierają wariant, który oblicza zarówno funkcję, jak i jej analityczny gradient. Jeśli "prawdziwy" gradient nie jest dostępny dla proceduralnej funkcji, zawsze możesz obliczyć skończone różnice, aby ją przybliżyć, chociaż jest to mniej dokładne i wymaga więcej pracy. From 2ddad652f6e50dfecc89834d23d6cdbb3f5adc04 Mon Sep 17 00:00:00 2001 From: Wojtek Date: Thu, 2 Mar 2023 11:54:41 +0100 Subject: [PATCH 18/23] appendix --- 13/README-pl.md | 2 +- README-pl.md | 2 +- appendix/00/README-pl.md | 41 ++++++++++++++ appendix/01/README-pl.md | 28 ++++++++++ appendix/02/README-pl.md | 107 ++++++++++++++++++++++++++++++++++++ appendix/03/README-pl.md | 113 +++++++++++++++++++++++++++++++++++++++ appendix/README-pl.md | 32 +++++++++++ 7 files changed, 323 insertions(+), 2 deletions(-) create mode 100644 appendix/00/README-pl.md create mode 100644 appendix/01/README-pl.md create mode 100644 appendix/02/README-pl.md create mode 100644 appendix/03/README-pl.md create mode 100644 appendix/README-pl.md diff --git a/13/README-pl.md b/13/README-pl.md index 0c1a784..1339aae 100644 --- a/13/README-pl.md +++ b/13/README-pl.md @@ -150,6 +150,6 @@ Mniej ekstremalnym przykładem tej techniki jest następujący kod, w którym za
-Zakrzywienie współrzędnych tekstury za pomocą szumu może być bardzo użyteczne, daje dużo frajdy, ale jest diabelnie trudne do opanowania. Jest to potężne narzędzie, ale potrzeba sporo doświadczenia, aby dobrze je wykorzystać. Przydatnym narzędziem do tego jest przemieszczanie współrzędnych za pomocą pochodnej (gradientu) szumu. [Na tym pomyśle opiera się słynny artykuł Kena Perlina i Fabrice'a Neyreta o nazwie "flow noise"](http://evasion.imag.fr/Publications/2001/PN01/). Niektóre nowoczesne implementacje szumu Perlina zawierają wariant, który oblicza zarówno funkcję, jak i jej analityczny gradient. Jeśli "prawdziwy" gradient nie jest dostępny dla proceduralnej funkcji, zawsze możesz obliczyć skończone różnice, aby ją przybliżyć, chociaż jest to mniej dokładne i wymaga więcej pracy. +Zakrzywianie współrzędnych tekstury za pomocą szumu może być bardzo użyteczne, daje dużo frajdy, ale jest diabelnie trudne do opanowania. Jest to potężne narzędzie, ale potrzeba sporo doświadczenia, aby dobrze je wykorzystać. Przydatnym narzędziem do tego jest przemieszczanie współrzędnych za pomocą pochodnej (gradientu) szumu. [Na tym pomyśle opiera się słynny artykuł Kena Perlina i Fabrice'a Neyreta o nazwie "flow noise"](http://evasion.imag.fr/Publications/2001/PN01/). Niektóre nowoczesne implementacje szumu Perlina zawierają wariant, który oblicza zarówno funkcję, jak i jej gradient. Jeśli gradient nie jest istnieje, zawsze możesz obliczyć skończone różnice (różnica między sąsiadującymi pikselami), aby go przybliżyć, chociaż jest to mniej dokładne i wymaga więcej pracy. diff --git a/README-pl.md b/README-pl.md index 70b23b4..6898e47 100644 --- a/README-pl.md +++ b/README-pl.md @@ -56,7 +56,7 @@ * Reflect and refract * [Dodatek:](appendix/) Inne sposoby korzystania z tej książki - * [Jak korzystać z tej książki offline?](appendix/00/) + * [Jak mogę korzystać z tej książki offline?](appendix/00/) * [Jak uruchomić przykłady na Raspberry Pi?](appendix/01/) * [Jak wydrukować tę książkę?](appendix/02/) * [Jak mogę pomóc?](appendix/03/) diff --git a/appendix/00/README-pl.md b/appendix/00/README-pl.md new file mode 100644 index 0000000..0e67325 --- /dev/null +++ b/appendix/00/README-pl.md @@ -0,0 +1,41 @@ +## Jak mogę korzystać z tej książki offline? + +Powiedzmy, że masz przed sobą długą podróż i chcesz ją wykorzystać do nauczenia się kilku shaderów. W takim przypadku możesz zrobić lokalną kopię tej książki na swoim komputerze i uruchomić lokalny serwer. + +Do tego potrzebujesz tylko PHP, Pythona 3 i Git'a. Na komputerach z systemem macOS i Raspberry Pi Python jest zainstalowany domyślnie, ale musisz jeszcze zainstalować PHP i klienta Git. W tym celu: + + + +Na **MacOSX** musisz mieć zainstalowane [homebrew](http://brew.sh/) by następnie w terminalu uruchomić: + +```bash +brew update +brew upgrade +brew install git php +``` + +Na **Raspberry Pi** potrzebujesz [Raspbian](https://www.raspberrypi.org/downloads/raspbian/), opartej na Debianie dystrybucji Linuxa, by następnie uruchomić: + +```bash +sudo apt-get update +sudo apt-get upgrade +sudo apt-get install git-core glslviewer php +``` + +Gdy masz już wszystko zainstalowane wystarczy uruchomić: + + + +```bash +cd ~ +git clone --recursive https://github.com/patriciogonzalezvivo/thebookofshaders.git +cd thebookofshaders +git submodule foreach git submodule init && git submodule update +php -S localhost:8000 +``` + +Następnie otwórz swoją przeglądarkę na [`http://localhost:8000/`](http://localhost:8000/) diff --git a/appendix/01/README-pl.md b/appendix/01/README-pl.md new file mode 100644 index 0000000..fbd7475 --- /dev/null +++ b/appendix/01/README-pl.md @@ -0,0 +1,28 @@ +## Jak uruchomić przykłady na Raspberry Pi? + +Jeszcze kilka lat temu założenie, że każdy ma komputer z procesorem graficznym było dalekie od prawdy. Teraz większość komputerów ma GPU, ale to wciąż wysoka poprzeczka. + +Dzięki [Fundacji Raspberry Pi](http://www.raspberrypi.org/) nowy typ małych i tanich komputerów nowej generacji (około 35 dolarów za sztukę) trafił do sal lekcyjnych. Co ważniejsze dla celów tej książki, [Raspberry Pi](http://www.raspberrypi.org/) jest wyposażone w przyzwoity procesor graficzny Broadcom, do którego można uzyskać dostęp bezpośrednio z konsoli. Stworzyłem [elastyczne narzędzie do kodowania GLSL na żywo o nazwie **glslViewer**](https://github.com/patriciogonzalezvivo/glslViewer), które uruchamia wszystkie przykłady zawarte w tej książce. Program ten automatycznie się odswieża, gdy użytkownik zapisze zmiany w swoim kodzie. Co to oznacza? Możesz edytować shader i za każdym razem, gdy go zapiszesz, shader zostanie ponownie skompilowany i wyrenderowany za Ciebie. + + + +Robiąc lokalną kopię repozytorium tej książki (zobacz poprzedni rozdział) i mając [zainstalowany `glslViewer`](https://github.com/patriciogonzalezvivo/glslViewer), użytkownicy mogą uruchamiać przykłady za pomocą `glslviewer`. Dodając flagę `-l` mogą oni renderować przykład w rogu ekranu, podczas gdy modyfikują go za pomocą dowolnego edytora tekstu (jak `nano`, `pico`, `vi`, `vim` lub `emacs`). Działa to również przy połączeniu przez ssh/sftp. + +Aby zainstalować i skonfigurować to wszystko na Raspberry Pi, po zainstalowaniu [Raspbian](https://www.raspberrypi.org/downloads/raspbian/) (dystrybucja Linuksa oparta na Debianie, stworzona dla Raspberry Pi) i zalogowaniu się, wpisz następujące polecenia: + + + +```bash +sudo apt-get update +sudo apt-get upgrade +sudo apt-get install git-core glslviewer +cd ~ +git clone https://github.com/patriciogonzalezvivo/thebookofshaders.git +cd thebookofshaders +``` diff --git a/appendix/02/README-pl.md b/appendix/02/README-pl.md new file mode 100644 index 0000000..6ac38a8 --- /dev/null +++ b/appendix/02/README-pl.md @@ -0,0 +1,107 @@ +## Jak wydrukować tę książkę? + +Powiedzmy, że nie chcesz nawigować ani wchodzić w interakcje z przykładami i chcesz po prostu mieć starą dobrą książkę tekstową, którą możesz czytać na plaży lub podczas dojazdu do miasta. W takim przypadku możesz wydrukować tę książkę. + + +#### Instalacja programu glslViewer + +Aby wydrukować tę książkę, musisz najpierw ją przetworzyć. W tym celu będziesz potrzebował [`glslViewer`](https://github.com/patriciogonzalezvivo/glslViewer) - konsolowego narzędzia do shaderów, które skompiluje i przekształci przykłady shaderów w obrazy. + + + +W **MacOSX** upewnij się, że masz zainstalowany [homebrew](http://brew.sh/), a następnie w terminalu wykonaj: + + + +```bash +brew install glslviewer +``` + +Na **Raspberry Pi** należy pobrać [Raspbian](https://www.raspberrypi.org/downloads/raspbian/), dystrybucję Linuksa opartą na Debianie, stworzoną dla Raspberry Pi, a następnie wykonać: + + + +```bash +sudo apt-get update +sudo apt-get upgrade +sudo apt-get install git-core glslviewer +``` + +#### Instalacja Pythona 3, silnika Latex i Pandoc + +Do parsowania Markdowna do Latexa, a następnie do pliku PDF użyjemy Xetex Latex Engine i Pandoc. + +W **MacOSX**: + +Pobierz i zainstalluj MacTeX: + + + +```bash +brew cask install mactex-no-gui +``` + +a następnie zainstalowuj [Pandoc](http://johnmacfarlane.net/pandoc/) i Python 3 przez: + + + +```bash +brew install pandoc python +``` + +Na **Raspberry Pi** (Raspbian): + +```bash +sudo apt-get install texlive-xetex pandoc python2.7 +``` + +#### Skompiluj książkę do pdf i wydrukuj ją + +Teraz, gdy masz już wszystko, czego potrzebujesz, nadszedł czas na sklonowanie [repozytorium tej książki](https://github.com/patriciogonzalezvivo/thebookofshaders) i skompilowanie książki. + +W tym celu otwórz jeszcze raz swój terminal i wpisz: + + + +```bash +cd ~ +git clone https://github.com/patriciogonzalezvivo/thebookofshaders.git +cd thebookofshaders +make clean pdf +``` + +Jeśli wszystko pójdzie dobrze, zobaczysz plik `book.pdf`, który możesz przeczytać na swoim ulubionym urządzeniu lub wydrukować. + +#### Skompiluj książkę do postaci epub, aby użyć jej w e-czytniku. + + + +```bash +cd ~ +git clone https://github.com/patriciogonzalezvivo/thebookofshaders.git +cd thebookofshaders +make clean epub +``` + +Wygenerowany `book.epub` może być użyty bezpośrednio, lub przekonwertowany, za pomomocą, na przykład, Calibre, na plik `.mobi` do użytku z Kindle. + + diff --git a/appendix/03/README-pl.md b/appendix/03/README-pl.md new file mode 100644 index 0000000..c0bb318 --- /dev/null +++ b/appendix/03/README-pl.md @@ -0,0 +1,113 @@ +## Jak mogę pomóc? + +Dziękujemy za chęć współpracy! Jest wiele sposobów pomocy: + +- Tłumaczenie treści +- Poprawianie [sekcji ```glosariusz/```](https://github.com/patriciogonzalezvivo/thebookofshaders/tree/master/glossary) +- Edytowanie zawartości +- Dzielenie się swoimi przykładami shaderów poprzez [edytor on-line](http://editor.thebookofshaders.com/) + + + +### Tłumaczenie treści + +Ta książka jest napisana w [języku Markdown](https://daringfireball.net/projects/markdown/syntax), więc bardzo łatwo jest ją edytować i pracować nad nią. + +1. Zacznij od przejścia do [repozytorium github pod adresem ``github.com/patriciogonzalezvivo/thebookofshaders``](https://github.com/patriciogonzalezvivo/thebookofshaders). Przyjrzyj się znajdującym się w nim plikom i folderom. Zauważysz, że treść znajduje się w pliku ``README.md`` oraz innych plikach z dużymi literami jak: ``TITLE.md``, ``SUMMARY.md``, itd. Zauważ również, że tłumaczenia są hostowane w plikach z nazwami kończącymi się na dwie litery reprezentujące język tłumaczenia, na przykład: ``README-jp.md``, ``README-es.md``, itd. + + + +2. Forkuj repozytorium i sklonuj je w swoim komputerze. + +3. Zduplikuj zawartość plików, które chcesz przetłumaczyć. Pamiętaj, aby do plików, nad którymi będziesz pracował, dodać dwie litery nawiązujące do języka, który tłumaczysz. + +4. Przetłumacz treść linijka po linijce (patrz **Uwagi dotyczące tłumaczenia**). + +5. Przetestuj ją (patrz **Testy**). + +6. Pushuj na własny fork githuba, aby następnie zrobić [Pull Request](https://help.github.com/articles/using-pull-requests/) + + + +#### Uwagi dotyczące tłumaczenia + +Nie wymazuj ani nie modyfikuj rzeczy w osadzonych przykładach, wyglądających tak: + + + +```html +
+``` + +lub + +```html +
+``` + +#### Testowanie + +Rozpocznij uruchamianie lokalnego serwera PHP wewnątrz lokalnego folderu repozytorium: + + + +```bash +php -S localhost:8000 +``` + +Następnie w przeglądarce wyszukaj ``localhost:8000``, przejdź do rozdziału, który tłumaczysz i dodaj ``?lan=``, a następnie dwie litery, których użyłeś do oznaczenia języka, na który tłumaczysz. + +Na przykład, jeśli tłumaczysz rozdział ``03`` na język francuski pracowałeś z plikiem ``03/README-fr.md``, to możesz go przetestować wchodząc na: ``http://localhost:8000/03/?lan=fr`` + + + +### Ulepszanie glosariusza + +Glosariusz jest w trakcie rozwoju. Chętnie wysłuchamy Twoich pomysłów, jak uczynić ją przyjaznym narzędziem dla wszystkich. Wyślij nam wiadomość na adres [@bookofshaders](https://twitter.com/bookofshaders). + +### Edycja treści + +Wszyscy jesteśmy ludźmi. Jeśli widzisz błąd, daj znać i zrób Pull Request lub otwórz Issue. Dzięki! + + + +### Dzielenie się przykładami shaderów + +Zobaczysz wiele linków do [edytora on-line](http://editor.thebookofshaders.com/) i jego osadzonych instancji. +Gdy zakodujesz coś, co sprawi, że będziesz dumny, kliknij "Export" (lub ikonę ``⇪``), a następnie skopiuj "URL to code...". Wyślij go do [@bookofshaders](https://twitter.com/bookofshaders) lub [@kyndinfo](https://twitter.com/kyndinfo). Czekamy na nie i dodamy je do [działu galeria przykładów](https://thebookofshaders.com/examples/). + + diff --git a/appendix/README-pl.md b/appendix/README-pl.md new file mode 100644 index 0000000..5f0c4e0 --- /dev/null +++ b/appendix/README-pl.md @@ -0,0 +1,32 @@ +# Dodatek + +1. [Jak mogę nawigować po tej książce w trybie off-line?](00/) + +2. [Jak uruchomić przykłady na Raspberry Pi?](01/) + +3. [Jak wydrukować tę książkę?](02/) + +4. [Jak współpracować przy tworzeniu tej książki?](03/) + +5. [Wprowadzenie dla osób pochodzących z JS](04/) autorstwa [Nicolas Barradeau](http://www.barradeau.com/) + +6. [Wprowadzenie dla wektorów](05/) autorstwa ... + +7. [Wprowadzenie do interpolacji](06) przez ... + + + From 945bc5cbd513b5754343ad860dbcea4dac14f0fc Mon Sep 17 00:00:00 2001 From: Wojtek Date: Thu, 2 Mar 2023 16:29:27 +0100 Subject: [PATCH 19/23] fixing 00 - 05 --- 00/README-pl.md | 20 ++++++------- 01/README-pl.md | 55 +++++++++++++++++------------------ 02/README-pl.md | 29 +++++++++---------- 03/README-pl.md | 12 ++++---- 04/README-pl.md | 2 +- 05/README-pl.md | 76 ++++++++++++++++++++++++++++++------------------- 6 files changed, 105 insertions(+), 89 deletions(-) diff --git a/00/README-pl.md b/00/README-pl.md index 5eaf1c8..485ba7e 100644 --- a/00/README-pl.md +++ b/00/README-pl.md @@ -2,7 +2,7 @@ -Powyższe obrazy zostały stworzone na różny sposób. Pierwszy stworzył Van Gogh, aplikując farbę warstwa po wartwie. Zajęło mu to godziny. Drugi z nich stworzono poprzez połączenie czterech macierzy zawierających piksele koloru niebieskozielonego (cyjan), magenty, żółtego i czarnego. Kluczowa różnicę stanowi fakt, że drugi obraz stworzny został natychmiast, a nie seryjnie, krok po kroku. +Powyższe obrazy zostały stworzone na różny sposób. Pierwszy stworzył Van Gogh, aplikując farbę warstwa po wartwie. Zajęło mu to godziny. Drugi z nich stworzono poprzez połączenie czterech macierzy zawierających piksele koloru niebieskozielonego (cyjan), magenty, żółtego i czarnego. Kluczowa różnicę stanowi fakt, że drugi obraz stworzny został natychmiastowo (przez komputer), a nie seryjnie, krok po kroku (przez malarza). Ta książka jest o rewolucyjnej technice obliczeniowej, tzw. *fragment shaderach* (zwanych też *pixel shaderami*), które wznoszą cyfrowo generowane obrazy na wyższy poziom. Możesz o nich myśleć jak o ekwiwalencie maszyny drukarskiej Gutenberga dla zastosowań graficznych. @@ -17,19 +17,19 @@ W następujących rozdziałach odkryjesz jak niewiarygodnie szybkie i potężne ## Dla kogo jest ta książka? -Ta książka jest napisana dla creative koderów, game developerów i inżynierów, którzy posiadają doświadczenie programistyczne, podstawową wiedzę z algebry liniowej i trygonometrii, i którzy chcą wznieść jakość swoich prac graficzny na wyższy poziom. (Jeżeli chcesz nauczyć się programować, polecam zacząć od [Processing](https://processing.org/) i wrócić, gdy opanujesz go do komfortowego poziomu. +Ta książka jest napisana dla osób zainteresowanych *creative coding*'iem, game developerów i inżynierów, którzy posiadają doświadczenie programistyczne, podstawową wiedzę z algebry liniowej i trygonometrii, i którzy chcą podnieść jakość swoich prac graficzny na wyższy poziom. (Jeżeli chcesz nauczyć się programować, polecam zacząć od [Processing](https://processing.org/) i wrócić, gdy opanujesz go do komfortowego poziomu. -Ta książka nauczy cię jak używać i integrować shadery w twoich projektach, aby podnieść ich wydajność i wygląd. Ponieważ shadery GLSL (OpenGL Shading Language) kompilują i uruchamiają się na różnorodnych platformach, będziesz w stanie zaaplikować tutaj zdobytą wiedzę do jakiegokolwiek środowiska wykorzystującego OpenGL, OpenGL ES lub WebGL. Innymi słowy, będziesz w stanie wykorzystać tę wiedzę przy tworzeniu szkiców z [Processing](https://processing.org/), aplikacji z [openFrameworks](http://openframeworks.cc/), interaktywnych instalacji z [Cinder](http://libcinder.org/) czy stron internetowych i gier iOS/Android z [Three.js](http://threejs.org/). +Ta książka nauczy cię jak używać shadery w celu polepszenia wydajności i wyglądu twoich projektów. Ponieważ shadery GLSL (OpenGL Shading Language) kompilują i uruchamiają się na różnorodnych platformach, będziesz w stanie zaaplikować tutaj zdobytą wiedzę do jakiegokolwiek środowiska wykorzystującego OpenGL, OpenGL ES lub WebGL. Innymi słowy, będziesz w stanie wykorzystać tę wiedzę przy tworzeniu szkiców z [Processing](https://processing.org/), aplikacji z [openFrameworks](http://openframeworks.cc/), interaktywnych instalacji z [Cinder](http://libcinder.org/) czy stron internetowych z [Three.js](http://threejs.org/) i gier iOS/Android. ## Jaki materiał pokrywa ta książka? -Ta książka skupia się na użyciu fragment shaderów GLSL. Wpierw zdefiniujemy czym shadery są; potem dowiemy się jak, z ich pomocą, tworzyć proceduralne kształty, wzorce, tekstury i animacje. Nauczysz się podstaw języka shadingowego i jego przydatnych aplikacji w przetwarzaniu obrazów (operacje na obrazach, sploty macierzowe, rozmycia, filtry koloru, "lookup tables" i inne efekty) czy symulacji ("Gra w życie" Conwaya, model reakcji-dyfuzji Graya-Scotta, plusk wody, efekt akwareli, komórki Voronoi, itp.). Pod koniec książki zobaczymy kilka zaawansowanych technik opartych o Ray Marching +Ta książka skupia się na użyciu fragment shaderów GLSL. Wpierw zdefiniujemy czym shadery są; potem dowiemy się jak, z ich pomocą, tworzyć proceduralne kształty, wzory, tekstury i animacje. Nauczysz się podstaw języka shadingowego i jego przydatnych aplikacji w przetwarzaniu obrazów (operacje na obrazach, sploty macierzowe, rozmycia, filtry koloru, "lookup tables" i inne efekty) czy symulacji ("Gra w życie" Conwaya, model reakcji-dyfuzji Graya-Scotta, plusk wody, efekt akwareli, komórki Voronoi, itp.). Pod koniec książki zobaczymy kilka zaawansowanych technik opartych o Ray Marching. *W każdym rozdziale znajdziesz interaktywne przykłady do wypróbowania.* Kiedy zmodyfikujesz kod, natychmiastowo zobaczysz zmiany. Zagadnienia mogą być abstrakcyjne i mylące, więc takie interkatywne przykłady stanowią konieczną pomoc w zrozumieniu materiału. Im szybciej złapiesz praktykę, tym prostsza będzie dalsza nauka. Materiał, którego ta książka nie pokrywa: -* To *nie jest* książka o OpenGL lub WebGL. OpenGL/WebGL jest większym tematem niż GLSL czy fragment shadery. Jeśli chcesz wiedzieć więcej o OpenGL i WebGL, to polecam zajrzeć do [OpenGL Introduction](https://open.gl/introduction), [the 8th edition of the OpenGL Programming Guide](http://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) (zwana również "czerwoną książką") lub [WebGL: Up and Running](http://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) +* To *nie jest* książka o OpenGL lub WebGL. OpenGL/WebGL jest większym tematem niż GLSL czy fragment shadery. Jeśli chcesz wiedzieć więcej o OpenGL i WebGL, polecam zajrzeć do [OpenGL Introduction](https://open.gl/introduction), [the 8th edition of the OpenGL Programming Guide](http://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) (zwana również "czerwoną książką") lub [WebGL: Up and Running](http://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) * To *nie jest* książka do nauki matematyki. Choć opisane są w niej algorytmy i techniki, które opierają się zrozumieniu algebry i trygonometrii, to nie będziemy ich szczegółowo tłumaczyć. Z pytaniami dotyczącymi matematyki polecam zajrzeć do następujących książek: [3rd Edition of Mathematics for 3D Game Programming and computer Graphics](http://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) lub [2nd Edition of Essential Mathematics for Games and Interactive Applications](http://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). @@ -38,13 +38,13 @@ Materiał, którego ta książka nie pokrywa: Niewiele! Jeśli masz współczesną przeglądarkę, która obsługuje WebGL (jak Chrome, Firefox czy Safari) i połączenie internetowe, to kliknij "Dalej" na dole strony, aby zacząć. -Alternatywnie, w zależności od tego co masz albo co potrzebujesz od tej książki, możesz: +Alternatywnie, w zależności od tego, co masz albo co potrzebujesz od tej książki, możesz: -- [Stworzyć wersję off-line tej książki](https://thebookofshaders.com/appendix/00/) +- [Stworzyć wersję off-line tej książki](https://thebookofshaders.com/appendix/00/?lan=pl) -- [Uruchomić przykłady na Raspberry PI bez przeglądarki](https://thebookofshaders.com/appendix/01/) +- [Uruchomić przykłady na Raspberry PI bez przeglądarki](https://thebookofshaders.com/appendix/01/?lan=pl) -- [Stworzyć wersję PDF tej książki do wydrukowania](https://thebookofshaders.com/appendix/02/) +- [Stworzyć wersję PDF tej książki do wydrukowania](https://thebookofshaders.com/appendix/02/?lan=pl) -- Sprawdź [repozytorium GitHub](https://github.com/patriciogonzalezvivo/thebookofshaders) tej książki, by pomóc rożwiązać issues i podzielić się swoim kod +- Sprawdź [repozytorium GitHub](https://github.com/patriciogonzalezvivo/thebookofshaders) tej książki, by pomóc rożwiązać issues i podzielić się swoim kodem. diff --git a/01/README-pl.md b/01/README-pl.md index c80f2de..555a18c 100644 --- a/01/README-pl.md +++ b/01/README-pl.md @@ -3,15 +3,16 @@ W poprzednim rozdziale nazwaliśmy shadery ekwiwalentem prasy drukarskiej Gutenberga dla grafiki. Dlaczego? A co ważniejsze: czym jest shader? -![Od "litera po literze" do "strona po stronie", po prawej: William Blades (1891), po lewej: Rolt-Wheeler (1920).](print.png) +![Od litera po literze, po lewej: William Blades (1891); do strona po stronie, po prawej: Rolt-Wheeler (1920).](print.png) -Jeżeli masz doświadczenie w rysowaniu z użyciem komputera, to wiesz, że proces ten polega na rysowaniu kółek, prostokątów, linii oraz trójkątów do momentu skomponowania pożądanego obrazu. Proces ten jest bardzo podobny do pisania listów lub książek odręcznie - jest to zbiór instrukcji wykonujących zadanie po zadaniu. +Jeżeli masz doświadczenie w rysowaniu z użyciem komputera (np. w *Paint*), to wiesz, że proces ten polega na rysowaniu kółek, prostokątów, linii oraz trójkątów do momentu skomponowania pożądanego obrazu. Proces ten jest bardzo podobny do pisania listów lub książek odręcznie - jest to zbiór instrukcji wykonujących zadanie po zadaniu. -If you already have experience making drawings with computers, you know that in that process you draw a circle, then a rectangle, a line, some triangles until you compose the image you want. That process is very similar to writing a letter or a book by hand - it is a set of instructions that do one task after another. + -Shader jest również zbiorem instrukcji, ale wykonywanych równocześnie dla każdego piksela na ekranie. Oznacza to, że kod, który piszesz musi działać inaczej w zależności od pozycji piksela na ekranie. Podobnie jak maszyna drukarska, twój program będzie działał jak funkcja matematyczna otrzymująca pozycję piksela i zwracająca jego kolor. Po skompilowaniu twój program będzie działał błyskawicznie. - -Shaders are also a set of instructions, but the instructions are executed all at once for every single pixel on the screen. That means the code you write has to behave differently depending on the position of the pixel on the screen. Like a type press, your program will work as a function that receives a position and returns a color, and when it's compiled it will run extraordinarily fast. +Shader również jest zbiorem instrukcji, ale wykonywanych równocześnie dla każdego piksela na ekranie. Oznacza to, że kod, który piszesz musi działać inaczej w zależności od pozycji piksela na ekranie. Podobnie jak maszyna drukarska, twój program będzie działał jak funkcja matematyczna otrzymująca pozycję piksela i zwracająca jego kolor. Po skompilowaniu twój program będzie działał błyskawicznie. + ![Chińska ruchoma czcionka](typepress.jpg) @@ -19,58 +20,58 @@ Shaders are also a set of instructions, but the instructions are executed all at Aby odpowiedzieć na pytanie, omówmy cud *przetwarzania równoległego* (ang. *parallel processing*) -To answer this, I present the wonders of *parallel processing*. + -Wyobraź sobie procesor twojego komputera jako pipeline, przez który przechodzą różnorakie zadania (jak na linii produkcyjnej w fabryce). Niektóre zadania są większe od innych, co oznacza, że wymagają więcej czasu i energii. Mówimy wtedy, że wymagają więcej *mocy obliczeniowej* (ang. *processing power*). Ze względu na architekturę współczesnych komputerów, zadania te wykonują się seryjnie (jeden po drugim) - każde zadanie musi poczekać, dopóki poprzednie zadanie nie zostanie ukończone. Jednakże, współczesne komputery posiadają zwykle więcej niż jedną jednostkę przetwarzają (np. 2, 4 lub 8 rdzeni procesora), które funkcjonują jak pomniejsze pipeline'y. Każda taki pomniejsze pipeline nazywany jest również *wątkiem* (ang. *thread*). +Wyobraź sobie procesor twojego komputera jako potok przetwarzania (ang. "pipeline"), przez który przechodzą różnorakie zadania (jak na linii produkcyjnej w fabryce). Niektóre zadania są większe od innych, co oznacza, że wymagają więcej czasu i energii. Mówimy wtedy, że wymagają więcej *mocy obliczeniowej* (ang. *processing power*). Ze względu na architekturę współczesnych komputerów, zadania te wykonują się seryjnie (jeden po drugim) - każde zadanie musi poczekać, dopóki poprzednie zadanie nie zostanie ukończone. Jednakże, współczesne komputery posiadają zwykle więcej niż jedną jednostkę przetwarzającą (np. 2, 4 lub 8 rdzeni procesora), które funkcjonują jak pomniejsze potoki przetwarzania. Każdy taki pomniejszy potok nazywany jest również *wątkiem* (ang. *thread*). -Imagine the CPU of your computer as a big industrial pipe, and every task as something that passes through it - like a factory line. Some tasks are bigger than others, which means they require more time and energy to deal with. We say they require more processing power. Because of the architecture of computers the jobs are forced to run in a series; each job has to be finished one at a time. Modern computers usually have groups of four processors that work like these pipes, completing tasks one after another to keep things running smoothly. Each pipe is also known as a *thread*. + ![CPU](00.jpeg) -Gry video i inne aplikacje graficzne wymagają zdecydowanie więcej mocy obliczeniowej niż większość programów, gdyż muszą wykonywać ogromne ilości operacji piksel po pikselu. Nie dość, że każdy pojedynczy piksel musi być obliczony, to w wypadku gier 3D dochodzą do tego obliczania geometryczne i obliczenie perspektywy. +Gry video i inne aplikacje graficzne wymagają zdecydowanie więcej mocy obliczeniowej niż większość programów, gdyż muszą wykonywać ogromne ilości operacji piksel po pikselu. Nie dość, że każdy pojedynczy piksel musi być obliczony, to w wypadku gier 3D dochodzą do tego obliczenia geometryczne i obliczenie perspektywy. -Video games and other graphic applications require a lot more processing power than other programs. Because of their graphic content they have to do huge numbers of pixel-by-pixel operations. Every single pixel on the screen needs to be computed, and in 3D games geometries and perspectives need to be calculated as well. + -Wróćmy do naszej metafory pipeline'u. Każdy piksel na ekranie reprezentuje proste zadanie. Indywidualnie zadania te nie stanowią problemu dla CPU, jednak sytuacja zmienia się, gdy takie zadanie musi być wykonane dla każdego piksela na ekranie. Oznacza to, że na starym monitorze 800x600 na jedną klatkę przypada 480.000 obliczeń, a na jedną sekundę - 14.400.000. Właśnie tak! Skala problemu może przeciążyć mikroprocesor. Na współczesnym monitorze 2560x1440 przy 60 FPS osiągamy 221.356.800 obliczeń na sekundę. Jak inżynierowie graficzni rozwiązują ten problem? +Wróćmy do naszej metafory potoku przetwarzania. Każdy piksel na ekranie reprezentuje proste zadanie. Indywidualnie zadania te nie stanowią problemu dla CPU, jednak sytuacja zmienia się, gdy takie zadanie musi być wykonane dla każdego piksela na ekranie. Oznacza to, że na starym monitorze 800x600 na jedną klatkę przypada 480.000 obliczeń, co oznacza 14.400.000 obliczeń na jedną sekundę! Właśnie tak! Skala problemu może przeciążyć mikroprocesor. Co więcej, na współczesnym monitorze 2560x1440 przy 60 FPS osiągamy 221.356.800 obliczeń na sekundę. Jak inżynierowie graficzni rozwiązują ten problem? -Let's go back to our metaphor of the pipes and tasks. Each pixel on the screen represents a simple small task. Individually each pixel task isn't an issue for the CPU, but (and here is the problem) the tiny task has to be done to each pixel on the screen! That means in an old 800x600 screen, 480,000 pixels have to processed per frame which means 14,400,000 calculations per second! Yes! That’s a problem big enough to overload a microprocessor. In a modern 2880x1800 retina display running at 60 frames per second that calculation adds up to 311,040,000 calculations per second. How do graphics engineers solve this problem? + ![](03.jpeg) -Z pomocą przychodzi przetwarzanie równoległe. Zamiast kilku dużych, potężnych mikroprocesorów (lub *rur*) lepiej mieć wiele małych mikroprocesorów działających równolegle. Tak właśnie działa procesor graficzna (GPU) w karcie graficznej. +Z pomocą przychodzi przetwarzanie równoległe. Zamiast kilku dużych, potężnych mikroprocesorów (potoków) lepiej mieć wiele małych mikroprocesorów działających równolegle. Tak właśnie działa procesor graficzny (GPU) w karcie graficznej. -This is when parallel processing becomes a good solution. Instead of having a couple of big and powerful microprocessors, or *pipes*, it is smarter to have lots of tiny microprocessors running in parallel at the same time. That’s what a Graphic Processor Unit (GPU) is. + ![GPU](04.jpeg) -Wyobraź sobie mały mikroprocesor jako tabele rur, a dane jako piłeczkę ping pongową. 14.400.000 piłeczek ping pongowych na sekundę może zablokować prawie każdą rurę. Ale tabela 800x600 malutkich rur przyjmująca co sekundę 30 fal po 480.000 pikseli poradzi sobie z nimi bez problemu. Tak samo działa to na wyższych rozdzielczościach - im więcej równolegle pracującego hardware'u, tym większy potok, z którym sobie poradzi. +Wyobraź sobie mały mikroprocesor jako tablicę rur (spójrz na obrazek powyżej), a dane jako piłeczki ping pongowe. 14.400.000 piłeczek ping pongowych na sekundę może zablokować prawie każdą pojedynczą rurę. Ale tabela 800x600 malutkich rur przyjmująca co sekundę 30 fal po 480.000 piłeczek poradzi sobie z nimi bez problemu. Tak samo działa to na wyższych rozdzielczościach - im więcej równolegle pracującego hardware'u, tym większy potok, z którymi GPU sobie poradzi. -Picture the tiny microprocessors as a table of pipes, and the data of each pixel as a ping pong ball. 14,400,000 ping pong balls a second can obstruct almost any pipe. But a table of 800x600 tiny pipes receiving 30 waves of 480,000 pixels a second can be handled smoothly. This works the same at higher resolutions - the more parallel hardware you have, the bigger the stream it can manage. + Inną "super umiejętnością" GPU jest fakt, że złożone funkcje matematyczne wykonywane są bezpośrednio na poziomie hardware'u przez mikroczipy, a nie przez software. Skutkiem tego są super szybkie operacje trygonometryczne i macierzowe. -Another “super power” of the GPU is special math functions accelerated via hardware, so complicated math operations are resolved directly by the microchips instead of by software. That means extra fast trigonometrical and matrix operations - as fast as electricity can go. + ## Czym jest GLSL? -GLSL oznacza "Open**GL** **S**hading **L**anguage" i stanowi standard pisania shaderów, który zobaczysz następnych rozdziałach tej książki. W zależności od hardware'u i systemu operacyjnego wyróżnia się też inne rodzaje shaderów. Tutaj skupimy się na specyfikacji OpenGL uregulowanej przez [Khronos Group](https://www.khronos.org/opengl/). Zrozumienie historii OpenGL może pomóc w zrozumieniu wielu dziwnych konwencji; w tym celu polecam zajrzeć do: [openglbook.com/chapter-0-preface-what-is-opengl.html](http://openglbook.com/chapter-0-preface-what-is-opengl.html). +GLSL oznacza "Open**GL** **S**hading **L**anguage" i stanowi standard pisania shaderów, który zobaczysz w następnych rozdziałach tej książki. W zależności od hardware'u i systemu operacyjnego wyróżnia się też inne rodzaje shaderów. Tutaj skupimy się na specyfikacji OpenGL uregulowanej przez [Khronos Group](https://www.khronos.org/opengl/). Zrozumienie historii OpenGL może pomóc w zrozumieniu wielu dziwnych konwencji; w tym celu polecam zajrzeć do: [openglbook.com/chapter-0-preface-what-is-opengl.html](http://openglbook.com/chapter-0-preface-what-is-opengl.html). -GLSL stands for openGL Shading Language, which is the specific standard of shader programs you'll see in the following chapters. There are other types of shaders depending on hardware and Operating Systems. Here we will work with the openGL specs regulated by [Khronos Group](https://www.khronos.org/opengl/). Understanding the history of OpenGL can be helpful for understanding most of its weird conventions, for that I recommend taking a look at: [openglbook.com/chapter-0-preface-what-is-opengl.html](http://openglbook.com/chapter-0-preface-what-is-opengl.html) + ## Dlaczego shadery budzą postrach? Jak to mówią: "with great power comes great responsibility". Stosuje się to również do obliczeń równoległych - potężne rozwiązania architektoniczne w GPU wiążą się również z pewnymi ograniczeniami. -As Uncle Ben said “with great power comes great responsibility,” and parallel computation follows this rule; the powerful architectural design of the GPU comes with its own constraints and restrictions. + -Aby wątki mogły działać równolegle, muszą być od siebie niezależne. Mówimy, że wątki są *ślepe* na to, co robi reszta wątków. Ograniczenie to implikuje, że dane muszą "płynąć w ten samą stronę" - nie jest możliwe sprawdzić wynik innego wątku, zmodyfikować jego wejście albo przekazać wyjście jednego wątku do wejścia drugiego. +Aby wątki mogły działać równolegle, muszą być od siebie niezależne. Mówimy, że wątki są *ślepe* na to, co robi reszta wątków. Ograniczenie to implikuje, że dane muszą "płynąć w ten samą stronę" - nie jest możliwe sprawdzić dane wyjściowe innego wątku, zmodyfikować jego dane wejściowe albo przekazać dane wyjściowe jednego wątku jako dane wejściowe innego. -In order to run in parallel every pipe, or thread, has to be independent from every other thread. We say the threads are *blind* to what the rest of the threads are doing. This restriction implies that all data must flow in the same direction. So it’s impossible to check the result of another thread, modify the input data, or pass the outcome of a thread into another thread. Allowing thread-to-thread communications puts the integrity of the data at risk. + -Poza tym GPU odpowiada za to, żeby każdy wątek miał coś do roboty, i żeby otrzymał dane potrzebne do jej wykonania. Nie jest możliwe, aby wątek wiedział, co robił sekundę temu. Mógł rysować przycisk w UI systemu operacyjnego, a potem renderować fragment nieba w grze wideo, a jeszcze potem wyświetlać treść maila. Każdy wątek jest nie tylko **ślepy**, ale również **bez pamięci**. Te cechy sprawiają, że pisanie shaderów nie cieszy się dużą popularnością wśród początkujących programistów. +Poza tym GPU odpowiada za to, żeby każdy wątek miał coś do roboty, i żeby otrzymał dane potrzebne do wykonania tej roboty. Trzeba też pamiętać, że nie jest możliwe, aby wątek wiedział, co robił sekundę temu - mógł rysować przycisk w UI systemu operacyjnego, a potem renderować fragment nieba w grze wideo, a jeszcze potem wyświetlać treść maila. Każdy wątek jest nie tylko **ślepy**, ale również **bez pamięci**. Te cechy sprawiają, że pisanie shaderów nie cieszy się dużą popularnością wśród początkujących programistów. -Also the GPU keeps the parallel micro-processor (the pipes) constantly busy; as soon as they get free they receive new information to process. It's impossible for a thread to know what it was doing in the previous moment. It could be drawing a button from the UI of the operating system, then rendering a portion of sky in a game, then displaying the text of an email. Each thread is not just **blind** but also **memoryless**. Besides the abstraction required to code a general function that changes the result pixel by pixel depending on its position, the blind and memoryless constraints make shaders not very popular among beginning programmers. + -Ale nie martw się! W następnych rozdziałąch nauczymy się, krok po kroku, prostych i zaawansowanych obliczeń shadingowych. Jeżeli czytasz to we współczesnej przeglądarce, to z pewnością docenisz zabawę z interaktywnymi przykładami. Ale nie przedłużajmy! Naciśnij *Next >>* aby przejść dalej. +Ale nie martw się! W następnych rozdziałąch nauczymy się, krok po kroku, prostych i zaawansowanych obliczeń shadingowych. Jeżeli czytasz to we współczesnej przeglądarce, to z pewnością docenisz zabawę z interaktywnymi przykładami. Ale nie przedłużajmy! Naciśnij *Next>>* aby przejść dalej. -Don't worry! In the following chapters, we will learn step-by-step how to go from simple to advanced shading computations. If you are reading this with a modern browser, you will appreciate playing with the interactive examples. So let's not delay the fun any longer and press *Next >>* to jump into the code! + diff --git a/02/README-pl.md b/02/README-pl.md index 2d37766..ae8196a 100644 --- a/02/README-pl.md +++ b/02/README-pl.md @@ -1,32 +1,32 @@ -## Hello World +## Witaj świecie! Zazwyczaj przykład "Hello world!" stanowi pierwszy krok przy nauce nowego języka. Jest to prosty jednolinijkowy programy, który zwraca pełną entuzjazmu wiadomość powitalną i tym samym zapowiada nadchodzące przygody. -Usually the "Hello world!" example is the first step to learning a new language. It's a simple one-line program that outputs an enthusiastic welcoming message and declares opportunities ahead. + W świecie GPU renderowanie tekstu jest jednak zbyt skomplikowanym zadaniem dla żółtodzioba. Zamiast tego wybierzemy jasny, serdeczny kolor by wykrzyczeć naszą ekscytację! -In GPU-land rendering text is an overcomplicated task for a first step, instead we'll choose a bright welcoming color to shout our enthusiasm! +
Jeżeli czytasz tę książkę w przeglądarce: powyższy blok kodu jest interaktywny. Oznacza to, że możesz edytować dowolną linijkę kodu w celach eksploracyjnych. Shader kompiluje się na bieżąco, więc zmiany widoczne będą natychmiast. Spróbuj pozmieniać wartości w linijce 8. -If you are reading this book in a browser the previous block of code is interactive. That means you can click and change any part of the code you want to explore. Changes will be updated immediately thanks to the GPU architecture that compiles and replaces shaders *on the fly*. Give it a try by changing the values on line 8. + Choć kod jest prosty, to możemy wyciągnąć z niego ważne wnioski: -1. Podobnie jak w C, język shadingowy ma jedną funkcje `main`. Pod koniec zwraca ona kolor. +1. Podobnie jak w C, GLSL ma jedną funkcje `main`. Pod koniec zwraca ona kolor. 2. Finalny kolor piksela przypisywany jest do zarezerowanej zmiennej globalnej `gl_FragColor`. -3. Ten C-podobny język ma wbudowane *zmienne* (jak `gl_FragColor`), *funkcje* i *typy*. W aktualnym przykładzie występuje jedynie typ `vec4`, oznaczający czterowymiarowy wektor zmiennoprzecinkowy ("float vector"). Później zobaczymy również takie typy jak `vec3`, `vec2` oraz znajome `float`, `int` i `bool`. +3. Ten C-podobny język ma wbudowane *zmienne* (jak `gl_FragColor`), *funkcje* i *typy*. W aktualnym przykładzie występuje jedynie typ `vec4`, oznaczający czterowymiarowy wektor zmiennoprzecinkowy (ang. "float vector"). Później zobaczymy również takie typy jak `vec3`, `vec2` oraz znajome `float`, `int` i `bool`. 4. Patrząc na typ `vec4`, możemy wywnioskować, że jego cztery argumenty odnoszą się do kanałów CZERWONEGO, ZIELONEGO, NIEBIESKIEGO i ALPHA. Widać też, że jego wartości są *znormalizowane*, więc znajdują się w zakresie od `0.0` do `1.0`. Później zobaczymy, jak normalizowanie wartości pomaga w *mapowaniu* wartości między zakresami. -5. Kolejnym ważną C-podobną własnością w tym przykładzie jest obecność makr preprocessora. Dzięki nim można definiować zmienne globalne za pomocą `#define` oraz operacje warunkowe za pomocą `#ifdef` ("if defined"), `#ifndef` ("if not defined") i `#endif`. Wszystkie makra zaczynają się od płotka `#` kompilacją wszystkie ... W naszym powyższym przykładzie linijka 2 kompilowana jest tylko wtedy, gdy zmienna `GL_ES` jest zdefiniowana (jest na urządzeniach mobilnych i w przeglądarkach). +5. Kolejną ważną C-podobną własnością w tym przykładzie jest obecność makr preprocessora. Dzięki nim można definiować zmienne globalne za pomocą `#define` oraz operacje warunkowe za pomocą `#ifdef` ("if defined"), `#ifndef` ("if not defined") i `#endif`. Wszystkie makra zaczynają się od płotka `#` i ewaluowane są podczas procesu prekompilacji poprzedzającego kompilację. W naszym powyższym przykładzie linijka 2 kompilowana jest tylko wtedy, gdy zmienna `GL_ES` jest zdefiniowana (co występuje na urządzeniach mobilnych i w przeglądarkach). -Although these simple lines of code don't look like a lot, we can infer substantial knowledge from them: + 6. Typy zmiennoprzecinkowe są kluczowe w shaderach, więc ich poziom precyzji (ang. *precision*) jest kluczowy. Niższa precyzja oznacza szybsze renderowanie, ale kosztem jakości. Możesz być wybredny i określać precyzję każdej zmiennej zmiennoprzecinkowej z osobna. W linijce 2 (`precision mediump float;`) ustawiamy średnią precyzję zmiennych zmiennoprzecinkowych ("mediump", bo "medium precision"). Możemy też ustawić ją jako niską (`precision lowp float;`) lub wysoką (`precision highp float;`). -7. Ostatni i chyba najważniejszy szczegół specyfikacji GLSL: nie ma gwaracji, że zmienne będą automatycznie castowane (np. z `int` do `float` przy dzieleniu liczby 5 przez 2). Producenci GPU mogą stosować przeróżne optymalizacje w kartach graficzncyh, ale muszą przy tym przestrzegać pewnych wytycznych. Automatyczne castowanie nie jest jednym z nich. W naszym przykładzie `vec4` ma precyzję zmiennoprzecinkową i dlatego jego argumenty wymagają `float`ów. Przezwyczaj się do stawiania kropek (`.`) we `float`ach (`1.` lub `1.0`, a nie `1`), jeżeli nie chcesz spędzić godzin przy debugowaniu. Poniższy kod nie zawsze będzie działa: +7. Ostatni i chyba najważniejszy szczegół specyfikacji GLSL: nie ma gwaracji, że zmienne będą automatycznie castowane (np. z `int` do `float` przy dzieleniu liczby 5 przez 2). Producenci GPU mogą stosować przeróżne optymalizacje w kartach graficzncyh, ale muszą przy tym przestrzegać pewnych wytycznych. Automatyczne castowanie nie jest jednym z nich. W naszym przykładzie `vec4` ma precyzję zmiennoprzecinkową i dlatego jego argumenty wymagają `float`ów. Przezwyczaj się do stawiania kropek (`.`) we `float`ach (`1.` lub `1.0`, a nie `1`), jeżeli nie chcesz spędzić godzin przy debugowaniu. Poniższy kod nie zawsze będzie, zatem, działał: ```glsl void main() { @@ -48,9 +48,9 @@ void main() { } ``` -Czas +Czas na ćwiczenia! Pamiętaj, że w wypadku błędu kompilacji pokaże się informacje o błędzie i linijce w której wystąpił, a kanwa zmieni kolor na biały. -* Spróbuj zamienić `float`y na `int`y. Jeśli kod się nie kompiluje, to twoja karta graficzna nie toleruje +* Spróbuj zamienić `float`y na `int`y. Jeśli kod się nie kompiluje, to widocznie twoja karta graficzna tego nie toleruje * Zakomentuj linię 8 @@ -68,7 +68,4 @@ vec4 red(){ vec4 color = vec4(vec3(1.0,0.0,1.0),1.0); ``` -Choć przykład ten nie jest zbyt ekscytujący -W następnych rozdziałach zobaczymy, jak zmienić kolor piksela z pomocą inputu przestrzennego (położenie piksela na ekranie) i temporalnego (okres czasu od momentu załadowania się strony) - - +Choć przykład ten nie jest zbyt ekscytujący, ale stanowi ważną podstawę. W następnych rozdziałach zobaczymy, jak zmienić kolor piksela z pomocą inputu przestrzennego (położenie piksela na ekranie) i temporalnego (okres czasu od momentu załadowania się strony). \ No newline at end of file diff --git a/03/README-pl.md b/03/README-pl.md index 640b69d..67e5556 100644 --- a/03/README-pl.md +++ b/03/README-pl.md @@ -1,12 +1,12 @@ ## Uniformy -Do tej pory widzieliśmy jak GPU zarządza wieloma równoległymi wątkami, z który każdy odpowiada za kolor części renderowanego obrazu. Choć wątki nie komunikują się między sobą, to jednak muszą jakoś otrzymywać input z CPU. Ze względu na architekturę karty graficznej taki input musi być jednakowy (ang. *uniform*) dla wszystkich wątków i, z konieczności, tylko do odczytu. Innymi słowy, każdy wątek otrzymuje takie same dane, które może odczytać, ale nie nadpisać, zmienić. +Do tej pory widzieliśmy jak GPU zarządza wieloma równoległymi wątkami, z których każdy odpowiada za kolor części renderowanego obrazu. Choć wątki nie komunikują się między sobą, to jednak muszą jakoś otrzymywać input z CPU. Ze względu na architekturę karty graficznej taki input musi być jednakowy (ang. "*uniform*") dla wszystkich wątków i, z konieczności, tylko do odczytu (ang. "read-only"). Innymi słowy, każdy wątek otrzymuje takie same dane, które może odczytać, ale nie nadpisać, zmienić. -~~So far we have seen how the GPU manages large numbers of parallel threads, each one responsible for assigning the color to a fraction of the total image. Although each parallel thread is blind to the others, we need to be able to send some inputs from the CPU to all the threads. Because of the architecture of the graphics card those inputs are going to be equal (*uniform*) to all the threads and necessarily set as *read only*. In other words, each thread receives the same data which it can read but cannot change.~~ + -Inputy te nazywamy `uniform`ami i mogę być większości wspieranych typów: `float`, `vec2`, `vec3`, `vec4`, `mat2`, `mat3`, `mat4`, `sampler2D` i `samplerCube`. Uniformy definiowane są zwykle na górze shaderu zaraz po przypisaniu domyślnej precyzji floatów. +Inputy te nazywamy `uniform`ami i mogę być większości wspieranych typów: `float`, `vec2`, `vec3`, `vec4`, `mat2`, `mat3`, `mat4`, `sampler2D` i `samplerCube`. Uniformy definiowane są zwykle na górze shaderu zaraz po przypisaniu domyślnej precyzji float'ów. -~~These inputs are called `uniform` and come in most of the supported types: `float`, `vec2`, `vec3`, `vec4`, `mat2`, `mat3`, `mat4`, `sampler2D` and `samplerCube`. Uniforms are defined with the corresponding type at the top of the shader right after assigning the default floating point precision.~~ + ```glsl #ifdef GL_ES @@ -20,7 +20,7 @@ uniform float u_time; // czas w sekundach od załadowania shadera Wyobraź sobie te uniformy jak małe mosty między CPU i GPU. Ich nazwy bywają różne, ale w tej książce używam: `u_time`, `u_resolution` i `u_mouse` (przeczytaj komentarze w kodzie, aby wiedzieć, co robią). Podążam za konwencją dodawnaia `u_` przed nazwą uniformów, aby było wiadomo, że nie są to zwykłe zmienne, ale ostatecznie jest to kwestia gustu. Przykładowo, [ShaderToy.com](https://www.shadertoy.com/) używa takich samych uniformów, ale z następującym nazewnictwem: -~~You can picture the uniforms like little bridges between the CPU and the GPU. The names will vary from implementation to implementation but in this series of examples I’m always passing: `u_time` (time in seconds since the shader started), `u_resolution` (billboard size where the shader is being drawn) and `u_mouse` (mouse position inside the billboard in pixels). I’m following the convention of putting `u_` before the uniform name to be explicit about the nature of this variable but you will find all kinds of names for uniforms. For example [ShaderToy.com](https://www.shadertoy.com/) uses the same uniforms but with the following names:~~ + ```glsl uniform vec3 iResolution; @@ -57,7 +57,7 @@ Pobawmy się powyższym kodem: ## gl_FragCoord -GLSL daje nam nie tylko domyślny output `vec4 gl_FragColor`, ale również domyślny input w postaci `vec4 gl_FragCoord`, który przechowuje współrzędne *piksela* (inaczej: *fragmentu*), nad którym aktualnie pracuje wątek - dzięki `vec4 gl_FragCoord` wiemy, gdzie wątek pracuje wewnątrz kanwy. Nie nazywamy go `uniform`em, ponieważ jego wartość różni się między wątkami. Zamiast tego `gl_FragCoord` nazywamy *varying* (z ang. "zmieniający się", "różniący się"). +GLSL daje nam nie tylko domyślny output `vec4 gl_FragColor`, ale również domyślny input w postaci `vec4 gl_FragCoord`, który przechowuje współrzędne *piksela* (inaczej: *fragmentu*), nad którym aktualnie pracuje wątek - dzięki `vec4 gl_FragCoord` wiemy, gdzie wątek pracuje wewnątrz kanwy. Nie nazywamy go `uniform`em, ponieważ jego wartość *różni się* między wątkami. Zamiast tego `gl_FragCoord` nazywamy *varying* (z ang. "zmieniający się", "różniący się"). diff --git a/04/README-pl.md b/04/README-pl.md index 44397c3..1b231ea 100644 --- a/04/README-pl.md +++ b/04/README-pl.md @@ -252,7 +252,7 @@ Po więcej informacji na temat shaderów w openFrameworks zajrzyj do znakomitego ### W **Blender** -[GlslTexture](https://github.com/patriciogonzalezvivo/glslTexture) to addon pozwalający programistycznie generować textury z użyciem shaderó GLSL. Jest on w pełni kompatybilny z resztą sandboxów w tym rozdziale. Jak go użyć? +[GlslTexture](https://github.com/patriciogonzalezvivo/glslTexture) to addon pozwalający programistycznie generować textury z użyciem shaderów GLSL. Jest on w pełni kompatybilny z resztą sandboxów w tym rozdziale. Jak go użyć? diff --git a/05/README-pl.md b/05/README-pl.md index 394fa66..a05c9cc 100644 --- a/05/README-pl.md +++ b/05/README-pl.md @@ -1,5 +1,5 @@ # Rysowanie algorytmiczne -## Funkcje kształtujące (ang. "shaping functions") +## Shaping functions Rozdział ten mógłby się nazywać "lekcja płota Pana Miyagiego". Poprzednio, mapowaliśmy znormalizowane pozycje *x* i *y* do *czerwonego* i *zielonego* kanału. W skróćie, stworzyliśmy fumkcję, która przyjmuje dwuwymiarowy wektor (x i y) i zwraca czterowymiarowy wektor (r, g, b i a). Jednak zanim zagłębimy się w takie transformacje między wymiarami, wypada najpierw opanować tworzenie jednowymiarowych funkcji w pełni. Im więcej czasu spędzisz na szlifowaniu tej umiejętności, tym lepsze będzie twoje "shader karate". @@ -13,14 +13,13 @@ Poniższy kod będzie naszym płotem. Wizualizujemy w nim znormalizowaną warto
-**Krótka uwaga**: Konstruktor typu `vec3` "rozumie", że chcesz przypisać tę samą wartość do każdego z trzech kanałów koloru, natomaist typu `vec4` rozumie, że chcesz stworzyć czterowymiarowy wektor z wektora trójwymiarowego i czwartej wartości (w tym wypadku wartość ta controluje alphę, czyli przezroczystość). Spójrz na linjki 19 i 25 powyżej. +**Krótka uwaga**: Konstruktor typu `vec3` "rozumie", że chcesz przypisać tę samą wartość do każdego z trzech kanałów koloru, natomaist typu `vec4` rozumie, że chcesz stworzyć czterowymiarowy wektor z wektora trójwymiarowego i czwartej wartości (w tym wypadku wartość ta kontroluje alphę, czyli przezroczystość). Spójrz na linjki 19 i 25 powyżej. -Kod jest twoim płotem - ważne, żebyś umiał na niego spojrzeć i go zrozumieć. Będziesz zakres od *0.0* do *1.0* będzie ci stale towarzyszył. Opanujesz sztukę blendowania (pol. "mieszania", "łączenia") i kształtowaniatej linii +Kod jest twoim płotem - ważne, żebyś umiał na niego spojrzeć i go zrozumieć. Zakres od *0.0* do *1.0* będzie ci stale towarzyszył. Opanujesz sztukę blendowania (pol. "mieszania", "łączenia") i kształtowania tej linii -This code is your fence; it's important to observe and understand it. You will come back over and over to this space between *0.0* and *1.0*. You will master the art of blending and shaping this line. -= + Tę wzajmnie jednoznaczną (ang. "one-to-one") funkcję między *x* i *y* (lub jasnością) nazywamy *interpolacją liniową*. Możemy użyć funkcji matematycznych by *uformować* tę linię. Przykładowo, możemy podnieść *x* do potęgi 5, aby utworzyć *krzywą* linię. @@ -28,15 +27,15 @@ Tę wzajmnie jednoznaczną (ang. "one-to-one") funkcję między *x* i *y* (lub j
-Ciekawe, prawda? W linijce 22 spróbuj użyć następujących wykładników: 20.0, 2.0, 1.0, 0.0, 0.2 czy 0.02. Zrozumienie związków między końcową wartością a wykładnikiem będzie bardzo porzydatne. Używanie tego typu funkcji matematycznych tu i tam da ci pełnię kontroli nad twoim kodem. +Ciekawe, prawda? W linijce 22 spróbuj użyć następujących wykładników: 20.0, 2.0, 1.0, 0.0, 0.2 lub 0.02. Zrozumienie związków między końcową wartością a wykładnikiem będzie bardzo przydatne. Używanie tego typu funkcji matematycznych tu i tam da ci pełnię kontroli nad twoim kodem. -[`pow()`](../glossary/?search=pow) są natywnymi funkcjami w GLSL. Większość z nich zaimplementowana jest na poziomie hardware'u, co oznacza, że odpowiednie ich użycie przypiszy twój kod. +[`pow()`](../glossary/?search=pow) to natywna funkcja w GLSL, więc zaimplementowana jest na poziomie hardware'u, co oznacza większą wydajność. -Zastąp funkcję potęgową w linijce 22 inną funkcją. Spróbuj [`exp()`](../glossary/?search=exp), [`log()`](../glossary/?search=log) i [`sqrt()`](../glossary/?search=sqrt). W wypadku funkcji trygonometrycznych warto użyć liczby PI. Jest ona zdefiniowana w 8 linijce za pomocą makra, który zastąpi każde użycie `PI` wartością `3.14159265359`. +Zastąp funkcję potęgową w linijce 22 inną natywną funkcją. Spróbuj [`exp()`](../glossary/?search=exp), [`log()`](../glossary/?search=log) i [`sqrt()`](../glossary/?search=sqrt). W wypadku funkcji trygonometrycznych warto użyć liczby PI. Jest ona zdefiniowana w 8 linijce za pomocą makra, który zastąpi każde użycie `PI` wartością `3.14159265359`. @@ -45,22 +44,21 @@ Zastąp funkcję potęgową w linijce 22 inną funkcją. Spróbuj [`exp()`](../g GLSL posiada też unikalne natywne funckje interpolacyjne wykorzystujące akcelerację sprzętową. -Funkcja [`step()`](../glossary/?search=step) otrzymuje dwa argumenty. Pierwszy z nich to limit lub próg, natomiast drugi to wartość, którą chcemy sprawdzić lub przekazać. Każda wartość poniżej limitu zwróci `0.0`, natomiast wszystko powyżej limitu zwróci `1.0`. +Funkcja [`step()`](../glossary/?search=step) otrzymuje dwa argumenty. Pierwszy z nich to limit lub próg, natomiast drugi to wartość, którą chcemy porównać z tym progiem. Każda wartość poniżej limitu zwróci `0.0`, natomiast wszystko powyżej limitu zwróci `1.0`. - Spróbuj zmienić tę wartość progową w linijce 20 poniższego kodu.
-Druga unikalna funkcja znana jest jako [`smoothstep()`](../glossary/?search=smoothstep) i otrzymuje trzy argumenty Dwa pierwsze argumenty służą do określenia początku i końca przejścia (interpolacji), natomiast trzeci jest wartością interpolowaną. +Druga unikalna funkcja znana jest jako [`smoothstep()`](../glossary/?search=smoothstep) i otrzymuje trzy argumenty Dwa pierwsze argumenty służą do określenia początku i końca interpolacji (tranzycji/przejścia), natomiast trzeci jest wartością interpolowaną.
-W poprzednim przykładzie, w linii 12, zauważ, że użyliśmy smoothstep wewnątrz funkcji `plot()` do narysowania zielonej linii. Dla każdej pozycji wzdłuż osi x funkcja ta zwraca odpowiednią wartość y. Jak? Poprzez połączenie ze sobą dwóch [`smoothstep()`](../glossary/?search=smoothstep). Spójrz na poniżśzy fragment kodu i wstaw go w linijce 20 powyższego przykładu; pomyśl, że dokonane została pionowe cięcie - tło wygląda jak linia, prawda? +W poprzednim przykładzie, w linii 12, zauważ, że użyliśmy smoothstep wewnątrz funkcji `plot()` do narysowania zielonej linii. Dla każdej pozycji wzdłuż osi x funkcja ta zwraca odpowiednią wartość y. Jak? Poprzez połączenie ze sobą dwóch [`smoothstep()`](../glossary/?search=smoothstep). Spójrz na poniżśzy fragment kodu (zauważ, że jest analogiczny do kodu w funkcji `plot()`) i wstaw go w linijce 20 powyższego przykładu. Wyobraź sobie, że widoczny wykres o kształcie dzwona (o kształcie rozkładu normalnego) "wędruje" wzdłuż funkcji przekazanej do argumentu `pct` funkcji `plot()`. @@ -74,13 +72,13 @@ Kiedy chcesz użyć matematyki do animacji, kształtowania lub blendowania warto -Te dwie podstawowe funkcje trygonometryczne współpracują ze sobą, aby skonstruować okręgi, które są tak poręczne jak szwajcarski scyzoryk MacGyvera. Warto wiedzieć, jak się zachowują i na jakie sposoby można je łączyć. W skrócie, przyjąwszy kąt (w radianach), zwrócą one współrzędne *x* ([cosinus](../glossary/?search=cos)) i *y* ([sinus](../glossary/?search=sin)) punktu na brzegu okręgu o promieniu równym 1. Jednak fakt, że zwracają one znormalizowane wartości (wartości pomiędzy -1 a 1) w tak gładki sposób, czyni z nich niesamowite narzędzie. +Te dwie podstawowe funkcje trygonometryczne współpracują ze sobą, aby skonstruować okręgi, które są tak poręczne jak szwajcarski scyzoryk MacGyvera. Warto wiedzieć, jak się zachowują i na jakie sposoby można je łączyć. W skrócie, otrzymawszy kąt (w radianach), zwrócą one współrzędne *x* ([cosinus](../glossary/?search=cos)) i *y* ([sinus](../glossary/?search=sin)) punktu na brzegu okręgu o promieniu równym 1. Jednak fakt, że zwracają one znormalizowane wartości (wartości pomiędzy -1 a 1) w tak płynny sposób, czyni z nich niesamowite narzędzie. ![](sincos.gif) -Choć trudno opisać wszystkie związki między funkcjami trygonometrycznymi i okręgami, powyższa animacja pięknie wizualizuje te związki. +Choć trudno opisać wszystkie związki między funkcjami trygonometrycznymi i okręgami, powyższa animacja pięknie je wizualizuje. @@ -158,17 +156,17 @@ Pod koniec ostatniego ćwiczenia wprowadziliśmy kilka nowych funkcji. Teraz cza ### Zaawansowane funkcje kształtujące -[Golan Levin](http://www.flong.com/) ma świetną dokumentację bardziej złożonych funkcji kształtujących, które są niezwykle pomocne. Samodzielene przeniesienie ich do GLSL jest dobrym krokiem w stronę budowania własnego zasobu snippetów kodu. +[Golan Levin](http://www.flong.com/) ma świetną dokumentację bardziej złożonych shaping functions, które są niezwykle pomocne. Samodzielene przeniesienie ich do GLSL jest dobrym krokiem w stronę budowania własnego zasobu snippetów kodu. -* Wielomianowe Funkcje Kształtujące: [www.flong.com/archive/texts/code/shapers_poly](http://www.flong.com/archive/texts/code/shapers_poly/) +* Wielomianowe shaping fucntions: [www.flong.com/archive/texts/code/shapers_poly](http://www.flong.com/archive/texts/code/shapers_poly/) -* Wykładnicze Funkcje Kształtujące: [www.flong.com/archive/texts/code/shapers_exp](http://www.flong.com/archive/texts/code/shapers_exp/) +* Wykładnicze shaping functions: [www.flong.com/archive/texts/code/shapers_exp](http://www.flong.com/archive/texts/code/shapers_exp/) -* Kołowe i Eliptyczne Funkcje Kształtujące: [www.flong.com/archive/texts/code/shapers_circ](http://www.flong.com/archive/texts/code/shapers_circ/) +* Kołowe i Eliptyczne shaping functions: [www.flong.com/archive/texts/code/shapers_circ](http://www.flong.com/archive/texts/code/shapers_circ/) -* Parametryczne (Beziera) Funkcje Kształtujące: [www.flong.com/archive/texts/code/shapers_bez](http://www.flong.com/archive/texts/code/shapers_bez/) +* Parametryczne (Beziera) shaping functions: [www.flong.com/archive/texts/code/shapers_bez](http://www.flong.com/archive/texts/code/shapers_bez/) -[Iñigo Quiles](http://www.iquilezles.org/) ma wspaniałą kolekcję [użytecznych funkcji](http://www.iquilezles.org/www/articles/functions/functions.htm). Po przeczytaniu [tego artykułu](http://www.iquilezles.org/www/articles/functions/functions.htm) spójrz na poniższe tłumaczenie tych funkcji na GLSL. Zwróć uwagę na wymagane małe zmiany, jak stawianie "." (kropki) na liczbach zmiennoprzecinkowych i używanie nazw GLSL dla funkcji *C*; na przykład zamiast `powf()` użyj `pow()`: +[Iñigo Quiles](http://www.iquilezles.org/) ma wspaniałą kolekcję [użytecznych funkcji](http://www.iquilezles.org/www/articles/functions/functions.htm). Po przeczytaniu [tego artykułu](http://www.iquilezles.org/www/articles/functions/functions.htm) spójrz na poniższe tłumaczenie tych funkcji na GLSL. Zwróć uwagę na małe zmiany, jak stawianie "." (kropki) przy liczbach zmiennoprzecinkowych i używanie nazw GLSL dla funkcji z *C* (na przykład zamiast `powf()` użyj `pow()`): -[Iñigo Quiles](http://www.iquilezles.org/) has a great collection of [useful functions](http://www.iquilezles.org/www/articles/functions/functions.htm). After reading [this article](http://www.iquilezles.org/www/articles/functions/functions.htm) take a look at the following translation of these functions to GLSL. Pay attention to the small changes required, like putting the "." (dot) on floating point numbers and using the GLSL name for *C functions*; for example instead of `powf()` use `pow()`: +
-To keep your motivation up, here is an elegant example (made by [Danguafer](https://www.shadertoy.com/user/Danguafer)) of mastering the shaping-functions karate. +Aby podtrzymać twoją motywację, oto elegancki przykład (wykonany przez [Danguafer](https://www.shadertoy.com/user/Danguafer)) ilustrujący opanowanie karate shaping functions. + + -In the *Next >>* chapter we will start using our new moves. First with mixing colors and then drawing shapes. +W następnym rozdziale zaczniemy używać naszych nowych sztuczek. Najpierw z mieszaniem kolorów, a potem z rysowaniem kształtów. + + + +#### Ćwiczenia -#### Exercise + -Take a look at the following table of equations made by [Kynd](http://www.kynd.info/log/). See how he is combining functions and their properties to control the values between 0.0 and 1.0. Now it's time for you to practice by replicating these functions. Remember the more you practice the better your karate will be. +Przyjrzyj się poniższej tabeli wzorów wykonanej przez [Kynd](http://www.kynd.info/log/). Zobacz jak łączy on funkcje i ich właściwości, aby kontrolować wartości pomiędzy 0.0 a 1.0. Teraz nadszedł czas, abyś poćwiczył, odtwarzając te funkcje. Pamiętaj im więcej będziesz ćwiczył tym lepsze będzie twoje karate. + + ![Kynd - www.flickr.com/photos/kynd/9546075099/ (2013)](kynd.png) -#### For your toolbox +#### Pomocne narzędzia + +Oto kilka narzędzi, które ułatwią ci wizualizację tego typu funkcji. + +* Grapher: jeśli masz komputer z systemem MacOS, wpisz `grapher` w swoim Spotlight, a będziesz mógł użyć tego super poręcznego narzędzia. + +![OS X Grapher (2004)](grapher.png) + +* [GraphToy](http://www.iquilezles.org/apps/graphtoy/): po raz kolejny [Iñigo Quilez](http://www.iquilezles.org) stworzył narzędzie do wizualizacji funkcji GLSL w WebGL. + +![Iñigo Quilez - GraphToy (2010)](graphtoy.png) + +* [Shadershop](http://tobyschachman.com/Shadershop/): to niesamowite narzędzie stworzone przez [Toby Schachman](http://tobyschachman.com/) nauczy cię jak konstruować złożone funkcje w niesamowicie wizualny i intuicyjny sposób. -Here are some tools that will make it easier for you to visualize these types of functions. + ![Toby Schachman - Shadershop (2014)](shadershop.png) From efbbe1c4243e44290475540f2f1a998632ddd834 Mon Sep 17 00:00:00 2001 From: Wojtek Date: Mon, 6 Mar 2023 14:40:49 +0100 Subject: [PATCH 20/23] 06 fix --- 06/README-pl.md | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/06/README-pl.md b/06/README-pl.md index 908493b..a9315e3 100644 --- a/06/README-pl.md +++ b/06/README-pl.md @@ -8,7 +8,7 @@ Zanim przejdziemy dalej, ważne jest żebyśmy dowiedzieli się o nich więcej, -Jeżeli paradgymat programowania obiektowego jest ci bliski, to prawdopodobnie zauważyłeś, że proces wyciągania danych z wektorów wygląda podobnie przy C-podobnych `struct`'ach. +Jeżeli paradgymat programowania obiektowego jest ci bliski, to prawdopodobnie zauważyłeś, że proces ekstrakcji danych z wektorów wygląda podobnie jak ekstracja danych z `struct`'ów w C. @@ -19,7 +19,7 @@ red.y = 0.0; red.z = 0.0; ``` -Definiowanie kolor za pomocą notacji *x*, *y* i *z* jest trochę mylące, prawda? Właśnie dlatego istnieją inne sposoby dostępu do tej samej informacji, ale za pomocą różncyh nazw. Wartości `.x`, `.y` i `.z` mogą być również uzyskane za pomocą `.r`, `.g` i `.b`, jak i `.s`, `.t` i `.p` (`.s`, `.t` i `.p` są zwykle używane przy współrzędnych tekstur, które zobaczymy w następnych rozdziałach). Możesz również uzyskać dane wektora za pomocą indeksów `[0]`, `[1]` i `[2]`. +Definiowanie kolor za pomocą notacji *x*, *y* i *z* jest trochę mylące, prawda? Właśnie dlatego istnieją inne sposoby dostępu do tej samej informacji, ale za pomocą innych nazw. Wartości `.x`, `.y` i `.z` mogą być również uzyskane za pomocą `.r`, `.g` i `.b`, jak i `.s`, `.t` i `.p` (`.s`, `.t` i `.p` są zwykle używane przy współrzędnych tekstur, które zobaczymy w następnych rozdziałach). Możesz również uzyskać dane wektora za pomocą indeksów `[0]`, `[1]` i `[2]`. @@ -35,7 +35,7 @@ vector[2] = vector.b = vector.z = vector.p; vector[3] = vector.a = vector.w = vector.q; ``` -Ta mnogość metod uzyskiwania tych samych danych jest tylko po to, aby ułatwić pisanie zrozumiałego kodu. Ta elastyczność wbudowana w język shadingowy stanowi też okazję, żebyś zaczął myśleć o współrzędnych koloru i przestrzeni jako zamiennych. +Ta mnogość metod uzyskiwania tych samych danych jest tylko po to, aby ułatwić pisanie zrozumiałego kodu. Ta elastyczność wbudowana w język shadingowy stanowi też okazję, żebyś zaczął myśleć o współrzędnych koloru i przestrzeni jako wzjamenie zastępowalnych. @@ -89,7 +89,7 @@ Pokaż na co cie stać: -* Stwórz ekspresywną tranzycje między kolorami. Pomyśl o konkretnej emocji. Jaki kolor najlepiej ją reprezentuje? Jak wygląda? Jak zanika? Pomyśl o innej emocji i pasującym do niej kolorze. Zmień `colorA` i `colorB` w kodzie powyżej, aby pasowały do tych emocji. Następnie zanimuj tę tranzycję za pomocą funkcji kształtujących. Robert Penner stworzył serię popularnych funkcji kształtujących, z zasotoswaniami w animacji komputerowej, zwanych [easing functions](http://easings.net/), skorzystaj z [tego przykładu](../edit.php#06/easing.frag) jako inspiracji, ale najlepsze rezultaty osiągniesz tworząc własne tranzycje. +* Stwórz ekspresywną tranzycje między kolorami. Pomyśl o konkretnej emocji. Jaki kolor najlepiej ją reprezentuje? Jak wygląda? Jak zanika? Pomyśl o innej emocji i pasującym do niej kolorze. Zmień `colorA` i `colorB` w kodzie powyżej, aby pasowały do tych emocji. Następnie zanimuj tę tranzycję za pomocą shaping function. Robert Penner stworzył serię popularnych shaping functions, z zasotoswaniami w animacji komputerowej, zwanych [easing functions](http://easings.net/), skorzystaj z [tego przykładu](../edit.php#06/easing.frag) jako inspiracji, jednak najlepsze rezultaty osiągniesz tworząc własne tranzycje. @@ -101,17 +101,17 @@ Funkcja [`mix()`](../glossary/?search=mix) ma więcej do zaoferowania. Zamiast p ![](mix-vec.jpg) -Spójrz na poniższy przykład. Tak jak w przykładach z poprzedniego rozdziału, podłączamy tranzycję do znormalizowanej współrzędnej `x` i wizualizujemy za pomocą linii. Aktualnie, wszystkie kanały leżą na tej samej linii. +Spójrz na poniższy przykład. Tak jak w przykładach z poprzedniego rozdziału, dzięki znormalizowanej współrzędnej `x` tworzymy gradient i wizualizujemy go za pomocą linii. Aktualnie, wszystkie kanały leżą na tej samej linii. -Odkomentuj linjkę 25 i zobacz, co się stanie. Następnie odkomentuj linijki 26 i 27. Pamiętaj, że linie wizualizują stosunek mieszania każdego z kanałów wektorów `colorA` i `colorB`. +Odkomentuj linjkę 25 i zobacz, co się stanie. Następnie odkomentuj linijki 26 i 27. Pamiętaj, że linie wizualizują, w jakim stosunku kanały (R, G, B) kolorów `colorA` i `colorB` są obecne w ostatecznym gradiencie.
-Prawdopodobnie rozpoznajesz trzy funkcje kształtującego, które używamy w linijkach 25 i 27. Baw się nimi! Czas pokazać swoje umiejętności z poprzednich rozdziałów, tworząc interesujące gradienty. Spróbuj następujących ćwiczeń: +Prawdopodobnie rozpoznajesz trzy shaping functions, które używamy w linijkach 25 i 27. Baw się nimi! Czas pokazać swoje umiejętności z poprzednich rozdziałów, tworząc interesujące gradienty. Spróbuj następujących ćwiczeń: ![William Turner - The Fighting Temeraire (1838)](turner.jpg) @@ -139,7 +139,7 @@ Prawdopodobnie rozpoznajesz trzy funkcje kształtującego, które używamy w lin Nie da się mówić o kolorze bez poruszenia tematu przestrzeni barw. Jak prawdopodobnie wiesz, istnieją też inne sposoby reprezentacji koloru poza RGB (z kanałem czerwonym, zielonym i niebieskim). -[HSB](http://en.wikipedia.org/wiki/HSL_and_HSV) oznacza Hue (pol. "barwa"), Saturation (pol. "nasycenie") i Brightness (pol. "jasność) i jest o wiele bardziej intuicyjną reprezentacją koloru niż RGB. Czasem zamiast Brightness używa sie Value, stąd zamiast HSB można spotkać się też z HSV. Przyjrzyj się funkcjom `rgb2hsv()` i `hsv2rgb()` w następującym kodzie: +[HSB](http://en.wikipedia.org/wiki/HSL_and_HSV) oznacza Hue (pol. "barwa"), Saturation (pol. "nasycenie") i Brightness (pol. "jasność) i jest o wiele bardziej intuicyjną reprezentacją koloru niż RGB. Czasem Brightness nazywany jest "Value", stąd zamiast HSB można spotkać się też ze skrótem HSV. Przyjrzyj się funkcjom `rgb2hsv()` i `hsv2rgb()` w następującym kodzie: @@ -153,11 +153,11 @@ Mapując pozycję na osi x do barwy i pozycję na osi y do jasności, otrzymujem ### HSB we współrzędnych biegunowych -Oryginalnie, HSB miało być reprezentowane z pomocą współrzędnych biegunowych (opartych na kącie i promieniu), a nie kartezjańskich (opartych na x i y). By zpamować naszą funkcję HSB do współrzędnych biegunowych, musimy otrzymać kąt i dystans wektora od centrum kanwy do współrzędnej piksela. W tym celu użyjemy funkcje [`length()`](../glossary/?search=length) i [`atan(y,x)`](../glossary/?search=atan) (który jest odpowiednikami `atan2(y,x)` w GLSL). +Oryginalnie, HSB miało być reprezentowane z pomocą współrzędnych biegunowych (opartych na kącie i promieniu), a nie kartezjańskich (opartych na x i y). By zmapować naszą funkcję HSB do współrzędnych biegunowych, musimy otrzymać kąt i dystans od centrum kanwy do współrzędnej piksela. W tym celu użyjemy funkcje [`length()`](../glossary/?search=length) i [`atan(y,x)`](../glossary/?search=atan) (który jest odpowiednikiem `atan2(y,x)` w GLSL). - +Pamiętaj: `vec2`, `vec3` i `vec4` traktowane są jak wektory nawet jeśli reprezentują kolor. Zaczniemy traktować kolory i wektory bardzo podobnie. @@ -165,7 +165,7 @@ Oryginalnie, HSB miało być reprezentowane z pomocą współrzędnych biegunowy -Gdy już zdobędziemy kąt i promień, musimy znormalizować ich wartości do zakresu od 0.0 do 1.0. W linijce 27, [`atan(y,x)`](../glossary/?search=atan) zwróci kąt w radianach między -PI a PI (-3.14 a 3.14), więc musimy podzielić tę liczbę przez `TWO_PI` (zdefiniowane na górze kodu), uzyskując wartości między -0.5 i 0.5, które, przez proste dodawanie, mapujemy dalej do zakresu od 0.0 do 1.0. Promień ma długość 0.5 (ponieważ liczymy odległość od środka TODO kanwy), więc musimy podwoić ten zakres (mnożąc przez 2), by uzyskać 1.0. +Gdy już zdobędziemy kąt i promień, musimy znormalizować ich wartości do zakresu od 0.0 do 1.0. W linijce 27, [`atan(y,x)`](../glossary/?search=atan) zwróci kąt w radianach między -PI a PI (-3.14 a 3.14), więc musimy podzielić tę liczbę przez `TWO_PI` (zdefiniowane na górze kodu), uzyskując wartości między -0.5 i 0.5, które, przez proste dodawanie, mapujemy dalej do zakresu od 0.0 do 1.0. Promień ma długość 0.5 (ponieważ liczymy odległość od środka kanwy), więc musimy podwoić ten zakres (mnożąc przez 2), by uzyskać 1.0. @@ -181,7 +181,7 @@ Spróuj poniższych ćwiczeń: * Zmodyfikuj przykład ze współrzędnymi biegunowymi, aby uzyskać kręcące się (jak w ikonce czekania myszki) koło barw. -* Użyj funkcji kształtującej razem z funkcją konwersji z HSB do RGB, aby rozszerzyć jedną barwę i zwężyć inną. +* Użyj shaping function razem z funkcją konwersji z HSB do RGB, aby rozszerzyć jedną barwę i zwężyć inną. @@ -204,7 +204,7 @@ Spróuj poniższych ćwiczeń: #### Uwaga o funkcjach i ich argumentach -Zanim przeskoczysz do następnego rozdziału, zatrzymajmy się na chwilę. Wróć do funkcji `hsb2rgb` z poprzedniego interaktywnego przykładu. Zauważysz `in` przed typem argumentu. Jest to [*kwalifikator*](http://www.shaderific.com/glsl-qualifiers/#inputqualifier) (ang. "qualifier") i akurat ten oznacza, że zmienna jest tylko do odczytu. W przyszłości zobaczymy, że jest również możliwe, by poprzedzić argumenty kwalifikatorami `out` i `inout`. `out` określa, że argument jest tylko do zapisu, natomiast `inout` działa podobnie jak przekazywanie argumentu przez referencje, co umożliwia modyfikowanie go. +Zanim przeskoczysz do następnego rozdziału, zatrzymajmy się na chwilę. Wróć do funkcji `hsb2rgb` z poprzedniego interaktywnego przykładu. Zauważysz `in` przed typem argumentu. Jest to [*kwalifikator*](http://www.shaderific.com/glsl-qualifiers/#inputqualifier) (ang. "qualifier") i akurat ten oznacza, że zmienna jest tylko do odczytu. W przyszłości zobaczymy, że jest również możliwe, by poprzedzić argumenty kwalifikatorami `out` i `inout`. Kwalifikator `out` określa, że argument jest tylko do zapisu (ang. "write-only"), natomiast `inout` działa podobnie jak przekazywanie argumentu przez referencje, co umożliwia również modyfikowanie go. @@ -214,6 +214,6 @@ int newFunction(in vec4 aVec4, // read-only inout int aInt); // read-write ``` -Może w to nie uwierzysz, ale mamy wszystkie składniki potrzbne do tworzenia fajnych rysunków. W następnym rozdziale nauczymy się jak połączyć wszystkie poznane tricki, by stworzyć geometryczne formy przez *blendowanie* przestrzeni. Dobrze słyszysz... *blendowanie* przestrzeni. +Może w to nie uwierzysz, ale mamy wszystkie składniki potrzbne do tworzenia fajnych rysunków. W następnym rozdziale nauczymy się jak połączyć wszystkie poznane tricki, by stworzyć geometryczne formy/kształty przez *blendowanie* przestrzeni. Dobrze słyszysz... *blendowanie* przestrzeni. From a2eef2c65cf22e7fad23916ae7019fda6c3bc8a0 Mon Sep 17 00:00:00 2001 From: Wojtek Date: Fri, 10 Mar 2023 16:11:29 +0100 Subject: [PATCH 21/23] 07-10 --- 07/README-pl.md | 40 +++++++++++++++++++--------------------- 08/README-pl.md | 12 ++++++------ 09/README-pl.md | 4 ++-- 10/README-pl.md | 12 ++++++------ 4 files changed, 33 insertions(+), 35 deletions(-) diff --git a/07/README-pl.md b/07/README-pl.md index 00f621d..384f95a 100644 --- a/07/README-pl.md +++ b/07/README-pl.md @@ -2,13 +2,13 @@ ## Kształty -Nareszcie! Czekaliśmy na ten moment! Poznałeś większość podstaw GLSL, jego typów i funkcji. Ćwiczyłeś również wykorzystanie funkcji kształtujących. Teraz nadszedł czas, aby połączyć to wszystko w całość. Jesteś w stanie sprostać temu wyzwaniu! W tym rozdziale dowiesz się, jak procedrualnie i równolegle rysować proste kształty. +Nareszcie! Czekaliśmy na ten moment! Poznałeś większość podstaw GLSL, jego typów i funkcji. Ćwiczyłeś również wykorzystanie shaping functions. Teraz nadszedł czas, aby połączyć to wszystko w całość. Jesteś w stanie sprostać temu wyzwaniu! W tym rozdziale dowiesz się, jak procedrualnie i równolegle rysować proste kształty. ### Prostokąt -Wyobraźmy sobie, że mamy papier w kratkę, taki jaki używaliśmy na lekcjach matematyki i naszym zadaniem domowym jest narysowanie kwadratu. Rozmiar papieru to 10x10, a kwadrat ma mieć wymiary 8x8. Co zrobisz? +Wyobraźmy sobie, że mamy papier w kratkę, taki jaki używaliśmy na lekcjach matematyki i naszym zadaniem domowym jest narysowanie kwadratu. Kartka papieru jest w wymiarach 10x10, a kwadrat w 8x8. Co zrobisz? @@ -18,11 +18,11 @@ Zamalowałbyś wszystko poza pierwszym i ostatnim rzędem oraz pierwszą i ostat -Jak to się ma do shaderów? Każdy mały kwadracik naszego papieru siatkowego to wątek (piksel). Każdy mały kwadrat zna swoje położenie, podobne do współrzędnych na szachownicy. W poprzednich rozdziałach zmapowaliśmy *x* i *y* na kanały kolorów *czerwony* i *zielony* oraz nauczyliśmy się korzystać z ciasnego dwuwymiarowego terytorium pomiędzy 0.0 a 1.0. Jak możemy tę wiedzę wykorzystać, aby narysować wyśrodkowany kwadrat na środku naszej kanwy? +Jak to się ma do shaderów? Każdy mały kwadracik naszej kartki papieru to wątek (piksel). Każdy mały kwadrat zna swoje położenie, podobne do współrzędnych na szachownicy. W poprzednich rozdziałach zmapowaliśmy *x* i *y* na kanały kolorów *czerwony* i *zielony* oraz nauczyliśmy się korzystać z ciasnego dwuwymiarowego terytorium pomiędzy 0.0 a 1.0. Jak możemy tę wiedzę wykorzystać, aby narysować wyśrodkowany kwadrat na środku naszej kanwy? -Zacznijmy od naszkicowania pseudokodu, który używa `if`ów na współrzędnych kanwy. Zasady, aby to zrobić, są nadzwyczaj podobne do tego, jak myślimy o sytuacji z papieram w kratke. +Zacznijmy od naszkicowania pseudokodu, który używa `if`ów na współrzędnych kanwy. Idea jest podobna jak w przypadku z papieram w kratke. @@ -33,7 +33,7 @@ else pomaluj na czarno ``` -Teraz, gdy mamy lepsze wyobrażenie o tym, jak to będzie działać, zastąpmy `if`a funkcją [`step()`](../glossary/?search=step), a zamiast używać współrzędnych 10x10 użyjmy znormalizowanych odpowiedników pomiędzy 0.0 a 1.0: +Teraz, gdy mamy lepsze wyobrażenie o tym, jak to będzie działać, zastąpimy `if`a funkcją [`step()`](../glossary/?search=step), a zamiast używać siatki 10x10 użyjmy znormalizowanych odpowiedników pomiędzy 0.0 a 1.0: @@ -92,7 +92,7 @@ vec2 tr = step(vec2(0.1),1.0-st); // top-right color = vec3(bl.x * bl.y * tr.x * tr.y); ``` -Ciekawe, prawda? W tej technice chodzi o wykorzystanie [`step()`](../glossary/?search=step), przerzucania współrzędnych oraz mnożenia (do operacji logicznych). +Ciekawe, prawda? W tej technice chodzi o wykorzystanie [`step()`](../glossary/?search=step), odwracania (ang. "flip") współrzędnych oraz mnożenia (jako operację logiczną AND). @@ -102,7 +102,7 @@ Zanim przejdziesz dalej, spróbuj wykonać następujące ćwiczenia: * Użyj [`smoothstep()`](../glossary/?search=smoothstep) zamiast [`step()`](../glossary/?search=step). Zauważ, że zmieniając wartości, możesz przejść od rozmytych krawędzi do eleganckich gładkich granic. -* Zaimplementuj to samo, ale za pomocą [`floor()`](../glossary/?search=floor)(+ mnożenia i dzielenia). +* Zaimplementuj to samo, ale za pomocą [`floor()`](../glossary/?search=floor) (+ mnożenie i dzielenie). * Wybierz implementację, którą najbardziej lubisz i zrób z niej funkcję, którą możesz ponownie wykorzystać w przyszłości. Spraw, aby twoja funkcja była elastyczna i wydajna. @@ -130,7 +130,7 @@ Zanim przejdziesz dalej, spróbuj wykonać następujące ćwiczenia: Łatwo jest rysować kwadraty na papierze w kratkę i prostokąty na współrzędnych kartezjańskich, ale okręgi wymagają innego podejścia, zwłaszcza że potrzebujemy algorytmu działającego na każdym pikselu z osobna. Jednym z rozwiązań jest *zmapowanie* współrzędnych tak, abyśmy mogli użyć funkcji [`step()`](../glossary/?search=step) do narysowania okręgu. -Jak to zrobić? Przypomnijmy sobie lekcje matematyki, gdzie rozpościeraliśmy ramiona cyrkla na promień okręgu, wciskaliśmy jedno ramię cyrkla w środek okręgu, a następnie obrysowywaliśmy krawędź okręgu obracając drugie ramię. +Jak to zrobić? Przypomnijmy sobie lekcje matematyki, gdzie rozpościeraliśmy ramiona cyrkla na długość promienia okręgu, wciskaliśmy jedno ramię cyrkla w środek okręgu, a następnie obrysowywaliśmy krawędź okręgu obracając drugie ramię. -Komentuj i odkomentuj linijki, aby wypróbować różne sposoby uzyskania tego samego wyniku. +Zakomentuj i odkomentuj linijki, aby wypróbować różne sposoby uzyskania tego samego wyniku. @@ -176,7 +176,7 @@ W powyższym przykładzie mapujemy odległość do centrum kanwy na jasność pi * Modify the above code in order to contain the entire circular gradient inside the canvas. --> -### Distance field +### Pole odległości Możemy również myśleć o powyższym przykładzie jako o mapie wysokości, gdzie im ciemniej tym wyżej. Gradient pokazuje nam coś podobnego do wzoru tworzonego przez stożek. Wyobraź sobie, że jesteś na szczycie tego stożka. Pozioma odległość do krawędzi stożka wynosi 0.5. Będzie ona stała we wszystkich kierunkach. Wybierając miejsce "przecięcia" stożka otrzymamy większą lub mniejszą powierzchnię kołową. @@ -245,9 +245,9 @@ Pod względem mocy obliczeniowej funkcja [`sqrt()`](../glossary/?search=sqrt) -
-### Przydatne własności Pól Odległości +### Przydatne własności pól odległości -![ogórd Zen](zen-garden.jpg) +![ogród Zen](zen-garden.jpg) Pola odległości mogą być używane do rysowania prawie wszystkiego. Oczywiście im bardziej złożony jest kształt, tym bardziej skomplikowane będzie jego równanie, ale gdy już masz formułę do tworzenia pól odległości danego kształtu, bardzo łatwo jest połączyć i/lub zastosować do niego efekty, takie jak gładkie krawędzie i wiele konturów. Z tego powodu, pola odległości są popularne w renderowaniu czcionek, takich jak [Mapbox GL Labels](https://blog.mapbox.com/drawing-text-with-signed-distance-fields-in-mapbox-gl-b0933af6f817), [Matt DesLauriers](https://twitter.com/mattdesl) [Material Design Fonts](http://mattdesl.svbtle.com/material-design-on-the-gpu) i [jak to jest opisane w rozdziale 7 iPhone 3D Programming, O'Reilly](http://chimera.labs.oreilly.com/books/1234000001814/ch07.html#ch07_id36000921). @@ -271,7 +271,7 @@ Jeśli odkomentujesz *linijkę 20*, zauważysz, że łączymy odległości do ty Spróbuj teraz odkomentować *linijkę 21*; robimy to samo, ale używamy funkcji [`max()`](../glossary/?search=max). Rezultatem jest prostokąt z zaokrąglonymi rogami. Zauważ, jak pierścienie pola odległości stają się gładsze, im bardziej oddalają się od środka. -Dokończ odkomentowywanie *linijek 27 do 29* jedna po drugiej, aby zrozumieć różne zastosowania wzorca pola odległości. +Dokończ odkomentowywanie *linijek 27 do 29* jedna po drugiej, aby zrozumieć różne zastosowania pól odległości. * Zanimować te kształty -* Połącz różne funkcje kształtujące by *zrobić dziury* w kształtach, aby powstały kwiaty, płatki śniegu i zębatki. -* Użyj funkcji `plot()` z rodziału *Funkcje kształtujące* i narysuj sam kontur (bez wypełnienia) +* Połącz różne shaping functions by *zrobić dziury* w kształtach, aby powstały kwiaty, płatki śniegu i zębatki. +* Użyj funkcji `plot()` z rodziału *Shaping functions* i narysuj sam kontur (bez wypełnienia) -### Combining powers - -### Łączenie +### Łącząc siły Teraz gdy wiemy, jak zmieniać promień koła w zależności od kąta z użyciem [`atan()`](../glossary/?search=atan), możemy spróbować połączyć `atan()` z polami odległości. -Trik polega na wykorzystanie liczby krawędzi wielokąta, by skonstruować pole odległości z użyciem współrzędnych polarnych. Sprawdź [następujący kod](http://thndl.com/square-shaped-shaders.html) od [Andrew Baldwin](https://twitter.com/baldand). +Trik polega na wykorzystaniu liczby krawędzi wielokąta, by skonstruować pole odległości z użyciem współrzędnych polarnych. Sprawdź [następujący kod](http://thndl.com/square-shaped-shaders.html) od [Andrew Baldwin](https://twitter.com/baldand). @@ -350,7 +348,7 @@ Trik polega na wykorzystanie liczby krawędzi wielokąta, by skonstruować pole -Gratulacje! Udało ci się przebrnąć przez trudny materiał! Odpocznij i pozwól - choć rysowanie prostych kształtów jest proste w Processing, to tutaj już nie. W świecie shaderów rysowanie kształtów jest zawiłe; przestawienie się na ten nowy sposób programowania może być męczące. +Gratulacje! Udało ci się przebrnąć przez bardzo trudny materiał! Choć rysowanie prostych kształtów w Processing jest proste, to tutaj już nie. W świecie shaderów rysowanie kształtów jest zawiłe; przestawienie się na ten nowy sposób programowania może być męczące. diff --git a/08/README-pl.md b/08/README-pl.md index 7e62cce..b52a86f 100644 --- a/08/README-pl.md +++ b/08/README-pl.md @@ -4,7 +4,7 @@ ### Translacja -W poprzednim rozdziale dowiedzieliśmy się, jak tworzyć różne kształty - sztuczka z przesuwaniem tych kształtów polega na przesuwaniu samego układu współrzędnych. Możemy to osiągnąć poprzez proste dodanie wektora do zmiennej ``st``, zawierającej położenie każdego fragmentu. Powoduje to przesunięcie całego układu współrzędnych. +W poprzednim rozdziale dowiedzieliśmy się, jak tworzyć różne kształty. Przesuwanie tych kształtów polega na przesuwaniu samego układu współrzędnych. Możemy to osiągnąć poprzez proste dodanie wektora do zmiennej ``st``, zawierającej położenie każdego fragmentu. Powoduje to przesunięcie całego układu współrzędnych. @@ -22,15 +22,15 @@ W poprzednim rozdziale dowiedzieliśmy się, jak tworzyć różne kształty - sz Spróbuj teraz wykonać następujące ćwiczenie: -* Używając ``u_time`` wraz z funkcjami kształtującymi poruszaj małym krzyżem w ciekawy sposób. Poszukaj interesującego cię ruchu i spróbuj sprawić, by krzyż poruszał się w ten sam sposób. Przydatne może być nagranie najpierw czegoś z "prawdziwego świata" - może to być przypływ i odpływ fal, ruch wahadła, odbijająca się piłka, przyspieszający samochód, zatrzymujący się rower. +* Używając ``u_time`` wraz z shaping functions poruszaj małym krzyżem w ciekawy sposób. Poszukaj interesującego cię ruchu i spróbuj sprawić, by krzyż poruszał się w ten sam sposób. Przydatne może być nagranie najpierw czegoś z "prawdziwego świata" - może to być przypływ i odpływ fal, ruch wahadła, odbijająca się piłka, przyspieszający samochód, zatrzymujący się rower. ### Rotacja -Aby obracać obiekty musimy również poruszać całym układem przestrzennym. Do tego celu będziemy używać [macierzy](http://en.wikipedia.org/wiki/Matrix_%28mathematics%29). Macierz to uporządkowany zbiór liczb w kolumnach i wierszach. Wektory są mnożone przez macierze według ściśle określonych reguł w celu zmodyfikowania wartości wektora w określony sposób. +Aby obracać obiekty również musimy poruszać całym układem przestrzennym. Do tego celu będziemy używać [macierzy](http://en.wikipedia.org/wiki/Matrix_%28mathematics%29). Macierz to uporządkowany zbiór liczb w kolumnach i wierszach. Wektory są mnożone przez macierze według ściśle określonych reguł w celu zmodyfikowania wartości wektora w określony sposób. [![wpis Wikipedii dotyczący macierzy](matrixes.png)](https://en.wikipedia.org/wiki/Matrix) -GLSL posiada natywne wsparcie dla dwu, trzy i czterowymiarowych macierzy: [``mat2``](../glossary/?search=mat2) (2x2), [``mat3``](../glossary/?search=mat3) (3x3) i [``mat4``](../glossary/?search=mat4) (4x4). GLSL obsługuje również mnożenie macierzy (``*``) oraz funkcję specyficzną dla macierzy ([``matrixCompMult()``](../glossary/?search=matrixCompMult)). +GLSL posiada natywne wsparcie dla dwu, trzy i czterowymiarowych macierzy: [``mat2``](../glossary/?search=mat2) (2x2), [``mat3``](../glossary/?search=mat3) (3x3) i [``mat4``](../glossary/?search=mat4) (4x4). GLSL obsługuje również mnożenie macierzy (``*``) oraz specyficzną dla macierzy funkcję [``matrixCompMult()``](../glossary/?search=matrixCompMult). Na podstawie tego, jak zachowują się macierze, możliwe jest skonstruowanie macierzy w celu wytworzenia określonych zachowań. Na przykład możemy użyć macierzy do translacji wektora: @@ -85,7 +85,7 @@ Spróbuj wykonać następujące ćwiczenia: * Zakomentuj translacje przed i po rotacji, w liniach 37 i 39, i zaobserwuj konsekwencje. -* Użyj rotacji, aby poprawić ruch, który zasymulowałeś w ćwiczeniu z podrozdziału "Translcją". +* Użyj rotacji, aby poprawić ruch, który zasymulowałeś w ćwiczeniu z podrozdziału "Translcja". ### Skalowanie @@ -120,7 +120,7 @@ mat2 scale(vec2 _scale){ Spróbuj następujących ćwiczeń, aby głębiej zrozumieć, jak to działa. -* Odkomentuj linię 42 powyższego kodu, aby zobaczyć skalowaną współrzędną przestrzeni. +* Odkomentuj linię 42 powyższego kodu, aby zobaczyć skalowanie współrzędnych przestrzeni. * Zobacz, co się stanie, gdy zakomentujesz translacje przed i po skalowaniu w liniach 37 i 39. diff --git a/09/README-pl.md b/09/README-pl.md index 62a08e2..584bd3c 100644 --- a/09/README-pl.md +++ b/09/README-pl.md @@ -4,9 +4,9 @@ Ponieważ shadery wykonywane są piksel po pikselu, więc niezależnie od tego, [ ![Nina Warmerdam - The IMPRINT Project (2013)](warmerdam.jpg) ](../edit.php#09/dots5.frag) -W tym rozdziale zamierzamy zastosować to, czego nauczyliśmy się do tej pory, ale powtarzając to wzdłuż kanwy. Podobnie jak w poprzednich rozdziałach, nasza strategia będzie opierała się na mnożeniu współrzędnych przestrzeni (z przedziału 0.0 a 1.0), dzięki czemu kształty, które narysujemy pomiędzy wartościami 0.0 a 1.0, będą się powtarzać, tworząc siatkę. +W tym rozdziale zamierzamy zastosować to, czego nauczyliśmy się do tej pory, dodając powtarzalność. Podobnie jak w poprzednich rozdziałach, nasza strategia będzie opierała się na mnożeniu współrzędnych przestrzeni (z przedziału 0.0 a 1.0), dzięki czemu kształty, które narysujemy pomiędzy wartościami 0.0 a 1.0, będą się powtarzać, tworząc siatkę. -*Siatka zapewnia ramy, w których może działać ludzka intuicja i inwencja, i które może obalić. W chaosie natury wzory zapewniają kontrast i obietnicę porządku. Od wczesnych wzorów na ceramice do geometrycznych mozaik w rzymskich łaźniach, ludzie od dawna używali siatek, by wzbogacić swoje życie o dekoracje. "* [*10 PRINT*, Mit Press, (2013)](http://10print.org/) +*Siatka* (ang. "grid") *zapewnia ramy, w których może działać ludzka intuicja i inwencja, i które może obalić. W chaosie natury wzory zapewniają kontrast i obietnicę porządku. Od wczesnych wzorów na ceramice do geometrycznych mozaik w rzymskich łaźniach, ludzie od dawna używali siatek, by wzbogacić swoje życie o dekoracje. "* [*10 PRINT*, Mit Press, (2013)](http://10print.org/) Najpierw przypomnijmy sobie funkcję [``fract()``](../glossary/?search=fract). Zwraca ona część ułamkową liczby, dzięki czemu ``fract()`` to w istocie funkcja modulo jeden ([``mod(x,1.0)``](../glossary/?search=mod)). Innymi słowy, [``fract()``](../glossary/?search=fract) zwraca liczbę po przecinku. Nasza zmienna znormalizowanego układu współrzędnych (``st``) już znajduje sie w zakresie od 0.0 do 1.0, więc nie ma sensu robić czegoś takiego jak: diff --git a/10/README-pl.md b/10/README-pl.md index f6d98a1..26fa5a0 100644 --- a/10/README-pl.md +++ b/10/README-pl.md @@ -16,9 +16,9 @@ Let's start by analyzing the following function: -->
-Powyżej wyodrębniamy zawartość ułamkową sinusoidy. Wartości [``sin()``](../glossary/?search=sin), które oscylują pomiędzy ``-1.0`` a ``1.0`` zostały posiekane, zwracając wszystkie dodatnie wartości pomiędzy ``0.0`` a ``1.0``. Możemy wykorzystać ten efekt do uzyskania pseudolosowych wartości. W jaki sposób? Mnożąc wypadkową [``sin(x)``](../glossary/?search=sin) przez większe liczby. Śmiało, zmodyfikuj powyższą funkcję, dodając zera do `1.0`. +Powyżej wyodrębniamy zawartość ułamkową sinusoidy. Wartości [``sin()``](../glossary/?search=sin), które oscylują pomiędzy ``-1.0`` a ``1.0`` zostały posiekane, i sprowadzone do zakresu pomiędzy ``0.0`` a ``1.0``. Możemy wykorzystać ten efekt do uzyskania pseudolosowych wartości. W jaki sposób? Mnożąc wypadkową [``sin(x)``](../glossary/?search=sin) przez większe liczby. Śmiało, zmodyfikuj powyższą funkcję, dodając zera do `1.0`. -Do czasu, gdy dojdziesz do ``100000.0`` (i równanie będzie wyglądało tak: ``y = fract(sin(x)*100000.0)`` ) nie jesteś już w stanie odróżnić sinusoidy. Ziarnistość części ułamkowej zepsuła falę sinusoidy w pseudolosowy chaos. +Do czasu, gdy dojdziesz do ``100000.0`` (i równanie będzie wyglądało tak: ``y = fract(sin(x)*100000.0)`` ) nie jesteś już w stanie dostrzec sinusoidę. Ziarnistość części ułamkowej zepsuła falę sinusoidy w pseudolosowy chaos.
-W tych liniach robimy coś podobnego do tego, co robiliśmy w poprzednim rozdziale. Dzielimy ciągłą liczbę zmiennoprzecinkową (``x``) na jej składowe całkowitą (``i``) i ułamkową (``f``). Używamy [``floor()``](../glossary/?search=floor) aby uzyskać ``i`` oraz [``fract()``](../glossary/?search=fract) aby uzyskać ``f```. Następnie stosujemy ``rand()`` do części całkowitej ``x``, co daje unikalną wartość losową dla każdej liczby całkowitej. +W tych liniach robimy coś podobnego do tego, co robiliśmy w poprzednim rozdziale. Dzielimy ciągłą liczbę zmiennoprzecinkową (``x``) na jej składowe całkowitą (``i``) i ułamkową (``f``). Używamy [``floor()``](../glossary/?search=floor) aby uzyskać ``i`` oraz [``fract()``](../glossary/?search=fract) aby uzyskać ``f``. Następnie stosujemy ``rand()`` do części całkowitej ``x``, co daje unikalną wartość losową dla każdej liczby całkowitej. Spójrz na dwie skomentowane linie. Pierwsza z nich interpoluje liniowo każdą wartość losową. @@ -303,7 +303,7 @@ W poniższym kodzie możesz odkomentować linię 44, aby zobaczyć jak siatka je -Wszystkie te ulepszenia skutkują algorytmicznym arcydziełem, jakim jest **Simplex Noise**. Poniżej znajduje się implementacja GLSL tego algorytmu wykonana przez Iana McEwana i Stefana Gustavsona (i przedstawiona w [tym artykule](http://webstaff.itn.liu.se/~stegu/jgt2012/article.pdf)), która jest nadmiernie skomplikowana w celach edukacyjnych, ale przekonasz się, że jest mniej enigmatyczna niż można by się spodziewać, a kod jest krótki i szybki. +Wszystkie te ulepszenia skutkują algorytmicznym arcydziełem, jakim jest **Simplex Noise**. Poniżej znajduje się implementacja GLSL tego algorytmu wykonana przez Iana McEwana i Stefana Gustavsona (i przedstawiona w [tym artykule](http://webstaff.itn.liu.se/~stegu/jgt2012/article.pdf)), która w celach edukacyjnych jest nadmiernie skomplikowana , ale przekonasz się, że jest też mniej enigmatyczna niż można by się spodziewać, a kod jest krótki i szybki. [ ![Ian McEwan of Ashima Arts - Simplex Noise](simplex-noise.png) ](../edit.php#11/2d-snoise-clear.frag) @@ -327,7 +327,7 @@ Cóż... dość technicznych rozważań, czas na wykorzystanie tego narzędzia w -W tym rozdziale wprowadziliśmy pewną kontrolę nad chaosem. Nie była to łatwa praca! Stanie się zaklinaczem chaosu wymaga czasu i wysiłku. +W tym rozdziale wprowadziliśmy pewną kontrolę nad chaosem. Nie była to łatwa praca! Zostanie zaklinaczem chaosu wymaga czasu i wysiłku. W następnych rozdziałach zobaczymy kilka dobrze znanych technik, które pozwolą ci udoskonalić swoje umiejętności i wydobyć więcej z szumu, aby zaprojektować wysokiej jakości generatywne dzieła za pomocą shaderów. Do tego czasu ciesz się czasem na zewnątrz, kontemplując naturę i jej zawiłe wzory. Twoja umiejętność obserwacji wymaga równego (a może nawet większego) poświęcenia niż twoje umiejętności tworzenia. Wyjdź na zewnątrz i ciesz się resztą dnia! diff --git a/12/README-pl.md b/12/README-pl.md index 627720e..beae7b5 100644 --- a/12/README-pl.md +++ b/12/README-pl.md @@ -205,7 +205,7 @@ Eksploruj tę ideę dalej: - What other ways of constructing this distance field can you imagine, besides ```m_dist = min(m_dist, dist);```? - What interesting patterns can you make with this distance field? --> -Algorytm ten można również interpretować z perspektywy punktów, a nie bieżących pikseli. W takim przypadku można go opisać jako: każdy punkt rośnie, dopóki nie znajdzie rosnącego obszaru innego punktu. Odzwierciedla to niektóre z zasad wzrostu w naturze. Żywe formy są kształtowane są przez napięcie między wewnętrzną siłą do rozszerzania się i wzrostu oraz zewnętrznymi siłami ograniczającymi. Klasyczny algorytm symulujący to zachowanie nazwany został za [Georgy Voronoi](https://en.wikipedia.org/wiki/Georgy_Voronoy). +Algorytm ten można również interpretować z perspektywy punktów, a nie bieżących pikseli. W takim przypadku można go opisać jako: każdy punkt rośnie, dopóki nie znajdzie rosnącego obszaru innego punktu. Odzwierciedla to niektóre z zasad wzrostu w naturze. Żywe formy kształtowane są przez napięcie między wewnętrzną siłą do rozszerzania się i wzrostu oraz zewnętrznymi siłami ograniczającymi. Klasyczny algorytm symulujący to zachowanie nazwany został za [Georgy Voronoi](https://en.wikipedia.org/wiki/Georgy_Voronoy). @@ -213,7 +213,7 @@ Algorytm ten można również interpretować z perspektywy punktów, a nie bież ### Algorytm Voronoi -Konstruowanie diagramów Voronoi z szumu komórkowego jest mniej trudne niż mogłoby się wydawać. Musimy tylko *zachować* pewną dodatkową informację o punkcie, który jest najbliżej bieżącego piksela. Do tego celu użyjemy ``vec2`` o nazwie ``m_point`` (z ang. "minimal point"). Przechowując wektor od bieżącego piksela do najbliższego punktu, zamiast tylko odległości, będziemy "przechowywać" "unikalny" identyfikator tego punktu. +Konstruowanie diagramów Voronoi z szumu komórkowego jest mniej trudne niż mogłoby się wydawać. Musimy tylko *zachować* pewną dodatkową informację o punkcie, który jest najbliżej bieżącego piksela. Do tego celu użyjemy ``vec2`` o nazwie ``m_point`` (z ang. "minimal point"). Przechowując wektor od bieżącego piksela do najbliższego punktu (zamiast samej odległości) będziemy "przechowywać" "unikalny" identyfikator tego punktu. @@ -234,7 +234,7 @@ Zauważ, że w poniższym kodzie nie używamy już ``min`` do obliczania najbli Zauważ, jak kolor ruchomej komórki (związanej z pozycją myszy) zmienia kolor w zależności od jej położenia. To dlatego, że kolor jest przypisywany przy użyciu wartości (pozycji) najbliższego punktu. -Podnieśmy poprzeczkę, przechodząc na podejście z [artykułu Stevena Worleya](http://www.rhythmiccanvas.com/research/papers/worley.pdf). Spróbuj zaimplementować to samodzielnie. Możesz skorzystać z pomocy poniższego przykładu, klikając na niego. Zauważ, że oryginalne podejście Stevena Worleya używa zmiennej liczby punktów dla każdego kafla, więcej niż jeden w większości kafli. W jego nie-shaderowej implementacji w C, jest to używane do przyspieszenia pętli poprzez wczesne wychodzenie. Pętle GLSL nie pozwalają na zmienną liczbę iteracji, więc prawdopodobnie chcesz trzymać się jednego punktu na kafelek. +Podnieśmy poprzeczkę, przechodząc na podejście z [artykułu Stevena Worleya](http://www.rhythmiccanvas.com/research/papers/worley.pdf). Spróbuj zaimplementować to samodzielnie. Możesz skorzystać z pomocy poniższego przykładu, klikając na niego. Zauważ, że oryginalne podejście Stevena Worleya używa zmiennej liczby punktów dla każdego kafla, więcej niż jeden w większości kafli. W tej jego nie-shaderowej implementacji (bo w C, a nie w GLSL) pomaga to przyspieszyć pętlę poprzez wczesne jej opuszczanie. Pętle GLSL nie pozwalają na zmienną liczbę iteracji, więc prawdopodobnie chcesz trzymać się jednego punktu na kafelek. -Eksperymenty Inigo z Voronoi nie skończyły się na tym. W 2014 roku napisał artykuł o tym, co nazywa [voro-noise](http://www.iquilezles.org/www/articles/voronoise/voronoise.htm). Jest to funkcja, która pozwala na stopniowe mieszanie między zwykłym szumem a Voronoi. Jego słowami: +Eksperymenty Inigo z Voronoi nie skończyły się na tym. W 2014 roku napisał artykuł o tym, co nazywa [voro-noise](http://www.iquilezles.org/www/articles/voronoise/voronoise.htm). Jest to funkcja, która pozwala na stopniowe interpolowanie między zwykłym szumem a Voronoi. Jego słowami: -*"Pomimo tego podobieństwa, faktem jest, że sposób użycia kafelkowania w obu metodach jest inny. Szum interpoluje/uśrednia wartości losowe (jak w Value Noise) lub gradienty (jak w Gradient Noise), podczas gdy Voronoi oblicza odległość do najbliższego punktu w kafelku. Teraz, interpolacja dwuliniowa (ang. "bilinear") i wartość minimalna to dwie bardzo różne operacje, ale czy na pewno? Czy można je połączyć w bardziej ogólną metrykę? Gdyby tak było, to zarówno szum jak i Voronoi mogłyby być postrzegane jako szczególne przypadki bardziej ogólnego generatora wzorów kafelkowych?"*. +*"Pomimo tego podobieństwa, faktem jest, że sposób użycia kafelkowania w obu metodach jest inny. Szum interpoluje/uśrednia wartości losowe (jak w Value Noise) lub gradienty (jak w Gradient Noise), podczas gdy Voronoi oblicza odległość do najbliższego punktu w kafelku. Interpolacja dwuliniowa* (ang. "bilinear") *i wartość minimalna to dwie bardzo różne operacje, ale czy na pewno? Czy można je połączyć w bardziej ogólną metrykę? Gdyby tak było, to zarówno szum jak i Voronoi mogłyby być postrzegane jako szczególne przypadki bardziej ogólnego generatora wzorów kafelkowych?"*. --> +
-Innym użytecznym wariantem jest mnożenie składowych szumu zamiast ich dodawania. Interesujące jest również skalowanie kolejnych funkcji szumu za pomocą czegoś, co zależy od poprzednich terminów w pętli. Kiedy robimy takie rzeczy, odchodzimy od ścisłej definicji fraktala i wchodzimy w stosunkowo nieznaną dziedzinę "multifraktali". Multifraktale nie są tak ściśle zdefiniowane matematycznie, ale to nie czyni ich mniej użytecznymi dla grafiki. W rzeczywistości symulacje multifraktalne są bardzo powszechne we współczesnym komercyjnym oprogramowaniu do generowania terenu. Aby przeczytać więcej, możesz przeczytać rozdział 16 książki "Texturing and Modeling: a Procedural Approach" (3. edycja), autorstwa Kentona Musgrave. Niestety, książka ta jest już od kilku lat niedostępna w druku, ale wciąż można ją znaleźć w bibliotekach i na rynku wtórnym. (Istnieje wersja PDF pierwszego wydania dostępna do kupienia online, ale nie kupuj tego - to strata pieniędzy. Jest z 1994 roku i nie zawiera żadnych rzeczy związanych z modelowaniem terenu z 3. edycji). +Innym użytecznym wariantem jest mnożenie składowych szumu zamiast ich dodawania. Interesujące jest również skalowanie kolejnych funkcji szumu za pomocą czegoś, co zależy od poprzednich terminów w pętli. Kiedy robimy takie rzeczy, odchodzimy od ścisłej definicji fraktala i wchodzimy w stosunkowo nieznaną dziedzinę "multifraktali". Multifraktale nie są tak ściśle zdefiniowane matematycznie, ale to nie czyni ich mniej użytecznymi dla grafiki. W rzeczywistości symulacje multifraktalne są bardzo powszechne we współczesnym komercyjnym oprogramowaniu do generowania terenu. Aby przeczytać więcej, możesz przeczytać rozdział 16 książki "Texturing and Modeling: a Procedural Approach" (3. edycja), autorstwa Kentona Musgrave. Niestety, książka ta jest już od kilku lat niedostępna w druku, ale wciąż można ją znaleźć w bibliotekach i na rynku wtórnym. (Istnieje wersja PDF pierwszego wydania dostępna do kupienia online, ale nie kupuj jej - to strata pieniędzy. Jest z 1994 roku i nie zawiera żadnych rzeczy związanych z modelowaniem terenu z 3. edycji). @@ -150,6 +150,6 @@ Mniej ekstremalnym przykładem tej techniki jest następujący kod, w którym za
-Zakrzywianie współrzędnych tekstury za pomocą szumu może być bardzo użyteczne, daje dużo frajdy, ale jest diabelnie trudne do opanowania. Jest to potężne narzędzie, ale potrzeba sporo doświadczenia, aby dobrze je wykorzystać. Przydatnym narzędziem do tego jest przemieszczanie współrzędnych za pomocą pochodnej (gradientu) szumu. [Na tym pomyśle opiera się słynny artykuł Kena Perlina i Fabrice'a Neyreta o nazwie "flow noise"](http://evasion.imag.fr/Publications/2001/PN01/). Niektóre nowoczesne implementacje szumu Perlina zawierają wariant, który oblicza zarówno funkcję, jak i jej gradient. Jeśli gradient nie jest istnieje, zawsze możesz obliczyć skończone różnice (różnica między sąsiadującymi pikselami), aby go przybliżyć, chociaż jest to mniej dokładne i wymaga więcej pracy. +Zakrzywianie współrzędnych tekstury za pomocą szumu może być bardzo użyteczne, daje dużo frajdy, ale jest diabelnie trudne do opanowania. Jest to potężne narzędzie, ale potrzeba sporo doświadczenia, aby dobrze je wykorzystać. Przydatnym wariantem jest też przemieszczanie współrzędnych za pomocą pochodnej (gradientu) szumu. [Na tym pomyśle opiera się słynny artykuł Kena Perlina i Fabrice'a Neyreta o nazwie "flow noise"](http://evasion.imag.fr/Publications/2001/PN01/). Niektóre nowoczesne implementacje szumu Perlina zawierają wariant, który oblicza zarówno funkcję, jak i jej gradient. Jeśli gradient nie istnieje, zawsze możesz obliczyć skończone różnice (różnica między sąsiadującymi pikselami), aby go przybliżyć, chociaż jest to mniej dokładne i wymaga więcej pracy. diff --git a/README-pl.md b/README-pl.md index 6898e47..2918580 100644 --- a/README-pl.md +++ b/README-pl.md @@ -30,7 +30,7 @@ * [Random](10/) * [Noise](11/) * [Cellular noise](12/) - * [Fraktalny ruch Browna](13/) + * [Fractal Brownian Motion](13/) * Fraktale * Image processing From f5cf99a9657d6c4ce2e8dca6082f4b904fb05e8a Mon Sep 17 00:00:00 2001 From: Wojtek Date: Tue, 21 Mar 2023 14:06:42 +0100 Subject: [PATCH 23/23] deleting a file with notes to myself (forgot to ignore it from commits) --- Questions_to_author.txt | 15 --------------- 1 file changed, 15 deletions(-) delete mode 100644 Questions_to_author.txt diff --git a/Questions_to_author.txt b/Questions_to_author.txt deleted file mode 100644 index c684042..0000000 --- a/Questions_to_author.txt +++ /dev/null @@ -1,15 +0,0 @@ -"Modern computers usually have groups of four processors that work like these pipes, completing tasks one after another" -- what is meant here by groups of four processors? Four CPU cores? -- fixed according to German version - - -Podać polskie tłumaczenie słowa pipeline -Podać angielskie tłumaczenie wejście i wyjście -Wytłumaczyć "hot reloading" (04) -użyć "akceleracja sprzętowa" zamiast "zaimplementowane w hardware" -"linii" vs "linijce" -blending - blending -shapin - kształtowanie -shaping functions - funkcje kształtujące -kreatywni koderzy -Distance field - pole odległości