Merge branch 'master' of https://github.com/WojtekPachowiak/thebookofshaders
commit
afecc34b9c
@ -0,0 +1,165 @@
|
||||
## Macierze 2D
|
||||
|
||||
<canvas id="custom" class="canvas" data-fragment-url="matrix.frag" width="700px" height="200px"></canvas>
|
||||
|
||||
### 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.
|
||||
|
||||
<!-- In the previous chapter we learned how to make some shapes - the trick to moving those shapes is to move the coordinate system itself. We can achieve that by simply adding a vector to the ```st``` variable that contains the location of each fragment. This causes the whole space coordinate system to move. -->
|
||||
|
||||
![](translate.jpg)
|
||||
|
||||
Łatwiej jest to zobaczyć niż wytłumaczyć, zatem:
|
||||
|
||||
*Odkomentuj linijkę 35 poniższego kodu, by zobaczyć jak przestrzeń się przesuwa.
|
||||
|
||||
<!-- This is easier to see than to explain, so to see for yourself:
|
||||
|
||||
* Uncomment line 35 of the code below to see how the space itself moves around. -->
|
||||
|
||||
<div class="codeAndCanvas" data="cross-translate.frag"></div>
|
||||
|
||||
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:
|
||||
|
||||
<!-- Now try the following exercise:
|
||||
|
||||
* Using ```u_time``` together with the shaping functions move the small cross around in an interesting way. Search for a specific quality of motion you are interested in and try to make the cross move in the same way. Recording something from the "real world" first might be useful - it could be the coming and going of waves, a pendulum movement, a bouncing ball, a car accelerating, a bicycle stopping.
|
||||
|
||||
### Rotations
|
||||
|
||||
To rotate objects we also need to move the entire space system. For that we are going to use a [matrix](http://en.wikipedia.org/wiki/Matrix_%28mathematics%29). A matrix is an organized set of numbers in columns and rows. Vectors are multiplied by matrices following a precise set of rules in order to modify the values of the vector in a particular way.
|
||||
|
||||
[![Wikipedia entry for Matrix (mathematics) ](matrixes.png)](https://en.wikipedia.org/wiki/Matrix)
|
||||
|
||||
GLSL has native support for two, three and four dimensional matrices: [```mat2```](../glossary/?search=mat2) (2x2), [```mat3```](../glossary/?search=mat3) (3x3) and [```mat4```](../glossary/?search=mat4) (4x4). GLSL also supports matrix multiplication (```*```) and a matrix specific function ([```matrixCompMult()```](../glossary/?search=matrixCompMult)).
|
||||
|
||||
Based on how matrices behave it's possible to construct matrices to produce specific behaviors. For example we can use a matrix to translate a vector: -->
|
||||
|
||||
![](3dtransmat.png)
|
||||
|
||||
Co ciekawsze, możemy użyć macierzy do obrócenia całego układu współrzędnych
|
||||
|
||||
<!-- More interestingly, we can use a matrix to rotate the coordinate system: -->
|
||||
|
||||
![](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)``.
|
||||
|
||||
<!-- Take a look at the following code for a function that constructs a 2D rotation matrix. This function follows the above [formula](http://en.wikipedia.org/wiki/Rotation_matrix) for two dimensional vectors to rotate the coordinates around the ```vec2(0.0)``` point. -->
|
||||
|
||||
```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.
|
||||
|
||||
<!-- According to the way we've been drawing shapes, this is not exactly what we want. Our cross shape is drawn in the center of the canvas which corresponds to the position ```vec2(0.5)```. So, before we rotate the space we need to move shape from the `center` to the ```vec2(0.0)``` coordinate, rotate the space, then finally move it back to the original place. -->
|
||||
|
||||
![](rotate.jpg)
|
||||
|
||||
Co odpowiada ponizszemu kodowi:
|
||||
|
||||
<!-- That looks like the following code: -->
|
||||
|
||||
<div class="codeAndCanvas" data="cross-rotate.frag"></div>
|
||||
|
||||
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.
|
||||
|
||||
<!-- Try the following exercises:
|
||||
|
||||
* Uncomment line 45 of above code and pay attention to what happens.
|
||||
|
||||
* Comment the translations before and after the rotation, on lines 37 and 39, and observe the consequences.
|
||||
|
||||
* Use rotations to improve the animation you simulated in the translation exercise.
|
||||
|
||||
### Scale
|
||||
|
||||
We've seen how matrices are used to translate and rotate objects in space. (Or more precisely to transform the coordinate system to rotate and move the objects.) If you've used 3D modeling software or the push and pop matrix functions in Processing, you will know that matrices can also be used to scale the size of an object. -->
|
||||
|
||||
![](scale.png)
|
||||
|
||||
Na podstawie powyższego wzoru, możemy stworzyć 2D macierz skalowania w GLSL:
|
||||
|
||||
<!-- Following the previous formula, we can figure out how to make a 2D scaling matrix: -->
|
||||
|
||||
```glsl
|
||||
mat2 scale(vec2 _scale){
|
||||
return mat2(_scale.x,0.0,
|
||||
0.0,_scale.y);
|
||||
}
|
||||
```
|
||||
|
||||
<div class="codeAndCanvas" data="cross-scale.frag"></div>
|
||||
|
||||
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.
|
||||
|
||||
<!-- Try the following exercises to understand more deeply how this works.
|
||||
|
||||
* Uncomment line 42 of above code to see the space coordinate being scaled.
|
||||
|
||||
* See what happens when you comment the translations before and after the scaling on lines 37 and 39.
|
||||
|
||||
* Try combining a rotation matrix together with a scale matrix. Be aware that the order matters. Multiply by the matrix first and then multiply the vectors.
|
||||
|
||||
* Now that you know how to draw different shapes, and move, rotate and scale them, it's time to make a nice composition. Design and construct a [fake UI or HUD (heads up display)](https://www.pinterest.com/patriciogonzv/huds/). Use the following ShaderToy example by [Ndel](https://www.shadertoy.com/user/ndel) for inspiration and reference. -->
|
||||
|
||||
<iframe width="800" height="450" frameborder="0" src="https://www.shadertoy.com/embed/4s2SRt?gui=true&t=10&paused=true" allowfullscreen></iframe>
|
||||
|
||||
### 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.
|
||||
|
||||
<div class="codeAndCanvas" data="yuv.frag"></div>
|
||||
|
||||
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.
|
||||
|
||||
<!-- ### Other uses for matrices: YUV color
|
||||
|
||||
[YUV](http://en.wikipedia.org/wiki/YUV) is a color space used for analog encoding of photos and videos that takes into account the range of human perception to reduce the bandwidth of chrominance components.
|
||||
|
||||
The following code is an interesting opportunity to use matrix operations in GLSL to transform colors from one mode to another.
|
||||
|
||||
<div class="codeAndCanvas" data="yuv.frag"></div>
|
||||
|
||||
As you can see we are treating colors as vectors by multiplying them with matrices. In that way we “move” the values around.
|
||||
|
||||
In this chapter we've learned how to use matrix transformations to move, rotate and scale vectors. These transformations will be essential for making compositions out of the shapes we learned about in the previous chapter. In the next chapter we'll apply all we've learned to make beautiful procedural patterns. You will find that coding repetition and variation can be an exciting practice. -->
|
@ -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:
|
||||
|
||||
<!-- ## Patterns
|
||||
|
||||
Since shader programs are executed by pixel-by-pixel no matter how much you repeat a shape the number of calculations stays constant. This means that fragment shaders are particulary suitable for tile patterns.
|
||||
|
||||
[ ![Nina Warmerdam - The IMPRINT Project (2013)](warmerdam.jpg) ](../edit.php#09/dots5.frag)
|
||||
|
||||
In this chapter we are going to apply what we've learned so far and repeat it along a canvas. Like in previous chapters, our strategy will be based on multiplying the space coordinates (between 0.0 and 1.0), so that the shapes we draw between the values 0.0 and 1.0 will be repeated to make a grid.
|
||||
|
||||
*"The grid provides a framework within which human intuition and invention can operate and that it can subvert. Within the chaos of nature patterns provide a constrast and promise of order. From early patterns on pottery to geometric mosaics in Roman baths, people have long used grids to enhance their lives with decoration."* [*10 PRINT*, Mit Press, (2013)](http://10print.org/)
|
||||
|
||||
First let's remember the [```fract()```](../glossary/?search=fract) function. It returns the fractional part of a number, making ```fract()``` in essence the modulo of one ([```mod(x,1.0)```](../glossary/?search=mod)). In other words, [```fract()```](../glossary/?search=fract) returns the number after the floating point. Our normalized coordinate system variable (```st```) already goes from 0.0 to 1.0 so it doesn't make sense to do something like: -->
|
||||
|
||||
```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.
|
||||
|
||||
<!-- But if we scale the normalized coordinate system up - let's say by three - we will get three sequences of linear interpolations between 0-1: the first one between 0-1, the second one for the floating points between 1-2 and the third one for the floating points between 2-3. -->
|
||||
|
||||
<div class="codeAndCanvas" data="grid-making.frag"></div>
|
||||
|
||||
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:
|
||||
|
||||
<!-- Now it's time to draw something in each subspace, by uncommenting line 27. (Because we are multiplying equally in x and y the aspect ratio of the space doesn't change and shapes will be as expected.)
|
||||
|
||||
Try some of the following exercises to get a deeper understanding: -->
|
||||
|
||||
* 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
|
||||
|
||||
<!-- * Multiply the space by different numbers. Try with floating point values and also with different values for x and y.
|
||||
|
||||
* Make a reusable function of this tiling trick.
|
||||
|
||||
* Divide the space into 3 rows and 3 columns. Find a way to know in which column and row the thread is and use that to change the shape that is displaying. Try to compose a tic-tac-toe match. -->
|
||||
|
||||
### 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.
|
||||
|
||||
<!-- ### Apply matrices inside patterns
|
||||
|
||||
Since each subdivision or cell is a smaller version of the normalized coordinate system we have already been using, we can apply a matrix transformation to it in order to translate, rotate or scale the space inside. -->
|
||||
|
||||
<div class="codeAndCanvas" data="checks.frag"></div>
|
||||
|
||||
* 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.
|
||||
|
||||
<!-- * Think of interesting ways of animating this pattern. Consider animating color, shapes and motion. Make three different animations.
|
||||
|
||||
* Recreate more complicated patterns by composing different shapes. -->
|
||||
|
||||
|
||||
[![](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).
|
||||
|
||||
<!-- * Combine different layers of patterns to compose your own [Scottish Tartan Patterns](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.
|
||||
|
||||
<!-- ### Offset patterns
|
||||
|
||||
So let's say we want to imitate a brick wall. Looking at the wall, you can see a half brick offset on x in every other row. How we can do that?
|
||||
|
||||
![](brick.jpg)
|
||||
|
||||
As a first step we need to know if the row of our thread is an even or odd number, because we can use that to determine if we need to offset the x in that row.
|
||||
|
||||
____we have to fix these next two paragraphs together____
|
||||
|
||||
To determine if our thread is in an odd or even row, we are going to use [```mod()```](../glossary/?search=mod) of ```2.0``` and then see if the result is under ```1.0``` or not. Take a look at the following formula and uncomment the two last lines. -->
|
||||
|
||||
<div class="simpleFunction" data="y = mod(x,2.0);
|
||||
// y = mod(x,2.0) < 1.0 ? 0. : 1. ;
|
||||
// y = step(1.0,mod(x,2.0));"></div>
|
||||
|
||||
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``.
|
||||
|
||||
<!-- As you can see we can use a [ternary operator](https://en.wikipedia.org/wiki/%3F:) to check if the [```mod()```](../glossary/?search=mod) of ```2.0``` is under ```1.0``` (second line) or similarly we can use a [```step()```](../glossary/?search=step) function which does the same operation, but faster. Why? Although is hard to know how each graphic card optimizes and compiles the code, it is safe to assume that built-in functions are faster than non-built-in ones. Everytime you can use a built-in function, use it!
|
||||
|
||||
So now that we have our odd number formula we can apply an offset to the odd rows to give a *brick* effect to our tiles. Line 14 of the following code is where we are using the function to "detect" odd rows and give them a half-unit offset on ```x```. Note that for even rows, the result of our function is ```0.0```, and multiplying ```0.0``` by the offset of ```0.5``` gives an offset of ```0.0```. But on odd rows we multiply the result of our function, ```1.0```, by the offset of ```0.5```, which moves the ```x``` axis of the coordinate system by ```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.
|
||||
|
||||
<!-- Now try uncommenting line 32 - this stretches the aspect ratio of the coordinate system to mimic the aspect of a "modern brick". By uncommenting line 40 you can see how the coordinate system looks mapped to red and green. -->
|
||||
|
||||
<div class="codeAndCanvas" data="bricks.frag"></div>
|
||||
|
||||
* 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:
|
||||
|
||||
<!-- * Try animating this by moving the offset according to time.
|
||||
|
||||
* Make another animation where even rows move to the left and odd rows move to the right.
|
||||
|
||||
* Can you repeat this effect but with columns?
|
||||
|
||||
* Try combining an offset on ```x``` and ```y``` axis to get something like this: -->
|
||||
|
||||
<a href="../edit.php#09/marching_dots.frag"><canvas id="custom" class="canvas" data-fragment-url="marching_dots.frag" width="520px" height="200px"></canvas></a>
|
||||
|
||||
## 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 Tiles
|
||||
|
||||
Now that we've learned how to tell if our cell is in an even or odd row or column, it's possible to reuse a single design element depending on its position. Consider the case of the [Truchet Tiles](http://en.wikipedia.org/wiki/Truchet_tiles) where a single design element can be presented in four different ways: -->
|
||||
|
||||
![](truchet-00.png)
|
||||
|
||||
Zmieniając wzór na kafelkach, można zbudować nieskończony zestaw skomplikowanych wzorów.
|
||||
|
||||
<!-- By changing the pattern across tiles, it's possible to construct an infinite set of complex designs. -->
|
||||
|
||||
![](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.
|
||||
|
||||
<!-- Pay close attention to the function ```rotateTilePattern()```, which subdivides the space into four cells and assigns an angle of rotation to each one. -->
|
||||
|
||||
<div class="codeAndCanvas" data="truchet.frag"></div>
|
||||
|
||||
* 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)
|
||||
|
||||
<!-- * Comment, uncomment and duplicate lines 69 to 72 to compose new designs.
|
||||
|
||||
* Change the black and white triangle for another element like: half circles, rotated squares or lines.
|
||||
|
||||
* Code other patterns where the elements are rotated according to their position.
|
||||
|
||||
* Make a pattern that changes other properties according to the position of the elements.
|
||||
|
||||
* Think of something else that is not necessarily a pattern where you can apply the principles from this section. (Ex: I Ching hexagrams) -->
|
||||
|
||||
<a href="../edit.php#09/iching-01.frag"><canvas id="custom" class="canvas" data-fragment-url="iching-01.frag" width="520px" height="200px"></canvas></a>
|
||||
|
||||
## 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ć.
|
||||
|
||||
<!-- ## Making your own rules
|
||||
|
||||
Making procedural patterns is a mental exercise in finding minimal reusable elements. This practice is old; we as a species have been using grids and patterns to decorate textiles, floors and borders of objects for a long time: from meanders patterns in ancient Greece, to Chinese lattice design, the pleasure of repetition and variation catches our imagination. Take some time to look at [decorative](https://archive.org/stream/traditionalmetho00chririch#page/130/mode/2up) [patterns](https://www.pinterest.com/patriciogonzv/paterns/) and see how artists and designers have a long history of navigating the fine edge between the predictability of order and the surprise of variation and chaos. From Arabic geometrical patterns, to gorgeous African fabric designs, there is an entire universe of patterns to learn from. -->
|
||||
|
||||
![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.
|
||||
|
||||
<!-- With this chapter we end the section on Algorithmic Drawing. In the following chapters we will learn how to bring some entropy to our shaders and produce generative designs. -->
|
@ -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:
|
||||
|
||||
<!-- Randomness is a maximal expression of entropy. How can we generate randomness inside the seemingly predictable and rigid code environment?
|
||||
|
||||
Let's start by analyzing the following function: -->
|
||||
|
||||
<div class="simpleFunction" data="y = fract(sin(x)*1.0);"></div>
|
||||
|
||||
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.
|
||||
|
||||
<!-- Above we are extracting the fractional content of a sine wave. The [```sin()```](../glossary/?search=sin) values that fluctuate between ```-1.0``` and ```1.0``` have been chopped behind the floating point, returning all positive values between ```0.0``` and ```1.0```. We can use this effect to get some pseudo-random values by "breaking" this sine wave into smaller pieces. How? By multiplying the resultant of [```sin(x)```](../glossary/?search=sin) by larger numbers. Go ahead and click on the function above and start adding some zeros.
|
||||
|
||||
By the time you get to ```100000.0``` ( and the equation looks like this: ```y = fract(sin(x)*100000.0)``` ) you aren't able to distinguish the sine wave any more. The granularity of the fractional part has corrupted the flow of the sine wave into pseudo-random 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.
|
||||
|
||||
<!-- ## Controlling chaos
|
||||
|
||||
Using random can be hard; it is both too chaotic and sometimes not random enough. Take a look at the following graph. To make it, we are using a ```rand()``` function which is implemented exactly like we describe above.
|
||||
|
||||
Taking a closer look, you can see the [```sin()```](../glossary/?search=sin) wave crest at ```-1.5707``` and ```1.5707```. I bet you now understand why - it's where the maximum and minimum of the sine wave happens.
|
||||
|
||||
If look closely at the random distribution, you will note that the there is some concentration around the middle compared to the edges. -->
|
||||
|
||||
<div class="simpleFunction" data="y = rand(x);
|
||||
//y = rand(x)*rand(x);
|
||||
//y = sqrt(rand(x));
|
||||
//y = pow(rand(x),5.);"></div>
|
||||
|
||||
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ść.
|
||||
|
||||
<!-- A while ago [Pixelero](https://pixelero.wordpress.com) published an [interesting article about random distribution](https://pixelero.wordpress.com/2008/04/24/various-functions-and-various-distributions-with-mathrandom/). I've added some of the functions he uses in the previous graph for you to play with and see how the distribution can be changed. Uncomment the functions and see what happens.
|
||||
|
||||
If you read [Pixelero's article](https://pixelero.wordpress.com/2008/04/24/various-functions-and-various-distributions-with-mathrandom/), it is important to keep in mind that our ```rand()``` function is a deterministic random, also known as pseudo-random. Which means for example ```rand(1.)``` is always going to return the same value. [Pixelero](https://pixelero.wordpress.com/2008/04/24/various-functions-and-various-distributions-with-mathrandom/) makes reference to the ActionScript function ```Math.random()``` which is non-deterministic; every call will return a different value. -->
|
||||
|
||||
## 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.
|
||||
|
||||
<!-- Now that we have a better understanding of randomness, it's time to apply it in two dimensions, to both the ```x``` and ```y``` axis. For that we need a way to transform a two dimensional vector into a one dimensional floating point value. There are different ways to do this, but the [```dot()```](../glossary/?search=dot) function is particulary helpful in this case. It returns a single float value between ```0.0``` and ```1.0``` depending on the alignment of two vectors. -->
|
||||
|
||||
<div class="codeAndCanvas" data="2d-random.frag"></div>
|
||||
|
||||
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.
|
||||
|
||||
<!-- Take a look at lines 13 to 15 and notice how we are comparing the ```vec2 st``` with another two dimensional vector ( ```vec2(12.9898,78.233)```).
|
||||
|
||||
* Try changing the values on lines 14 and 15. See how the random pattern changes and think about what we can learn from this.
|
||||
|
||||
* Hook this random function to the mouse interaction (```u_mouse```) and time (```u_time```) to understand better how it works. -->
|
||||
|
||||
## 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.
|
||||
|
||||
<!-- ## Using the chaos
|
||||
|
||||
Random in two dimensions looks a lot like TV noise, right? It's a hard raw material to use to compose images. Let's learn how to make use of it.
|
||||
|
||||
Our first step is to apply a grid to it; using the [```floor()```](../glossary/?search=floor) function we will generate an integer table of cells. Take a look at the following code, especially lines 22 and 23. -->
|
||||
|
||||
<div class="codeAndCanvas" data="2d-random-mosaic.frag"></div>
|
||||
|
||||
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.
|
||||
|
||||
<!-- After scaling the space by 10 (on line 21), we separate the integers of the coordinates from the fractional part. We are familiar with this last operation because we have been using it to subdivide a space into smaller cells that go from ```0.0``` to ```1.0```. By obtaining the integer of the coordinate we isolate a common value for a region of pixels, which will look like a single cell. Then we can use that common integer to obtain a random value for that area. Because our random function is deterministic, the random value returned will be constant for all the pixels in that cell.
|
||||
|
||||
Uncomment line 29 to see that we preserve the floating part of the coordinate, so we can still use that as a coordinate system to draw things inside each cell. -->
|
||||
|
||||
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``.
|
||||
|
||||
<!-- Combining these two values - the integer part and the fractional part of the coordinate - will allow you to mix variation and order.
|
||||
|
||||
Take a look at this GLSL port of the famous ```10 PRINT CHR$(205.5+RND(1)); : GOTO 10``` maze generator. -->
|
||||
|
||||
<div class="codeAndCanvas" data="2d-random-truchet.frag"></div>
|
||||
|
||||
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ę.
|
||||
|
||||
<!-- Here I'm using the random values of the cells to draw a line in one direction or the other using the ```truchetPattern()``` function from the previous chapter (lines 41 to 47).
|
||||
|
||||
You can get another interesting pattern by uncommenting the block of lines between 50 to 53, or animate the pattern by uncommenting lines 35 and 36. -->
|
||||
|
||||
## 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.
|
||||
|
||||
<!-- [Ryoji Ikeda](http://www.ryojiikeda.com/), Japanese electronic composer and visual artist, has mastered the use of random; it is hard not to be touched and mesmerized by his work. His use of randomness in audio and visual mediums is forged in such a way that it is not annoying chaos but a mirror of the complexity of our technological culture. -->
|
||||
|
||||
<iframe src="https://player.vimeo.com/video/76813693?title=0&byline=0&portrait=0" width="800" height="450" frameborder="0" webkitallowfullscreen mozallowfullscreen allowfullscreen></iframe>
|
||||
|
||||
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.
|
||||
|
||||
<!-- Take a look at [Ikeda](http://www.ryojiikeda.com/)'s work and try the following exercises:
|
||||
|
||||
* Make rows of moving cells (in opposite directions) with random values. Only display the cells with brighter values. Make the velocity of the rows fluctuate over time. -->
|
||||
|
||||
<a href="../edit.php#10/ikeda-00.frag"><canvas id="custom" class="canvas" data-fragment-url="ikeda-00.frag" width="520px" height="200px"></canvas></a>
|
||||
|
||||
* 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.
|
||||
|
||||
<!-- * Similarly make several rows but each one with a different speed and direction. Hook the position of the mouse to the threshold of which cells to show. -->
|
||||
|
||||
<a href="../edit.php#10/ikeda-03.frag"><canvas id="custom" class="canvas" data-fragment-url="ikeda-03.frag" width="520px" height="200px"></canvas></a>
|
||||
|
||||
* Stwórz inne ciekawe efekty.
|
||||
|
||||
<!-- * Create other interesting effects. -->
|
||||
|
||||
<a href="../edit.php#10/ikeda-04.frag"><canvas id="custom" class="canvas" data-fragment-url="ikeda-04.frag" width="520px" height="200px"></canvas></a>
|
||||
|
||||
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.
|
||||
|
||||
<!-- Using random aesthetically can be problematic, especially if you want to make natural-looking simulations. Random is simply too chaotic and very few things look ```random()``` in real life. If you look at a rain pattern or a stock chart, which are both quite random, they are nothing like the random pattern we made at the begining of this chapter. The reason? Well, random values have no correlation between them what so ever, but most natural patterns have some memory of the previous state.
|
||||
|
||||
In the next chapter we will learn about noise, the smooth and *natural looking* way of creating computational chaos. -->
|
Loading…
Reference in New Issue