diff --git a/03/README-pt.md b/03/README-pt.md index c9a5752..f292968 100644 --- a/03/README-pt.md +++ b/03/README-pt.md @@ -1,8 +1,8 @@ ## Uniforms -Até agora vimos como a GPU lida com grandes números de threads paralelas, cada uma responsável por atribuir cor a uma porção da imagem inteira. Apesar de cada thread paralela não saber da existência das outras, precisamos ser capazes de enviar dados da CPU para todas as threads. Por causa da arquitetura da placa de gráficos, esses dados deverão ser iguais (*uniform*) para todas as threads e necessariamente serem marcados como *read only*. Em outras palavras, cada thread recebe os mesmos dados, os quais se podem ler mas não podem se alterar. +Até agora, vimos como a GPU lida um grande número de threads em paralelo, cada uma sendo responsável por atribuir a cor a uma porção da imagem.Apesar de cada thread paralela não saber da existência das outras, precisamos ser capazes de enviá-las algumas entradas (inputs) da CPU. Devido à arquitetura das placas de vídeo, essas entradas serão iguais (*uniform*) para todas as threads e necessariamente determinadas como *somente leitura*. Em outras palavras, cada thread recebe os mesmos dados, os quais se podem ler mas não podem se alterar. -Esses dados são chamados de `uniform` e podem ser de tipos diferentes, como: `float`, `vec2`, `vec3`, `vec4`, `mat2`, `mat3`, `mat4`, `sampler2D` e `samplerCube`. Uniforms são definidos com o tipo correspondente no topo do shader, logo após atribuir o ponto flutuante de precisão padrão. +Essas entradas são chamamadas de `uniform` e podem ser de tipos diferentes, como: `float`, `vec2`, `vec3`, `vec4`, `mat2`, `mat3`, `mat4`, `sampler2D` e `samplerCube`. Uniformes são definidas com o tipo correspondente no começo do código, logo após atribuir a precisão padrão de pontos flutuantes, ```glsl #ifdef GL_ES @@ -14,7 +14,7 @@ uniform vec2 u_mouse; // mouse position in screen pixels uniform float u_time; // Time in seconds since load ``` -Imagine os uniforms como pequenas pontes entre a CPU e a GPU. Os nomes variam dependendo da implementação mas nessa série de exemplos estarei sempre usando: `u_time` (tempo em segundos desde que o shader foi iniciado), `u_resolution` (tamanho da tela em que o shader está sendo desenhado em) and `u_mouse` (posição do mouse dentro da tela em pixels). Estarei seguindo a convenção ao colocar `u_` antes do nome para ser explícito quando a natureza desta variável mas você encontrará outros tipos de nomenclatura para uniforms. Por exemplo [ShaderToy.com](https://www.shadertoy.com/) utiliza os mesmos uniforms mas com os seguintes nomes: +Imagine os uniforms como pequenas pontes entre a CPU e a GPU. Os nomes variam dependendo da implementação, mas nessa série de exemplos estarei sempre usando: `u_time` (tempo em segundos desde que o shader foi iniciado), `u_resolution` (tamanho da tela onde o shader está sendo desenhado) and `u_mouse` (posição em pixels do mouse dentro da tela). Estarei seguindo a convenção ao colocar `u_` antes do nome da uniform para evidenciar a natureza desta variável mas você encontrará outros tipos de nomenclatura para uniforms. Por exemplo [ShaderToy.com](https://www.shadertoy.com/) utiliza os mesmos uniforms mas com os seguintes nomes: ```glsl uniform vec3 iResolution; // viewport resolution (in pixels) @@ -22,40 +22,40 @@ uniform vec4 iMouse; // mouse pixel coords. xy: current, zw: click uniform float iTime; // shader playback time (in seconds) ``` -Chega de conversa, vamos ver os uniforms em ação. No código abaixo usamos `u_time` - o número de segundos desde que o shader começou a ser executado - junto com uma função de seno para animar a transição da quantidade de vermelho na tela. +Chega de conversa, vamos ver os uniforms em ação. No código abaixo, usamos `u_time` - o número de segundos desde que o shader começou a ser executado - junto com uma função de seno para animar a transição da quantidade de vermelho na tela.
-Como você pode ver, GLSL têm mais surpresas. A GPU tem funções angulares, trigonométricas e exponenciais aceleradas pelo hardware. Algumas dessas funções são: [`sin()`](../glossary/?search=sin), [`cos()`](../glossary/?search=cos), [`tan()`](../glossary/?search=tan), [`asin()`](../glossary/?search=asin), [`acos()`](../glossary/?search=acos), [`atan()`](../glossary/?search=atan), [`pow()`](../glossary/?search=pow), [`exp()`](../glossary/?search=exp), [`log()`](../glossary/?search=log), [`sqrt()`](../glossary/?search=sqrt), [`abs()`](../glossary/?search=abs), [`sign()`](../glossary/?search=sign), [`floor()`](../glossary/?search=floor), [`ceil()`](../glossary/?search=ceil), [`fract()`](../glossary/?search=fract), [`mod()`](../glossary/?search=mod), [`min()`](../glossary/?search=min), [`max()`](../glossary/?search=max) e [`clamp()`](../glossary/?search=clamp). +Como você pode ver, GLSL tem mais surpresas. A GPU tem funções angulares, trigonométricas e exponenciais aceleradas pelo hardware. Algumas dessas funções são: [`sin()`](../glossary/?search=sin), [`cos()`](../glossary/?search=cos), [`tan()`](../glossary/?search=tan), [`asin()`](../glossary/?search=asin), [`acos()`](../glossary/?search=acos), [`atan()`](../glossary/?search=atan), [`pow()`](../glossary/?search=pow), [`exp()`](../glossary/?search=exp), [`log()`](../glossary/?search=log), [`sqrt()`](../glossary/?search=sqrt), [`abs()`](../glossary/?search=abs), [`sign()`](../glossary/?search=sign), [`floor()`](../glossary/?search=floor), [`ceil()`](../glossary/?search=ceil), [`fract()`](../glossary/?search=fract), [`mod()`](../glossary/?search=mod), [`min()`](../glossary/?search=min), [`max()`](../glossary/?search=max) e [`clamp()`](../glossary/?search=clamp). Agora é novamente a hora de experimentar com o código acima. * Diminua a frequência até a mudança de cor se tornar quase imperceptível. -* Aumente a frequência até você ver uma única cor sem ela piscar. +* Aumente a velocidade até que seja possível ver somente uma cor sem oscilações. -* Experimente alterar os valores dos três canais (RGB) em diferentes frequências a fim de obter padões e comportamentos interessantes. +* Experimente alterar os valores dos três canais de cores (RGB) em diferentes frequências a fim de obter padrões e comportamentos interessantes. ## gl_FragCoord -Da mesma maneira que GLSL nos dá um output padrão, `vec4 gl_FragColor`, ele também nos dá um input padrão, `vec4 gl_FragCoord`, que possui as coordenadas de um *pixel* ou *screen fragment* com que a thread ativa está trabalhando. Com `vec4 gl_FragCoord` podemos saber onde a thread está trabalhando dentro da tela. Neste caso não chamaremos isso de `uniform` porque seu valor será diferente para cada thread, logo `gl_FragCoord` é chamada de *varying*. +Da mesma maneira que GLSL nos dá um output padrão, `vec4 gl_FragColor`, ele também nos dá um input padrão, `vec4 gl_FragCoord`, que possui as coordenadas de um *pixel* ou *screen fragment* com que a thread ativa está processando. Com `vec4 gl_FragCoord` podemos saber onde a thread está trabalhando dentro da tela. Neste caso, não chamaremos isso de `uniform` porque seu valor será diferente para cada thread, logo `gl_FragCoord` é chamada de *varying*.
-No código acima nós *normalizamos* as coordenadas do fragmento dividindo o mesmo pela resolução total da tela. Ao fazer isso os valores serão entre `0.0` e `1.0`, o que torna fácim mapear os valores de X e Y para os canais RED e GREEN. +No código acima nós *normalizamos* as coordenadas do fragmento ao dividi-las pela resolução total da tela. Fazendo isso, os valores serão entre `0.0` e `1.0`, o que facilita mapear os valores de X e Y para os canais RED e GREEN. -No mundo dos shaders não temos muitos recursos para investigar bugs além de atribuir uma cor marcante às variáveis e tentar entender o que está acontecendo com as mesmas. Você descobrirá que, às vezes, programar em GLSL é bem similar a construir navios dentro de garrafas. É igualmente difícil, bonito e gratificante. +No mundo dos shaders, não temos muitos recursos para depurar bugs além de atribuir uma cor marcante às variáveis e tentar entender o que está acontecendo com as mesmas. Você descobrirá que, às vezes, programar em GLSL é bem similar a construir navios dentro de garrafas. É igualmente difícil, bonito e gratificante. ![](08.png) Agora é a hora de tentar e desafiar a nossa compreensão desse código. -* Você pode me dizer onde a coordenada `(0.0, 0.0)` está em nossa tela? +* Você pode dizer onde a coordenada `(0.0, 0.0)` está em nossa tela? -* E então `(1.0, 0.0)`, `(0.0, 1.0)`, `(0.5, 0.5)` e `(1.0, 1.0)`? +* E quanto `(1.0, 0.0)`, `(0.0, 1.0)`, `(0.5, 0.5)` e `(1.0, 1.0)`? * Você pode adivinhar como se usa o uniform `u_mouse`, sabendo que os valores são em pixel e NÃO em valores normalizados? Você pode usá-lo para mover as cores ao longo da tela? * Você consegue imaginar uma maneira interessante para mudar esse padrão de cor usando `u_time` e as coordenadas de `u_mouse`? -Após completar estes exercícios você talvez se pergunte onde mais você pode aplicar seu novo superpoder de shader. No próximo capítulo veremos como fazer as nossas próprias ferramentas de shader em three.js, Processing, e openFrameworks. +Após completar estes exercícios, você talvez se pergunte onde mais você pode aplicar seu novo superpoder de shader. No próximo capítulo veremos como fazer as nossas próprias ferramentas de shader em three.js, Processing, e openFrameworks. \ No newline at end of file diff --git a/05/README-pt.md b/05/README-pt.md new file mode 100644 index 0000000..40f6428 --- /dev/null +++ b/05/README-pt.md @@ -0,0 +1,140 @@ +# Algoritmos de desenho +## Modelagem de funções + +Este capítulo poderia se chamar "Lição de pintar a cerca com o Sr. Miyagi". Anteriormente, nós mapeamos as posições normalizadas de *x* e *y* para os canais *red* e *green*. Essencialmente, nós criamos uma função que recebe um vetor bidimensional (x e y) e retornamos um com quatro dimensões (vermelho, verde, azul e alpha). Mas antes de irmos além de transformações dos dados entre as dimensões, precisamos fazer algo mais simples... muito mais simples: entender como criar uma função unidimensional. Quanto mais energia e tempo que você gastar dominando isso, mais forte seu karatê de shader será. + +![The Karate Kid (1984)](mr_miyagi.jpg) + +A estrutura do código a seguir será nossa cerca. Nela, nós visualizaremos os valores normalizados da coordenada *x* (`st.x`) de dois jeitos: uma com a claridade (observe o belo gradiente de branco para preto) e a outra é traçando uma linha verde por cima (neste caso, o valor de *x* será atribuído diretamente a *y*). Não foque tanto na função de traçar, nós a veremos com mais detalhes em alguns minutos. + +
+ +**Nota rápida**: O construtor do tipo `vec3` "entende" que você quer atribuir o mesmo valor aos três canais de cores, enquanto `vec4` entende que você quer construir um vetor quadridimensional usando um vetor tridimensional *um* somado a um quarto valor (neste caso, o valor que controlará o alpha ou opacidade). Veja as linhas 20 e 26 acima por exemplo. + +Este código é a sua cerca: É importante observar e entendê-lo. Você voltará algumas vezes para este espaço entre *0.0* e *1.0*. Aprenderá a arte de mesclar e dar forma a esta linha. + +Essa relação de um pra um entre *x* e *y* (ou de brilho) é conhecida como *interpolação linear*. A partir daqui, nós usaremos algumas funções matemáticas para dar *forma* a linha. Por exemplo, nós podemos elevar *x* à quinta potência para criar uma linha *curvada*. + +
+ +Interessante, não é? Na linha 22, tente diferentes expoentes: 20.0. 2.0, 1.0, 0.0, 0.2 e 0.02 por exemplo. Entender essa relação entre o valor e o expoente será de grande ajuda. Usar esses tipos de funções matemáticas aqui e ali nos dará um controle significativo do nosso código, uma espécie de acumpultura de dados que permite que você controle a fluência dos valores. + +[`pow()`](../glossary/?search=pow) é uma função nativa no GLSL e existem muitas outras. A maioria delas são aceleradas em nível de hardware, o que significa que se elas forem usadas da forma certa e com juízo, farão seu código mais rápido. + +Substitua a função de potência na linha 22. Tente outras como: [`exp()`](../glossary/?search=exp), [`log()`](../glossary/?search=log) e [`sqrt()`](../glossary/?search=sqrt). Algumas destas funções são mais interessantes quando você experimenta utilizando PI. Você pode ver na linha 8 que eu defini uma macro que retornará qualquer chamada de `PI` com o valor de `3.14159265359`. + +### Step e smoothstep + +GLSL também tem algumas exclusivas funções nativas de interpolação que são aceleradas pelo hardware. + +A interpolação [`step()`](../glossary/?search=step) recebe dois parâmetros. O primeiro é para o limite ou limiar, enquanto o segundo é o valor que nós queremos passar. Qualquer valor acima do limite retornará `0.0` e qualquer um acima do limite retornará `1.0`. + +Experimente mudar este valor de limiar na linha 20 do código a seguir. + +
+ +A outra função exclusiva é conhecida como [`smoothstep()`](../glossary/?search=smoothstep). Dado um intervalo de dois números, está função irá interpolar os valores entre o intervalo definido. Os dois primeiros parâmetros são para o início e o final da transição, enquanto o terceiro é o valor que será interpolado. + +
+ +No exemplo anterior, na linha 12, veja que estamos usando smoothstep para desenhar a linha verde na função `plot()`. Pra cada posição dentro do eixo *x*, esta função faz uma *marcação* num valor específico de *y*. Como? Conectando duas [`smoothstep()`](../glossary/?search=smoothstep) juntas. Dê uma olhada na seguinte função, troque a linha 20 acima por esta, e imagine-a como um corte vertical. O fundo se parece com uma linha, certo? + +```glsl +float y = smoothstep(0.2,0.5,st.x) - smoothstep(0.5,0.8,st.x); +``` + +### Seno e Cosseno + +Quando queremos usar um pouco de matemática para animar, dar forma e mesclar valores, não há nada melhor que ser amigo do seno e cosseno. + +Essas duas funções trigonométricas básicas trabalham juntas para construir circunferências que são tão úteis como o canivete suíço de MacGyver. É importante entender como elas se comportam e de quais formas elas podem ser combinadas. Em poucas palavras, dado um ângulo (em radianos), elas retornarão a posição correta de *x* ([cosseno](../glossary/?search=cos)) e *y* ([seno](../glossary/?search=sin)) de um ponto na linha de uma circunferência de raio igual a 1. O fato de elas retornarem valores normalizados (que vão de 1 a -1) de maneira suave faz delas, ferramentas incríveis. + +![](sincos.gif) + +Enquanto é difícil descrever todas as relações entre as funções trigonométricas e circunferências, a animação acima faz um ótimo trabalho em exemplificar visualmente esta relação. + +
+ +Preste muita atenção nesta onda de seno. Note como o valor de *y* flui suavemente entre +1 e -1. Como vimos nos exemplos de tempo no capítulo anterior, podemos usar esse movimento rítmico do [`sin()`](../glossary/?search=sin) para animar propriedades. Se você estiver lendo este exemplo em um navegador, você verá que você pode alterar o código da fórmula acima para observar como as ondas mudam. (Nota: não se esqueça do ponto e vírgula no final das linhas). + +Experimente com os seguintes exercícios e veja o que acontece: + +* Some o tempo (`u_time`) ao *x* antes de calcular o `sin`. Perceba o **movimento** ao longo de *x* + +* Multiplique *x* por `PI` antes de calcular o `sin`. Veja como a **frequência** entre as fases se torna mais comprimida. + +* Multiplique *x* pelo tempo (`u_time`) antes de calcular o `sin`. Note que u_time já pode ter se tornado um valor muito grande, o que torna difícil enxergar a linha verde. + +* Some 1.0 a [`sin(x)`](../glossary/?search=sin). Veja como toda a onda foi **deslocada** para cima e agora seus valores vão de 0.0 a 2.0. + +* Multiplique [`sin(x)`](../glossary/?search=sin) por 2.0. Veja como a **amplitude** dobra seu tamanho. + +* Calcule o valor absoluto ([`abs()`](../glossary/?search=abs)) do `sin(x)`. Se parece com o rastro de uma *bola quicando*. + +* Extraia apenas a parte fracionária ([`fract()`](../glossary/?search=fract)) do resultante do [`sin(x)`](../glossary/?search=sin). + +* Some o número inteiro mais alto ([`ceil()`](../glossary/?search=ceil)) e o inteiro mais baixo ([`floor()`](../glossary/?search=floor)) do resultante do [`sin(x)`](../glossary/?search=sin) para conseguir uma onda digital de 1 e -1. + +### Outras funções úteis + +No final do último exercício nós apresentamos algumas novas funções. Agora é hora de experimentar cada uma descomentando as linhas abaixo, uma de cada vez. É importante entender o funcionamento e comportamento destas funções. Eu sei, você deve estar se perguntando... Por quê? Uma rápida pesquisa no google de "arte generativa" (ou generative art) te mostrará. Lembre-se que estas funções são a nossa cerca. Nós estamos dominando o movimento em uma dimensão, para cima e para baixo. Logo, usaremos duas, três quatro dimensões! + +![Anthony Mattox (2009)](anthony-mattox-ribbon.jpg) + +
+ +### Modelando funções avançadas + +[Golan Levin](http://www.flong.com/) tem uma ótima documentação de modelagem de funções complexas que são de extraordinária ajuda. Portá-las para GLSL é uma excelente forma para começar seu próprio banco de trechos de códigos. + +* [Polynomial Shaping Functions: www.flong.com/texts/code/shapers_poly](http://www.flong.com/texts/code/shapers_poly/) + +* [Exponential Shaping Functions: www.flong.com/texts/code/shapers_exp](http://www.flong.com/texts/code/shapers_exp/) + +* [Circular & Elliptical Shaping Functions: www.flong.com/texts/code/shapers_circ](http://www.flong.com/texts/code/shapers_circ/) + +* [Bezier and Other Parametric Shaping Functions: www.flong.com/texts/code/shapers_bez](http://www.flong.com/texts/code/shapers_bez/) + +
+ +Como chefs que coletam temperos e ingredientes exóticos, artistas digitais e programadores criativos tem um amor único por trabalhar nas suas próprias funções. + +[Iñigo Quiles](http://www.iquilezles.org/) tem uma grande coleção de [funções úteis](http://www.iquilezles.org/www/articles/functions/functions.htm). Depois de ler [este artigo](http://www.iquilezles.org/www/articles/functions/functions.htm), dê uma olhada na seguinte na seguinte tradução destas funções para GLSL. Preste atenção nas pequenas mudanças necessárias, como colocar o "." (ponto) nos números de ponto flutuantes ou usar o nome em GLSL para as *Funções em C*; por exemplo, em vez de `powf()`, usamos `pow()`: + +
+ +Para mantermos sua motivação lá em cima, aqui temos um exemplo elegante (feito por [Danguafer](https://www.shadertoy.com/user/Danguafer)) em masterizar o karatê das funções. + + + +No *Próximo >>* capítulo, nós começaremos a usar nossos novos movimentos. Primeiro misturando cores e em seguida, desenhando formas. + +#### Exercício + +Dê uma olhada na seguinte tabela de equações feita por [Kynd](http://www.kynd.info/log/). Veja como ele está combinando as funções e suas propriedades para controlar os valores entre 0.0 e 1.0. Agora é a hora de você praticar replicando estas funções. Lembre-se que quanto mais você praticar, melhor será o seu karatê de shaders. + +![Kynd - www.flickr.com/photos/kynd/9546075099/ (2013)](kynd.png) + +#### Para sua caixa de ferramentas + +Aqui temos algumas ferramentas que facilitarão a visualização destes tipos de funções. + +* Grapher: Se você estiver em um MacOS, digite `grapher` no sua Busca Spotlight e você poderá usar essa ferramenta super conveniente. + +![OS X Grapher (2004)](grapher.png) + +* [GraphToy](http://www.iquilezles.org/apps/graphtoy/): mais uma vez [Iñigo Quilez](http://www.iquilezles.org) fez uma ferramenta para visualizar funções em GLSL em WebGL. + +![Iñigo Quilez - GraphToy (2010)](graphtoy.png) + +* [Shadershop](http://tobyschachman.com/Shadershop/): esta surpreendente ferramenta criada por [Toby Schachman](http://tobyschachman.com/) lhe ensinará como construir funções complexas em uma forma inacreditavelmente visual e intuitiva. + +![Toby Schachman - Shadershop (2014)](shadershop.png) diff --git a/06/README-pt.md b/06/README-pt.md new file mode 100644 index 0000000..a0705d8 --- /dev/null +++ b/06/README-pt.md @@ -0,0 +1,143 @@ +![Paul Klee - Color Chart (1931)](klee.jpg) + +## Cores + +Ainda não tivemos a chance de conversar sobre os tipos de vetores em GLSL. Mas antes de seguirmos adiante, é importante aprender mais sobre estas variáveis e o tópico de cores é uma ótima forma de os entendermos melhor. + +Se você está familiarizado com os paradigmas de programação orientada a objetos, você provavelmente tenha percebido que estamos acessando dados dentro de vetores como qualquer `struct` em C. + +```glsl +vec3 red = vec3(1.0,0.0,0.0); +red.x = 1.0; +red.y = 0.0; +red.z = 0.0; +``` + +Definir cores usando a notação *x*, *y* e *z* pode ser confuso, certo? Por esta razão, existem outras formas de acessar esta mesma informação mas com nomes diferentes. Os valores de `.x`, `.y` e `.z` podem também ser chamados de `.r`, `.g` e `.b`, e também, .`s`, `.t` e `.p`. (.`s`, `.t` e `.p`. normalmente são usados para coordenadas espaciais de uma textura, na qual veremos mais tarde em outro capítulo). Você pode também acessar os dados de um vetor usando o índice de posição: `[0]`, `[1]` e `[2]`. + +As próximas linhas mostram todas as formas de acessar os mesmos dados: + +```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; +``` + +Essas formas diferentes de apontar para variáveis dentro de vetores são apenas nomenclaturas criadas para ajudar você a criar um código mais limpo. Esta flexibilidade embutida em linguagem de shader é a porta para começar a pensar alternadamente em cores e coordenadas espaciais. + +Outro ótima característica dos tipos vetoriais em GLSL é que as propriedades podem ser combinadas em qualquer ordem, o que facilita a manipulação dos valores. Esta habilidade é chamada de *swizzle*. + +```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 +``` + +#### Para sua caixa de ferramentas + +Você pode não estar acostumado a escolher cores com números - isso pode ser bem não intuitivo. Felizmente, existem inúmeros excelentes programas que facilitarão seu trabalho. Encontre um que atende as suas necessidades e então pratique para conseguir entregar cores em `vec3` ou `vec4`. Por exemplo, aqui está os templates que uso no [Spectrum](http://www.eigenlogik.com/spectrum/mac): + +``` +vec3({{rn}},{{gn}},{{bn}}) +vec4({{rn}},{{gn}},{{bn}},1.0) +``` + +### Misturando cores + +Agora que você sabe como cores são definidas, chegou a hora de integrar isso com nosso conhecimento prévio. Em GLSL, existe uma função muito útil chamada [`mix()`](../glossary/?search=mix), que permite que você misture dois valores em porcentagens. Você consegue adivinhar em qual intervalo esta porcentagem é? Sim, estes valores vão de 0.0 a 1.0! O que é perfeito para você, depois destas longas horas praticando seus movimentos de karatê na cerca - É hora de usá-los! + +![](mix-f.jpg) + +Dê uma olhada na linha 18 do código a seguir e veja se nós conseguimos usar valores absolutos de uma onda seno pelo tempo para misturar `colorA` e `colorB`. + +
+ +Mostre suas habilidades ao: + +* Fazer uma transição expressiva entre as cores. Pense em uma emoção em particular, qual cor parece representá-la melhor? Como ela aparece? Como ela se esvai? Pense em outra emoção e determine uma cor para ela. Mude as cores do início de do final no código acima para corresponder aquelas emoções. Então, anime a transição usando funções. Robert Penner desenvolveu uma série sobre funções populares para animação computacional conhecido como [funções de suavização](http://easings.net/). você pode usar [este exemplo](../edit.php#06/easing.frag) como pesquisa e inspiração mas os melhores resultados virão das suas próprias funções. + +### Experimentando com degradês + +A função [`mix()`](../glossary/?search=mix) tem mais a oferecer. Ao invés de passar um único `float`, nós podemos passar uma variável do tipo que correspondente aos dois primeiros argumentos, neste caso, uma `vec3`. Fazendo isso, nós ganhamos controle sobre a porcentagem de mesclagem para cada canal de cor individualmente, `r`, `g` e `b`. + +![](mix-vec.jpg) + +Dê uma olhada no exemplo a seguir. Como os exemplos no capítulo anterior, nós estamos encaixando a transição na coordenada *x* normalizada e a visualizando com uma linha. Agora todos os canais seguem esta mesma linha. + +Agora, descomente a linha de número 25 e veja o que acontece. Então tente descomentar as linhas 26 e 27. Lembre-se que as linhas representam a intensidade de `colorA` e `colorB` a serem misturar por canal. + +
+ +Você provavelmente reconheceu os três modelos de funções que estamos usando nas linhas 25 a 27. Explore com eles! Agora é hora para experimentar e exibir suas habilidades do capítulo anterior e criar gradientes interessantes. Tente os seguintes exercícios: + +![William Turner - The Fighting Temeraire (1838)](turner.jpg) + +* Componha um gradiente que se assemelha com entardecer de William Turner + +* Anime uma transição entre o nascer do sol e o pôr do sol usando `u_time`. + +* Você consegue criar um arco-íris usando o que foi aprendido até agora? + +* Use a função `step()` para criar uma bandeira colorida. + +### HSB + +Nós não podemos falar sobre cores sem mencionar o espaço de cores. Como você provavelmente sabe, existem diferentes formas de organizar cores além de canais de vermelho, verde e azul. + +[HSB](http://en.wikipedia.org/wiki/HSL_and_HSV) vem de Hue(Matiz), Saturation(Saturação) e Brightness (Brilho ou Valor) e é uma forma muito mais intuitiva e útil de organizar cores. Pare um momento para ler as funções `rgb2hsv()` e `hsv2rgb()` no código a seguir. + +Mapeando a posição no eixo x para a matiz e a posição no eixo y para brilho, nós obtemos um lindo espectro de cores visíveis. Esta distribuição espacial de cores pode ser muito útil; é muito mais intuitivo para escolher uma cor com HSB do que com RGB + +
+ +### HSB em coordenadas populares + +HSB foi originalmente criada para ser representada em coordenadas polares (baseada em ângulo e raio) ao invés de coordenadas cartesianas (baseadas em x e y). Para mapear nossa função de HSB em coordenadas polares, precisamos obter o ângulo e a distância do centro da tela para a coordenada do píxel. Para isso, usaremos a função [`length()`](../glossary/?search=length) e [`atan(y,x)`](../glossary/?search=atan) (que é uma versão GLSL da comumente usada `atan2(y,x)`). + +Ao utilizar vetores e funções trigonométricas, `vec2`, `vec3` e `vec4` são tratados como vetores mesmo quando elas representam cores. Nós começaremos a tratar cores e vetores de forma similar e você verá que esta flexibilidade conceitual é muito poderosa. + +**Nota:** Se você estiver se perguntando, existem mais funções geométricas além de [`length`](../glossary/?search=length), como [`distance()`](../glossary/?search=distance), [`dot()`](../glossary/?search=dot), [`cross`](../glossary/?search=cross), [`normalize()`](../glossary/?search=normalize), [`faceforward()`](../glossary/?search=faceforward), [`reflect()`](../glossary/?search=reflect) e [`refract()`](../glossary/?search=refract). Também em GLSL tem funções relacionais especiais para vetorais como: [`lessThan()`](../glossary/?search=lessThan), [`lessThanEqual()`](../glossary/?search=lessThanEqual), [`greaterThan()`](../glossary/?search=greaterThan), [`greaterThanEqual()`](../glossary/?search=greaterThanEqual), [`equal()`](../glossary/?search=equal) e [`notEqual()`](../glossary/?search=notEqual). + +Uma vez que obtemos o ângulo e a tamanho, precisamos "normalizar" seus valores para o intervalo entre 0.0 e 1.0. Na linha 27, [`atan(y,x)`](../glossary/?search=atan) retornará um ângulo em radianos entre -PI e PI (-3.14 a 3.14), então precisamos dividir este número por `TWO_PI` (definido no topo do código) para obtermos valores entre -0.5 até 0.5, que, com uma simples adição, nós mudamos para o intervalo desejado de 0.0 a 1.0. O raio retornará um máximo de 0.5 (porque nós estamos calculando a distância a partir do centro da tela), então nós precisamos dobrar este intervalo (multiplicando por dois) para obter um máximo de 1.0. + +Como você pode observar, nosso jogo aqui é sobre transformar e mapear intervalos para 0.0 a 1.0 que gostamos. + +
+ +Tente os seguintes exercícios: + +* Modifique o exemplo de coordenadas polares para obter uma roda de cores que gira, assim como o ícone de espera do mouse. + +* Use a modelagem de função junto com a função de conversão de HSB para RGB para expandir um valor da matiz em particular e comprimir o resto. + +![William Home Lizars - Red, blue and yellow spectra, with the solar spectrum (1834)](spectrums.jpg) + +* Se você olhar de perto na roda de cores usada em seletores de cor (veja a imagem abaixo), elas usam um diferente espectro de acordo com o espaço de cores em RYB. Por exemplo, a cor oposta ao vermelho deve ser verde, mas no nosso exemplo é ciano. Você consegue encontrar um jeito de consertar isso para parecer exatamente com a imagem a baixo? [Dica: este é um grande momento para usar modelagem de funções.] + +![](colorwheel.png) + +* Leia [Josef Albers' book Interaction of Color](http://www.goodreads.com/book/show/111113.Interaction_of_Color) (EM INGLÊS) e use os seguintes exemplos de shader como prática. + +
+ +#### Nota sobre funções e argumentos + +Antes de irmos para o próximo capítulo, vamos parar e rebobinar. Volte e dê uma olhada nas funções nos exemplos anteriores. Você vai perceber um `in` antes dos tipos de argumentos. Isso é um *qualificador*](http://www.shaderific.com/glsl-qualifiers/#inputqualifier) e neste caso, especifica que a variável é somente leitura. Em exemplos futuros, veremos que também é possível definir argumentos como `out` ou `inout`. Este último, `inout`, é conceitualmente similar a passar um argumento pela referência na qual nos dará a possibilidade de modificar uma variável passada. + +```glsl +int newFunction(in vec4 aVec4, // read-only + out vec3 aVec3, // write-only + inout int aInt); // read-write +``` + +Você pode não acreditar, mas agora nós temos todos os elementos para fazer desenhos legais. No próximo capítulo, aprenderemos como combinar todos os truques para criar formas geométricas *mesclando* o espaço. Isso mesmo... *mesclando* espaço.