Wojtek Pachowiak 1 year ago
commit afecc34b9c

@ -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.
<!-- We haven't much of a chance to talk about GLSL vector types. Before going further it's important to learn more about these variables and the subject of colors is a great way to find out more about them. -->
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.
<!-- If you are familiar with object oriented programming paradigms you've probably noticed that we have been accessing the data inside the vectors like any regular C-like `struct`. -->
```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]`.
<!-- Defining color using an *x*, *y* and *z* notation can be confusing and misleading, right? That's why there are other ways to access this same information, but with different names. The values of `.x`, `.y` and `.z` can also be called `.r`, `.g` and `.b`, and `.s`, `.t` and `.p`. (`.s`, `.t` and `.p` are usually used for spatial coordinates of a texture, which we'll see in a later chapter.) You can also access the data in a vector by using the index position, `[0]`, `[1]` and `[2]`. -->
Następujący kod przedstawia wszystkkie sposoby uzysakania tych samych danych:
<!-- The following lines show all the ways to access the same data: -->
```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.
<!-- These different ways of pointing to the variables inside a vector are just nomenclatures designed to help you write clear code. This flexibility embedded in shading language is a door for you to start thinking interchangeably about color and space coordinates. -->
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.
<!-- Another great feature of vector types in GLSL is that the properties can be combined in any order you want, which makes it easy to cast and mix values. This ability is called *swizzle*. -->
```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
```
<!--
```glsl
vec3 yellow, magenta, green;
// Making Yellow
yellow.rg = vec2(1.0); // Assigning 1. to red and green channels
yellow[2] = 0.0; // Assigning 0. to blue channel
// Making Magenta
magenta = yellow.rbg; // Assign the channels with green and blue swapped
// Making Green
green.rgb = yellow.bgb; // Assign the blue channel of Yellow (0) to red and blue channels
``` -->
### 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!
<!-- Now that you know how colors are defined, it's time to integrate this with our previous knowledge. In GLSL there is a very useful function, [`mix()`](../glossary/?search=mix), that lets you mix two values in percentages. Can you guess what the percentage range is? Yes, values between 0.0 and 1.0! Which is perfect for you, after those long hours practicing your karate moves with the fence - it is time to use them! -->
![](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`.
<!-- Check the following code at line 18 and see how we are using the absolute values of a sin wave over time to mix `colorA` and `colorB`. -->
<div class="codeAndCanvas" data="mix.frag"></div>
Pokaż na co cie stać:
<!-- Show off your skills by: -->
* 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.
<!-- * Make an expressive transition between colors. Think of a particular emotion. What color seems most representative of it? How does it appear? How does it fade away? Think of another emotion and the matching color for it. Change the beginning and ending color of the above code to match those emotions. Then animate the transition using shaping functions. Robert Penner developed a series of popular shaping functions for computer animation known as [easing functions](http://easings.net/), you can use [this example](../edit.php#06/easing.frag) as research and inspiration but the best result will come from making your own transitions. -->
### 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`.
<!-- The [`mix()`](../glossary/?search=mix) function has more to offer. Instead of a single `float`, we can pass a variable type that matches the two first arguments, in our case a `vec3`. By doing that we gain control over the mixing percentages of each individual color channel, `r`, `g` and `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.
<!--
Take a look at the following example. Like the examples in the previous chapter, we are hooking the transition to the normalized *x* coordinate and visualizing it with a line. Right now all the channels go along the same line. -->
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`.
<!-- Now, uncomment line number 25 and watch what happens. Then try uncommenting lines 26 and 27. Remember that the lines visualize the amount of `colorA` and `colorB` to mix per channel. -->
<div class="codeAndCanvas" data="gradient.frag"></div>
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ę.
<!-- You probably recognize the three shaping functions we are using on lines 25 to 27. Play with them! It's time for you to explore and show off your skills from the previous chapter and make interesting gradients. Try the following exercises:
![William Turner - The Fighting Temeraire (1838)](turner.jpg)
* Compose a gradient that resembles a William Turner sunset
* Animate a transition between a sunrise and sunset using `u_time`.
* Can you make a rainbow using what we have learned so far?
* Use the `step()` function to create a colorful 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:
<!-- We can't talk about color without speaking about color space. As you probably know there are different ways to organize color besides by red, green and blue channels. -->
<!-- [HSB](http://en.wikipedia.org/wiki/HSL_and_HSV) stands for Hue, Saturation and Brightness (or Value) and is a more intuitive and useful organization of colors. Take a moment to read the `rgb2hsv()` and `hsv2rgb()` functions in the following code. -->
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.
<!-- By mapping the position on the x axis to the Hue and the position on the y axis to the Brightness, we obtain a nice spectrum of visible colors. This spatial distribution of color can be very handy; it's more intuitive to pick a color with HSB than with RGB. -->
<div class="codeAndCanvas" data="hsb.frag"></div>
### 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).
<!-- HSB was originally designed to be represented in polar coordinates (based on the angle and radius) instead of cartesian coordinates (based on x and y). To map our HSB function to polar coordinates we need to obtain the angle and distance from the center of the billboard to the pixel coordinate. For that we will use the [`length()`](../glossary/?search=length) function and [`atan(y,x)`](../glossary/?search=atan) (which is the GLSL version of the commonly used `atan2(y,x)`). -->
<!-- TODO Używając wektorów i funkcji trygonometrycznych, `vec2`, `vec3` i `vec4` traktowane są jak wektory nawet jeśli reprezentują kolor. Zaczniemy traktować kolory i wektory bardzo podobnie. -->
<!-- When using vector and trigonometric functions, `vec2`, `vec3` and `vec4` are treated as vectors even when they represent colors. We will start treating colors and vectors similarly, in fact you will come to find this conceptual flexibility very empowering. -->
**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).
<!-- **Note:** If you were wondering, there are more geometric functions besides [`length`](../glossary/?search=length) like: [`distance()`](../glossary/?search=distance), [`dot()`](../glossary/?search=dot), [`cross`](../glossary/?search=cross), [`normalize()`](../glossary/?search=normalize), [`faceforward()`](../glossary/?search=faceforward), [`reflect()`](../glossary/?search=reflect) and [`refract()`](../glossary/?search=refract). Also GLSL has special vector relational functions such as: [`lessThan()`](../glossary/?search=lessThan), [`lessThanEqual()`](../glossary/?search=lessThanEqual), [`greaterThan()`](../glossary/?search=greaterThan), [`greaterThanEqual()`](../glossary/?search=greaterThanEqual), [`equal()`](../glossary/?search=equal) and [`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.
<!-- Once we obtain the angle and length we need to “normalize” their values to the range between 0.0 to 1.0. On line 27, [`atan(y,x)`](../glossary/?search=atan) will return an angle in radians between -PI and PI (-3.14 to 3.14), so we need to divide this number by `TWO_PI` (defined at the top of the code) to get values between -0.5 to 0.5, which by simple addition we change to the desired range of 0.0 to 1.0. The radius will return a maximum of 0.5 (because we are calculating the distance from the center of the viewport) so we need to double this range (by multiplying by two) to get a maximum of 1.0. -->
Jak widzisz, sedno leży w transformowaniu i mapowaniu zakresów do 0.0 i 1.0.
<!-- As you can see, our game here is all about transforming and mapping ranges to the 0.0 to 1.0 that we like. -->
<div class="codeAndCanvas" data="hsb-colorwheel.frag"></div>
Spróuj poniższych ćwiczeń:
<!-- Try the following exercises: -->
* 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ą.
<!-- * Modify the polar example to get a spinning color wheel, just like the waiting mouse icon.
* Use a shaping function together with the conversion function from HSB to RGB to expand a particular hue value and shrink the rest. -->
![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]
<!-- * If you look closely at the color wheel used on color pickers (see the image below), they use a different spectrum according to RYB color space. For example, the opposite color of red should be green, but in our example it is cyan. Can you find a way to fix that in order to look exactly like the following image? [Hint: this is a great moment to use shaping functions.] -->
![](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.
<!-- * Read [Josef Albers' book Interaction of Color](http://www.goodreads.com/book/show/111113.Interaction_of_Color) and use the following shaders examples as practice. -->
<div class="glslGallery" data="160505191155,160505193939,160505200330,160509131554,160509131509,160509131420,160509131240" data-properties="clickRun:editor,openFrameIcon:false,showAuthor:false"></div>
#### 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.
<!-- Before jumping to the next chapter lets stop and rewind. Go back and take look at the functions in previous examples. You will notice `in` before the type of the arguments. This is a [*qualifier*](http://www.shaderific.com/glsl-qualifiers/#inputqualifier) and in this case it specifies that the variable is read only. In future examples we will see that it is also possible to define arguments as `out` or `inout`. This last one, `inout`, is conceptually similar to passing an argument by reference which will give us the possibility to modify a passed variable. -->
```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. -->

@ -0,0 +1,363 @@
![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.
<!-- Finally! We have been building skills for this moment! You have learned most of the GLSL foundations, types and functions. You have practiced your shaping equations over and over. Now is the time to put it all together. You are up for this challenge! In this chapter you'll learn how to draw simple shapes in a parallel procedural way. -->
### 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?
<!-- Imagine we have grid paper like we used in math classes and our homework is to draw a square. The paper size is 10x10 and the square is supposed to be 8x8. What will you do? -->
![](grid_paper.jpg)
Zamalowałbyś wszystko poza pierwszym i ostatnim rzędem oraz pierwszą i ostatnią kolumną, tak?
<!-- You'd paint everything except the first and last rows and the first and last column, right? -->
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?
<!-- How does this relate to shaders? Each little square of our grid paper is a thread (a pixel). Each little square knows its position, like the coordinates of a chess board. In previous chapters we mapped *x* and *y* to the *red* and *green* color channels, and we learned how to use the narrow two dimensional territory between 0.0 and 1.0. How can we use this to draw a centered square in the middle of our billboard? -->
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.
<!-- Let's start by sketching pseudocode that uses `if` statements over the spatial field. The principles to do this are remarkably similar to how we think of the grid paper scenario. -->
```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:
<!-- Now that we have a better idea of how this will work, lets replace the `if` statement with [`step()`](../glossary/?search=step), and instead of using 10x10 lets use normalized values between 0.0 and 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.
<!-- The [`step()`](../glossary/?search=step) function will turn every pixel below 0.1 to black (`vec3(0.0)`) and the rest to white (`vec3(1.0)`) . The multiplication between `left` and `bottom` works as a logical `AND` operation, where both must be 1.0 to return 1.0 . This draws two black lines, one on the bottom and the other on the left side of the canvas. -->
![](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:
<!-- In the previous code we repeat the structure for each axis (left and bottom). We can save some lines of code by passing two values directly to [`step()`](../glossary/?search=step) instead of one. That looks like this: -->
```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:
<!-- So far, weve only drawn two borders (bottom-left) of our rectangle. Let's do the other two (top-right). Check out the following code: -->
<div class="codeAndCanvas" data="rect-making.frag"></div>
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).
<!-- Uncomment *lines 21-22* and see how we invert the `st` coordinates and repeat the same [`step()`](../glossary/?search=step) function. That way the `vec2(0.0,0.0)` will be in the top right corner. This is the digital equivalent of flipping the page and repeating the previous procedure. -->
![](rect-02.jpg)
Zwróć uwagę, że w *linijkach 18 i 22* wszystkie boki są mnożone przez siebie. Jest to równoznaczne z napisaniem:
<!-- Take note that in *lines 18 and 22* all of the sides are being multiplied together. This is equivalent to writing: -->
```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).
<!-- Interesting right? This technique is all about using [`step()`](../glossary/?search=step) and multiplication for logical operations and flipping the coordinates. -->
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).
<!-- Before going forward, try the following exercises:
* Change the size and proportions of the rectangle.
* Experiment with the same code but using [`smoothstep()`](../glossary/?search=smoothstep) instead of [`step()`](../glossary/?search=step). Note that by changing values, you can go from blurred edges to elegant smooth borders.
* Do another implementation that uses [`floor()`](../glossary/?search=floor).
* Choose the implementation you like the most and make a function of it that you can reuse in the future. Make your function flexible and efficient.
* Make another function that just draws the outline of a rectangle.
* How do you think you can move and place different rectangles in the same billboard? If you figure out how, show off your skills by making a composition of rectangles and colors that resembles a [Piet Mondrian](http://en.wikipedia.org/wiki/Piet_Mondrian) painting. -->
![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ę.
<!-- It's easy to draw squares on grid paper and rectangles on cartesian coordinates, but circles require another approach, especially since we need a "per-pixel" algorithm. One solution is to *re-map* the spatial coordinates so that we can use a [`step()`](../glossary/?search=step) function to draw a circle.
How? Let's start by going back to math class and the grid paper, where we opened a compass to the radius of a circle, pressed one of the compass points at the center of the circle and then traced the edge of the circle with a simple spin. -->
![](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.
<!-- Translating this to a shader where each square on the grid paper is a pixel implies *asking* each pixel (or thread) if it is inside the area of the circle. We do this by computing the distance from the pixel to the center of the circle. -->
![](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:
<!-- There are several ways to calculate that distance. The easiest one uses the [`distance()`](../glossary/?search=distance) function, which internally computes the [`length()`](../glossary/?search=length) of the difference between two points (in our case the pixel coordinate and the center of the canvas). The `length()` function is nothing but a shortcut of the [hypotenuse equation](http://en.wikipedia.org/wiki/Hypotenuse) that uses square root ([`sqrt()`](../glossary/?search=sqrt)) internally. -->
![](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.
<!-- You can use [`distance()`](../glossary/?search=distance), [`length()`](../glossary/?search=length) or [`sqrt()`](../glossary/?search=sqrt) to calculate the distance to the center of the billboard. The following code contains these three functions and the non-surprising fact that each one returns exactly same result. -->
Komentuj i odkomentuj linijki, aby wypróbować różne sposoby uzyskania tego samego wyniku.
<!-- * Comment and uncomment lines to try the different ways to get the same result. -->
<div class="codeAndCanvas" data="circle-making.frag"></div>
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:
<!-- In the previous example we map the distance to the center of the billboard to the color brightness of the pixel. The closer a pixel is to the center, the lower (darker) value it has. Notice that the values don't get too high because from the center ( `vec2(0.5, 0.5)` ) the maximum distance barely goes over 0.5. Contemplate this map and think: -->
* 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)
<!-- * What you can infer from it?
* How we can use this to draw a circle?
* Modify the above code in order to contain the entire circular gradient inside the canvas. -->
### Distance field
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ą.
<!-- We can also think of the above example as an altitude map, where darker implies taller. The gradient shows us something similar to the pattern made by a cone. Imagine yourself on the top of that cone. The horizontal distance to the edge of the cone is 0.5. This will be constant in all directions. By choosing where to “cut” the cone you will get a bigger or smaller circular surface. -->
![](distance-field.jpg)
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.
<!-- 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. -->
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?
<!-- 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)));
```
* Zrób trzy kompozycje z wykorzystaniem tej techniki. Jeśli są one animowane, jeszcze lepiej!
<!-- * Make three compositions using this technique. If they are animated, even better! -->
#### Twoja skrzynka z narzędziami
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. -->
<div class="codeAndCanvas" data="circle.frag"></div>
### Przydatne własności Pól Odległości
![ogórd 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).
Przyjrzyj się następującemu kodowi.
<!-- 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, OReilly](http://chimera.labs.oreilly.com/books/1234000001814/ch07.html#ch07_id36000921).
Take a look at the following code. -->
<div class="codeAndCanvas" data="rect-df.frag"></div>
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)).
<!-- 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.
Lets 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 (thats what [`abs()`](../glossary/?search=abs) is doing there). -->
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.
<!-- 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. -->
### Krzywe biegunowe
![Robert Mangold - Untitled (2008)](mangold.jpg)
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:
<!-- 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);
```
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!
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.
<!-- 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. -->
<div class="simpleFunction" data="y = cos(x*3.);
//y = abs(cos(x*3.));
//y = abs(cos(x*2.5))*0.5+0.3;
//y = abs(cos(x*12.)*sin(x*3.))*.8+.1;
//y = smoothstep(-.5,1., cos(x*10.))*0.2+0.5;"></div>
<div class="codeAndCanvas" data="polar.frag"></div>
Spróbuj:
<!-- Try to: -->
* 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)
<!-- * 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
### Łą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.
<!-- 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. -->
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).
<!-- 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). -->
<div class="codeAndCanvas" data="shapes.frag"></div>
* 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.
<!-- * Using this example, make a function that inputs the position and number of corners of a desired shape and returns a distance field value. -->
* Połącz pola odległości ze sobą z użyciem [`min()`](../glossary/?search=min) i [`max()`](../glossary/?search=max).
<!-- * Mix distance fields together using [`min()`](../glossary/?search=min) and [`max()`](../glossary/?search=max). -->
* Zreplikuj dowolne logo z użyciem pól odległości
<!-- * Choose a geometric logo to replicate using distance fields. -->
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.
<!-- 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. -->
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.
<!-- 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! -->

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

@ -11,4 +11,5 @@ użyć "akceleracja sprzętowa" zamiast "zaimplementowane w hardware"
blending - blending
shapin - kształtowanie
shaping functions - funkcje kształtujące
kreatywni koderzy
kreatywni koderzy
Distance field - pole odległości

Loading…
Cancel
Save