mirror of
https://github.com/patriciogonzalezvivo/thebookofshaders
synced 2024-11-08 01:10:27 +00:00
Add a portuguese translation for chapter 4, 7 and 8.
This commit is contained in:
parent
5334b5eb18
commit
1c0f3ae1ed
188
04/README-pt.md
Normal file
188
04/README-pt.md
Normal file
@ -0,0 +1,188 @@
|
|||||||
|
## Rodando seu shader
|
||||||
|
|
||||||
|
Como parte da construção deste livro e minha prática artística, eu criei um ecossistema de ferramentas para criar, visualizar, compartilhar e curar shaders. Estas ferramentas funcionam de forma consistente nas plataformas Linux, Desktop, MacOS, [Raspberry Pi](https://www.raspberrypi.org/) e navegadores sem a necessidade de alterar o código.
|
||||||
|
|
||||||
|
**Visualize**: Todos os exemplos deste livro são exibidos usando [glslCanvas](https://github.com/patriciogonzalezvivo/glslCanvas) que facilita o processo de rodar o shader independentemente.
|
||||||
|
|
||||||
|
```html
|
||||||
|
<canvas class="glslCanvas" data-fragment-url=“yourShader.frag" data-textures=“yourInputImage.png” width="500" height="500"></canvas>
|
||||||
|
```
|
||||||
|
Como você pode ver, só é preciso um elemento `canvas` com a classe `class="glslCanvas"` e a url do seu shader em `data-fragment-url`. Saiba mais [aqui](https://github.com/patriciogonzalezvivo/glslCanvas).
|
||||||
|
|
||||||
|
Se você é como eu, você provavelmente quer rodar shaders diretamente do console, neste caso, você deve dar uma olhada no [glslViewer](https://github.com/patriciogonzalezvivo/glslViewer). Esta aplicação permite que voc6e incorpore shaders em seus scripts `bash` ou nas pipelines de unix e os-use de uma forma similar a [ImageMagick](http://www.imagemagick.org/script/index.php). [glslViewer](https://github.com/patriciogonzalezvivo/glslViewer) também é uma ótima forma de compilar seus shaders para [Raspberry Pi](https://www.raspberrypi.org/), razão na qual [openFrame.io](http://openframe.io/) o usa para exibir suas artes. Veja mais sobre a aplicação [aqui](https://github.com/patriciogonzalezvivo/glslViewer).
|
||||||
|
|
||||||
|
```bash
|
||||||
|
glslViewer yourShader.frag yourInputImage.png —w 500 -h 500 -s 1 -o yourOutputImage.png
|
||||||
|
```
|
||||||
|
|
||||||
|
**Crie**: Para iluminar a experiência de programar shaders, eu fiz um editor online chamado [glslEditor](https://github.com/patriciogonzalezvivo/glslEditor). Este editor é embedado nos exemplos ao vivo do livro, ele trás uma série de widgets úteis tornando mais tangóvei a experiência abstrata de trabalhar com códigos em glsl. Você pode também rodá-los numa aplicação web independente em [editor.thebookofshaders.com/](http://editor.thebookofshaders.com/). Aprenda mais sobre isso [aqui
|
||||||
|
](https://github.com/patriciogonzalezvivo/glslEditor).
|
||||||
|
|
||||||
|
![](glslEditor-01.gif)
|
||||||
|
|
||||||
|
Se você prefere trabalhar offline usando [SublimeText](https://www.sublimetext.com/), você pode instalar este [pacote do glslViewer](https://packagecontrol.io/packages/glslViewer). Veja mais sobre [aqui](https://github.com/patriciogonzalezvivo/sublime-glslViewer).
|
||||||
|
|
||||||
|
![](glslViewer.gif)
|
||||||
|
|
||||||
|
**Compartilhe**: o editor online ([editor.thebookofshaders.com/](http://editor.thebookofshaders.com/)) pode compartilhar seus shaders! Ambos, a versão incorporada e a independente, têm um botão de export onde você receberá uma URL única para seu shader. Também existe a opção de exportar diretamente para um [openFrame.io](http://openframe.io/).
|
||||||
|
|
||||||
|
![](glslEditor-00.gif)
|
||||||
|
|
||||||
|
**Cure**: Compartilhar seu código é só o começo para compartilhar seu shader como arte! Ao lado da opção para o [openFrame.io](http://openframe.io/), eu fiz uma ferramenta para curar shaders em uma galeria que pode ser incoporada em qualquer site, seu nome é [glslGallery](https://github.com/patriciogonzalezvivo/glslGallery). Veja mais [aqui](https://github.com/patriciogonzalezvivo/glslGallery).
|
||||||
|
|
||||||
|
## Rodando seus shaders no seu framework favorito
|
||||||
|
|
||||||
|
No caso de você já ter experiência em um framework como: [Processing](https://processing.org/), [Three.js](http://threejs.org/) ou [OpenFrameworks](http://openframeworks.cc/), você está provavelmente empolgado para testar shaders com plataformas que você se sente confortável. A seguir, vemos exemplos de como configurar shaders em algumas frameworks populares com as mesmas uniforms que vamos estar usando durante este livro. (No [repositório do Github deste para este capítulo](https://github.com/patriciogonzalezvivo/thebookofshaders/tree/master/04), você encontrará o código fonte completo para estas três frameworks.)
|
||||||
|
|
||||||
|
### Em ***Three.js***
|
||||||
|
|
||||||
|
O brilhante e muito humilde Ricardo Cabello (também conhecido como [MrDoob](https://twitter.com/mrdoob) ) tem desenvolvido junto com outros [contribuidores](https://github.com/mrdoob/three.js/graphs/contributors) provavelmente uma das mais famosas frameworks de WebGL, chamada [Three.js](http://threejs.org/). Você encontrará muitos exemplos, tutoriais e livros que te ensinarão como usar esta biblioteca em Javascript para criar bons gráficos 3D.
|
||||||
|
|
||||||
|
Abaixo, temos um exemplo de HTML e JS que você precisa para começar usando shaders em three.js. Preste atenção no script `id="fragmentShader"`, lá é onde você pode copiar os shaders que você encontrar neste livro.
|
||||||
|
|
||||||
|
```html
|
||||||
|
<body>
|
||||||
|
<div id="container"></div>
|
||||||
|
<script src="js/three.min.js"></script>
|
||||||
|
<script id="vertexShader" type="x-shader/x-vertex">
|
||||||
|
void main() {
|
||||||
|
gl_Position = vec4( position, 1.0 );
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<script id="fragmentShader" type="x-shader/x-fragment">
|
||||||
|
uniform vec2 u_resolution;
|
||||||
|
uniform float u_time;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
vec2 st = gl_FragCoord.xy/u_resolution.xy;
|
||||||
|
gl_FragColor=vec4(st.x,st.y,0.0,1.0);
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<script>
|
||||||
|
var container;
|
||||||
|
var camera, scene, renderer;
|
||||||
|
var uniforms;
|
||||||
|
|
||||||
|
init();
|
||||||
|
animate();
|
||||||
|
|
||||||
|
function init() {
|
||||||
|
container = document.getElementById( 'container' );
|
||||||
|
|
||||||
|
camera = new THREE.Camera();
|
||||||
|
camera.position.z = 1;
|
||||||
|
|
||||||
|
scene = new THREE.Scene();
|
||||||
|
|
||||||
|
var geometry = new THREE.PlaneBufferGeometry( 2, 2 );
|
||||||
|
|
||||||
|
uniforms = {
|
||||||
|
u_time: { type: "f", value: 1.0 },
|
||||||
|
u_resolution: { type: "v2", value: new THREE.Vector2() },
|
||||||
|
u_mouse: { type: "v2", value: new THREE.Vector2() }
|
||||||
|
};
|
||||||
|
|
||||||
|
var material = new THREE.ShaderMaterial( {
|
||||||
|
uniforms: uniforms,
|
||||||
|
vertexShader: document.getElementById( 'vertexShader' ).textContent,
|
||||||
|
fragmentShader: document.getElementById( 'fragmentShader' ).textContent
|
||||||
|
} );
|
||||||
|
|
||||||
|
var mesh = new THREE.Mesh( geometry, material );
|
||||||
|
scene.add( mesh );
|
||||||
|
|
||||||
|
renderer = new THREE.WebGLRenderer();
|
||||||
|
renderer.setPixelRatio( window.devicePixelRatio );
|
||||||
|
|
||||||
|
container.appendChild( renderer.domElement );
|
||||||
|
|
||||||
|
onWindowResize();
|
||||||
|
window.addEventListener( 'resize', onWindowResize, false );
|
||||||
|
|
||||||
|
document.onmousemove = function(e){
|
||||||
|
uniforms.u_mouse.value.x = e.pageX
|
||||||
|
uniforms.u_mouse.value.y = e.pageY
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function onWindowResize( event ) {
|
||||||
|
renderer.setSize( window.innerWidth, window.innerHeight );
|
||||||
|
uniforms.u_resolution.value.x = renderer.domElement.width;
|
||||||
|
uniforms.u_resolution.value.y = renderer.domElement.height;
|
||||||
|
}
|
||||||
|
|
||||||
|
function animate() {
|
||||||
|
requestAnimationFrame( animate );
|
||||||
|
render();
|
||||||
|
}
|
||||||
|
|
||||||
|
function render() {
|
||||||
|
uniforms.u_time.value += 0.05;
|
||||||
|
renderer.render( scene, camera );
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
```
|
||||||
|
|
||||||
|
### Em **Processing**
|
||||||
|
|
||||||
|
Criado por [Ben Fry](http://benfry.com/) e [Casey Reas](http://reas.com/) em 2001, [Processing](https://processing.org/) é um ambiente extremamente simples e poderoso para dar seus primeiros passos em programação (ao menos, foi para mim). [Andres Colubri](https://codeanticode.wordpress.com/)fez as atualizações mais importantes ao openGL e vídeo em Processing, facilitando o uso de GLSL shaders neste ambiente amigável. Processing buscará pelo shader `"shader.frag"` na pasta `data` do seu sketch. Tenha certeza de ter copiar os shaders que você encontrar aqui para a pasta e renomear os arquivos.
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
PShader shader;
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
size(640, 360, P2D);
|
||||||
|
noStroke();
|
||||||
|
|
||||||
|
shader = loadShader("shader.frag");
|
||||||
|
}
|
||||||
|
|
||||||
|
void draw() {
|
||||||
|
shader.set("u_resolution", float(width), float(height));
|
||||||
|
shader.set("u_mouse", float(mouseX), float(mouseY));
|
||||||
|
shader.set("u_time", millis() / 1000.0);
|
||||||
|
shader(shader);
|
||||||
|
rect(0,0,width,height);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Para que o shader funcione nas versões anteriores a 2.1, você precisa adicionar as seguintes linhas de código no começo do seu shader: `#define PROCESSING_COLOR_SHADER`. Algo parecido com isso:
|
||||||
|
|
||||||
|
```glsl
|
||||||
|
#ifdef GL_ES
|
||||||
|
precision mediump float;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define PROCESSING_COLOR_SHADER
|
||||||
|
|
||||||
|
uniform vec2 u_resolution;
|
||||||
|
uniform vec3 u_mouse;
|
||||||
|
uniform float u_time;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
vec2 st = gl_FragCoord.st/u_resolution;
|
||||||
|
gl_FragColor = vec4(st.x,st.y,0.0,1.0);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Para mais informação sobre shaders em Processing, dê uma olhada neste [tutorial](https://processing.org/tutorials/pshader/).
|
||||||
|
|
||||||
|
### Em **openFrameworks**
|
||||||
|
|
||||||
|
Todos tem um lugar no qual se sentem confortáveis, no meu caso, ainda é na [comunidade de openFrameworks](http://openframeworks.cc/). Esta framework C++ engloba OpenGL e outras bibliotecas C++ open source. É muito parecida com Processing, mas com as complicações óbvias de lidar com compiladores C++. Do mesmo jeito que Processing, openFrameworks procura pelos seus arquivos de shader na pasta data, então não se esqueça de copiar os arquivos `.frag` que você quer usar e os renomear quando carregá-los.
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
void ofApp::draw(){
|
||||||
|
ofShader shader;
|
||||||
|
shader.load("","shader.frag");
|
||||||
|
|
||||||
|
shader.begin();
|
||||||
|
shader.setUniform1f("u_time", ofGetElapsedTimef());
|
||||||
|
shader.setUniform2f("u_resolution", ofGetWidth(), ofGetHeight());
|
||||||
|
ofRect(0,0,ofGetWidth(), ofGetHeight());
|
||||||
|
shader.end();
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Para mais informação sobre shaders em openFrameworks, vá para este [excelente tutorial](http://openframeworks.cc/ofBook/chapters/shaders.html) feito por [Joshua Noble](http://thefactoryfactory.com/).
|
229
07/README-pt.md
Normal file
229
07/README-pt.md
Normal file
@ -0,0 +1,229 @@
|
|||||||
|
![Alice Hubbard, Providence, United States, ca. 1892. Photo: Zindman/Freemont.](froebel.jpg)
|
||||||
|
|
||||||
|
## Formas
|
||||||
|
|
||||||
|
Finalmente! Estávamos aperfeiçoando nossas habilidades para esse momento. Você aprendeu a maioria dos fundamentos de GLSL, tipos e funções. Você praticou e praticou suas equações. Agora é a hora de juntarmos tudo. Você está pronto para esse desafio! Neste capítulo, você aprenderá como desenhar formas simples de uma jeito paralelo e procedural.
|
||||||
|
|
||||||
|
## Retângulo
|
||||||
|
|
||||||
|
Supondo que temos um papel quadriculado como aqueles que nós usávamos em matemática e a nossa lição de casa é desenhar um quadrado. O tamanho do papel é de 10x10 e o quadrado deve ser de 8x8. O que você faria?
|
||||||
|
|
||||||
|
![](grid_paper.jpg)
|
||||||
|
|
||||||
|
Você pintaria tudo exceto a primeira e a última linha e a primeira e a última coluna, certo?
|
||||||
|
|
||||||
|
Como isso se relaciona com shaders? Cada pequeno quadrado do nosso papel quadriculado é uma thread (um píxel). Cada quadradinho sabe sua posição, como as coordenadas de um tabuleiro de xadrez. Nos capítulos anteriores, nós mapeamos *x* e *y* para os canais *red* e *green* de cor, nós aprendemos como usar o pequeno território bidimensional entre 0.0 e 1.0. Como podemos usar isso para desenhar um quadrado centralizado no meio da nossa tela?
|
||||||
|
|
||||||
|
Vamos começar rascunhando um pseudocódigo que usa a declaração de `if` sobre o intervalo espacial. Os princípios para fazer isso são extraordinariamente similares ao jeito que pensamos no papel quadriculado.
|
||||||
|
|
||||||
|
```glsl
|
||||||
|
if ( (X GREATER THAN 1) AND (Y GREATER THAN 1) )
|
||||||
|
paint white
|
||||||
|
else
|
||||||
|
paint black
|
||||||
|
```
|
||||||
|
|
||||||
|
Agora que temos uma ideia melhor de como isso funcionará, vamos substituir a declaração do `if` com [`step()`](../glossary/?search=step), e ao invés de usar 10x10, vamos usar os valores normalizados entre 0.0 e 1.0:
|
||||||
|
|
||||||
|
```glsl
|
||||||
|
uniform vec2 u_resolution;
|
||||||
|
|
||||||
|
void main(){
|
||||||
|
vec2 st = gl_FragCoord.xy/u_resolution.xy;
|
||||||
|
vec3 color = vec3(0.0);
|
||||||
|
|
||||||
|
// Each result will return 1.0 (white) or 0.0 (black).
|
||||||
|
float left = step(0.1,st.x); // Similar to ( X greater than 0.1 )
|
||||||
|
float bottom = step(0.1,st.y); // Similar to ( Y greater than 0.1 )
|
||||||
|
|
||||||
|
// The multiplication of left*bottom will be similar to the logical AND.
|
||||||
|
color = vec3( left * bottom );
|
||||||
|
|
||||||
|
gl_FragColor = vec4(color,1.0);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
A função [`step()`](../glossary/?search=step) fará com que todos os píxeis abaixo de 0.1 fiquem pretos (`vec3(0.0)`) e o acima, brancos (`vec3(1.0)`). A multiplicação entre o lado `esquerdo` e `inferior` funciona como uma operação lógica `AND`, onde ambos precisam ser 1.0 para retornar 1.0. Isso desenhará duas linhas pretas, uma abaixo e a outra do lado esquerdo da nossa tela.
|
||||||
|
|
||||||
|
![](rect-01.jpg)
|
||||||
|
|
||||||
|
No código anterir, nós repetimos a estrutura para cada eixo (esquerda e inferior). Podemos economizar algumas linhas de código passando dois valores diretamente ao [`step()`](../glossary/?search=step) em vez de um. Algo como:
|
||||||
|
|
||||||
|
```glsl
|
||||||
|
vec2 borders = step(vec2(0.1),st);
|
||||||
|
float pct = borders.x * borders.y;
|
||||||
|
```
|
||||||
|
|
||||||
|
Até agora, nós apenas desenhamos duas bordas (inferior-esquerda) do nosso retângulo. Vamos desenhar as outras duas (superior-direita). Dê uma olhada no código a seguir:
|
||||||
|
|
||||||
|
<div class="codeAndCanvas" data="rect-making.frag"></div>
|
||||||
|
|
||||||
|
Descomente as *linhas 21-22* e veja como nós invertamos as coordenadas `st` e repetimos a mesma função [`step()`](../glossary/?search=step). Desta forma, o `vec2(0.0,0.0)` será no canto superior direito. Esta é o equivalente digital a girar a página e repetir o procedimento anterior.
|
||||||
|
|
||||||
|
![](rect-02.jpg)
|
||||||
|
|
||||||
|
Tome nota que nas *linhas 18 e 22*, todos os lados estão senho multiplicados juntos. Isso é equivalente a escrever:
|
||||||
|
|
||||||
|
```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);
|
||||||
|
```
|
||||||
|
|
||||||
|
Interessante, não é? Essa técnica é sobre usar [`step()`](../glossary/?search=step) e multiplicação para operações lógicas e girar as coordenadas.
|
||||||
|
|
||||||
|
Antes de continuar, tente os seguintes exercícios:
|
||||||
|
|
||||||
|
* Mude o tamanho e as proporções do retângulo.
|
||||||
|
|
||||||
|
* Experimente no mesmo código usar [`smoothstep()`](../glossary/?search=smoothstep) em vez de [`step()`](../glossary/?search=step). Note que ao trocar os valores, você pode ir de bordas borradas a elegantes bordas suaves.
|
||||||
|
|
||||||
|
* Faça uma outra implementação que utiliza [`floor()`](../glossary/?search=floor).
|
||||||
|
|
||||||
|
* Escolha a implementação que você mais gostou e faça uma função dela para que você possa usar novamente no futuro. Faça sua função ser flexível e eficiente.
|
||||||
|
|
||||||
|
* Crie uma outra função que apenas desenhe o contorno do retângulo.
|
||||||
|
|
||||||
|
* Como você faria para mover e posicionar diferentes retângulos na mesma tela? Se você descobrir como, mostre suas habilidades fazendo uma composição de retângulos e cores que se pareça com uma pintura de [Piet Mondrian](http://en.wikipedia.org/wiki/Piet_Mondrian).
|
||||||
|
|
||||||
|
![Piet Mondrian - Tableau (1921)](mondrian.jpg)
|
||||||
|
|
||||||
|
## Círculos
|
||||||
|
|
||||||
|
Desenhar quadrados num papel quadriculado e retângulos em coordenadas cartesianas é fácil, entretanto círculos exigem uma outra abordagem, principalmente porque precisamos de um algoritmo "por-píxel". Uma solução é *remapear* as coordenadas espaciais para podermos usar a função [`step()`](../glossary/?search=step) para desenhar um círculo.
|
||||||
|
|
||||||
|
Como? Vamos começar voltando para aula de matemática e o papel quadriculado, quando nós abríamos um compasso com o raio do círculo, pressionávamos o ponto central do compasso e então, traçávamos o contorno do círculo com um simples giro.
|
||||||
|
|
||||||
|
![](circle.jpg)
|
||||||
|
|
||||||
|
Existem várias formas de calcular aquela distância. A forma mais fácil usa a função [`distance()`](../glossary/?search=distance), que internamente computa a distância ([`length()`](../glossary/?search=length)) da diferença entre dois pontos (neste caso, as coordenadas do píxel e o centro da tela). A função `length()` não é nada além de um atalho para a [equação da hipotenusa](http://en.wikipedia.org/wiki/Hypotenuse) que usa raiz quadrada internamente.
|
||||||
|
|
||||||
|
![](hypotenuse.png)
|
||||||
|
|
||||||
|
Você pode usar [`distance()`](../glossary/?search=distance), [`length()`](../glossary/?search=length) ou [`sqrt()`](../glossary/?search=sqrt) para calcular a distância do centro da tela. O código a seguir contém estas três funções e o fato nem-tão-surpreendente que cada uma retorna exatamente o mesmo resultado.
|
||||||
|
|
||||||
|
* Comente e descomente as linhas para experimentar diferentes formas de obter o mesmo resultado.
|
||||||
|
|
||||||
|
<div class="codeAndCanvas" data="circle-making.frag"></div>
|
||||||
|
|
||||||
|
No exemplo anterior, nós mapeamos a distância até o centro da tela para a luminosidade da cor do pixel. Quanto mais perto o pixel está do centro, menor (mais escuro) será o valor que ele possui. Note que os valores não vão tão altos porque a distância do centro ( `vec2(0.5, 0.5)` ) mal chega em 0.5. Contemple o mapa e reflita:
|
||||||
|
|
||||||
|
* O que você pode inferir sobre ele?
|
||||||
|
|
||||||
|
* Como podemos usá-lo para desenhar um círculo?
|
||||||
|
|
||||||
|
* Modifique o código acima para conter o gradiente circular inteiramente dentro da tela.
|
||||||
|
|
||||||
|
### Campo de distância (Distance Field)
|
||||||
|
|
||||||
|
Também podemos visualizar o exemplo acima como um mapa de altitude, onde as partes mais escuras indicam áreas mais altas. O gradiente nos mostra algo similar ao padrão feito por um cone. Imagine você mesmo no topo deste cone. A distância horizontal até o contorno do cone é 0.5. Está será constante em todas as direções. Ao escolher onde "cortar" o cone, você obterá uma superfície circular maior ou menor.
|
||||||
|
|
||||||
|
![](distance-field.jpg)
|
||||||
|
|
||||||
|
Basicamente, nós estamos usando uma re-interpretação do espaço (baseando na distância até o centro) para construir formas. Esta técnica é conhecida como "campo de distância" e é usada de diferentes formas desde contornos em fontes até gráficos 3D.
|
||||||
|
|
||||||
|
Faça os seguintes exercícios:
|
||||||
|
|
||||||
|
* Use [`step()`](../glossary/?search=step) para pintar tudo acima de 0.5 de branco e tudo abaixo de preto.
|
||||||
|
|
||||||
|
* Inverta as cores entre fundo e primeiro plano.
|
||||||
|
|
||||||
|
* Usando [`smoothstep()`](../glossary/?search=smoothstep), teste valores diferentes para obter bordas suaves em seu círculo.
|
||||||
|
|
||||||
|
* Quando você estiver satisfeito com a sua implementação, crie uma função dela para que você possa reusar no futuro.
|
||||||
|
|
||||||
|
* Adicione cores ao círculo.
|
||||||
|
|
||||||
|
* Você consegue animar seu círculo para crescer e encolher simulando um coração batendo? (Você pode se inspirar na animação no capítulo anterior.)
|
||||||
|
|
||||||
|
* E quanto a mover este círculo? Você consegue mover ele e posicionar diferentes círculos na tela?
|
||||||
|
|
||||||
|
* O que acontece se você combinar campos de distância usando diferentes funções e operações?
|
||||||
|
|
||||||
|
```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)));
|
||||||
|
```
|
||||||
|
|
||||||
|
* Faça três composições usando esta técnica. Se elas forem animadas, melhor ainda!
|
||||||
|
|
||||||
|
#### Para a sua caixa de ferramentas
|
||||||
|
|
||||||
|
Ao falarmos de poder computacional, a função [`sqrt()`](../glossary/?search=sqrt) - e todas funções que dependem dela - podem ser custosas. Aqui está outra forma de criar um campo de distância circular usando [`dot()`](../glossary/?search=dot) (produto escalar).
|
||||||
|
|
||||||
|
<div class="codeAndCanvas" data="circle.frag"></div>
|
||||||
|
|
||||||
|
### Propriedades úteis de um Campo de Distância
|
||||||
|
|
||||||
|
![Zen garden](zen-garden.jpg)
|
||||||
|
|
||||||
|
Campos de distância podem ser usados para desenhar praticamente tudo. Obviamente quanto mais complexa é a forma, mais complicado sua equação será, mas uma vez que você tem a formula para fazer um campo de distância de uma forma em particular, e torna muito fácil combiná-la ou aplicar efeitos a ela, como suavizar suas bordas ou multiplicar o contorno. Por esta razão, campos de distância são populares em renderização de fontes, como [Mapbox GL Labels](https://www.mapbox.com/blog/text-signed-distance-fields/), [Matt DesLauriers](https://twitter.com/mattdesl) [Material Design Fonts](http://mattdesl.svbtle.com/material-design-on-the-gpu) e [como descrito no capítulo 7 de iPhone 3D Programming, O’Reilly](http://chimera.labs.oreilly.com/books/1234000001814/ch07.html#ch07_id36000921).
|
||||||
|
|
||||||
|
Dê uma olhada no código a seguir.
|
||||||
|
|
||||||
|
<div class="codeAndCanvas" data="rect-df.frag"></div>
|
||||||
|
|
||||||
|
Começamos movendo o sistema de coordenadas ao centro e diminuindo ele pela metade para remapear os valores de posição para serem entre -1 e 1. Também, na *linha 24*, nós estamos visualizando os valores de um campo de distância usando uma função [`fract()`](../glossary/?search=fract), tornando fácil ver o padrão que eles criam. O padrão do campo de distância se repete novamente como aneis em um jardim Zen.
|
||||||
|
|
||||||
|
Vamos dar uma olhada na fóruma da *linha 19*. Lá nós estamos calculando a distância até a posição em `(.3,.3)` ou `vec3(.3)` em todos os quatro quadrantes (que é o que [`abs()`](../glossary/?search=abs) está fazendo lá).
|
||||||
|
|
||||||
|
Se você descomentar a *linha 20*, você notará que nós estamos combinando as distâncias destes quatro pontos usando [`min()`](../glossary/?search=min) com 0. O resultado produzirá um interessante padrão.
|
||||||
|
|
||||||
|
Agora, experimente descomentar a *linha 21*; Estamos fazendo o mesmo processo mas usando a função [`max()`](../glossary/?search=max). O resultado será um retângulo com bordas arredondadas. Note como os anéis do campo de distância se suavizam quanto mais eles se distanciam do centro.
|
||||||
|
|
||||||
|
Termine descomentando da * linha 27 até 29* uma por uma para entender os diferentes usos de um padrão de campo de distância.
|
||||||
|
|
||||||
|
### Formas polares
|
||||||
|
|
||||||
|
![Robert Mangold - Untitled (2008)](mangold.jpg)
|
||||||
|
|
||||||
|
No capítulo sobre cor, nós mapeamos as coordenadas cartesianas em coordenadas polares calculando o *raio* e *ângulo* de cada pixel com a seguinte fórmula:
|
||||||
|
|
||||||
|
```glsl
|
||||||
|
vec2 pos = vec2(0.5)-st;
|
||||||
|
float r = length(pos)*2.0;
|
||||||
|
float a = atan(pos.y,pos.x);
|
||||||
|
```
|
||||||
|
|
||||||
|
Nós usamos parte dessa fórmula no começo deste capítulo para desenhar um círculo. Nós calculamos a distância até o centro usando [`length()`](../glossary/?search=length). Agora que nós entendemos sobre campos de distância, nós podemos aprender outra forma de desenhar formas usando coordenadas polares.
|
||||||
|
|
||||||
|
Está técnica é um pouco restrita, mas muito simples. Ela consiste em mudar o raio do círculo baseado no ângulo para chegar em formas diferentes. Como faremos a modulação? Sim, usando a modelagem de funções!
|
||||||
|
|
||||||
|
Abaixo, você verá as mesmas funções em um gráfico cartesiano e em um exemplo de shader em coordenadas polares (entre as *linhas 21 e 25*). Descomente as funções uma a uma, prestando atenção nas relações entre um sistema de coordenadas e o outro.
|
||||||
|
|
||||||
|
<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>
|
||||||
|
|
||||||
|
Tente:
|
||||||
|
|
||||||
|
* Animar estas formas.
|
||||||
|
|
||||||
|
* Combinar diferentes funções modeladas para *cortar buracos* na forma e fazer flores, flocos de neve e engrenagens.
|
||||||
|
|
||||||
|
* Use a função `plot()` que nós estávamos usando no *Capítulo de Modelagem de Funções* para desenhar apenas o contorno.
|
||||||
|
|
||||||
|
### Combinando poderes
|
||||||
|
|
||||||
|
Agora que nós aprendemos como modular o raio de um círculo de acordo com o ângulo usando [`atan()`](../glossary/?search=atan) para desenhar formas diferentes, aprendemos como usar `atan()` com campos de distância e a aplicar todos os truques e efeitos possíveis com campos de distância.
|
||||||
|
|
||||||
|
O truque usará o número de lados de um polígono para construir um campo de distância usando coordenadas polares. Confira [o código abaixo](http://thndl.com/square-shaped-shaders.html) from [Andrew Baldwin](https://twitter.com/baldand).
|
||||||
|
|
||||||
|
<div class="codeAndCanvas" data="shapes.frag"></div>
|
||||||
|
|
||||||
|
* Usando este exemplo, faça uma função que recebe a posição e o número de ângulos da forma desejada e retorna um campo de distância do valor.
|
||||||
|
|
||||||
|
* Misture campos de distância juntos usando [`min()`](../glossary/?search=min) e [`max()`](../glossary/?search=max).
|
||||||
|
|
||||||
|
* Escola um logo geométrico para recriar usando campos de distância.
|
||||||
|
|
||||||
|
Parabéns! Você conseguiu passar pela parte difícil! Agora descanse um pouco e deixe esses conceitos se fixarem - Aqui não é tão fácil de desenhar formas simples como em Processing. Na terra dos shaders, pode ser uma tarefa cansativa para se adaptar a este novo paradigma de programação para desenhar formas.
|
||||||
|
|
||||||
|
Agora que você sabe como desenhar formas, tenho certeza que novas ideias vão pipocar na sua mente. No próximo capítulo, você aprenderá como mover, rotacionar e escalonar formas. Isso vai permitir que você faça suas composições!
|
101
08/README-pt.md
Normal file
101
08/README-pt.md
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
## Matrizes 2D
|
||||||
|
|
||||||
|
<canvas id="custom" class="canvas" data-fragment-url="matrix.frag" width="700px" height="200px"></canvas>
|
||||||
|
|
||||||
|
### Translação
|
||||||
|
|
||||||
|
No capítulo anterior, nós aprendemos como criar algumas formas - o truque para mover estas formas é mover o próprio sistema de coordenadas. Nós fazemos isso simplesmente adicionando um vetor às variáveis ```st``` que contem a localização de cada fragmento. Isso fará com que todo o espaço de coordenadas se mova.
|
||||||
|
|
||||||
|
![](translate.jpg)
|
||||||
|
|
||||||
|
Isso é mais fácil de enxergar do que explicar, veja você mesmo:
|
||||||
|
|
||||||
|
* Descomente as linhas 35 do código abaixo e veja como o próprio espaço se move.
|
||||||
|
|
||||||
|
<div class="codeAndCanvas" data="cross-translate.frag"></div>
|
||||||
|
|
||||||
|
Agora implemente os seguintes exercícios:
|
||||||
|
|
||||||
|
* Usando ```u_time``` junto com a modelagem de função, mova a pequena cruz de uma forma interessante. Procure por uma específica qualidade de movimento que você se interessa e tente fazer com que a cruz se mova da mesma forma. Se lembrando de algo suave do "mundo real" primeiramente pode ser útil - Pode ser as ondas que vem e vão de um pêndulo, uma bola quicando, um carro acelerando uma bicicleta parando.
|
||||||
|
|
||||||
|
### Rotações
|
||||||
|
|
||||||
|
Para rotacionarmos objetos, também precisamos mexer todo o sistema espacial. Para isso, nós iremos usar uma [matriz](http://en.wikipedia.org/wiki/Matrix_%28mathematics%29). Uma matriz é um conjunto organizado de números em linhas e colunas. Vetores são multiplicados por matrizes seguindo um preciso conjunto de ordens para modificar os valores do vetor em uma forma particular.
|
||||||
|
|
||||||
|
[![Artigo da wikipedia sobre matrizes (matemática) ](matrixes.png)](https://en.wikipedia.org/wiki/Matrix)
|
||||||
|
|
||||||
|
GLSL tem um suporte nativo para matrizes de duas, três e quatro dimensões: [```mat2```](../glossary/?search=mat2) (2x2), [```mat3```](../glossary/?search=mat3) (3x3) e [```mat4```](../glossary/?search=mat4) (4x4). GLSL também suporta multiplicação de matrizes (```*```) e uma função específica para matriz ([```matrixCompMult()```](../glossary/?search=matrixCompMult)).
|
||||||
|
|
||||||
|
Baseado em como matrizes se comportam, é possível construir matrizes para produzir comportamentos específicos. Por exemplo, nós podemos usar matriz para transladar um vetor:
|
||||||
|
|
||||||
|
![](3dtransmat.png)
|
||||||
|
|
||||||
|
E mais interessante ainda, podemos usar uma matriz para rotacionar um sistema de coordenadas:
|
||||||
|
|
||||||
|
![](rotmat.png)
|
||||||
|
|
||||||
|
Dê uma olhada no seguinte código para uma função que constrói uma matriz de rotação bidimensional. Esta função segue a [formula](http://en.wikipedia.org/wiki/Rotation_matrix) acima para vetores de duas dimensões rotacionarem as coordenadas em torno do ponto ```vec2(0.0)```.
|
||||||
|
|
||||||
|
```glsl
|
||||||
|
mat2 rotate2d(float _angle){
|
||||||
|
return mat2(cos(_angle),-sin(_angle),
|
||||||
|
sin(_angle),cos(_angle));
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
De acordo com o jeito que estamos desenhando formas, isto não é exatamente o que queremos. Nossa forma de cruz está desenhada no centro do canvas, que corresponde a posição ```vec2(0.5)```. Então, antes de rotacionarmos o espaço, nós precisamos mover a forma, do `centro` para a coordenada ```vec2(0.0)```, rotacionar o espaço, e então, finalmente, move-la de volta ao seu lugar original.
|
||||||
|
|
||||||
|
![](rotate.jpg)
|
||||||
|
|
||||||
|
Isso se parece com o seguinte código:
|
||||||
|
|
||||||
|
<div class="codeAndCanvas" data="cross-rotate.frag"></div>
|
||||||
|
|
||||||
|
Tente os seguintes exercícios:
|
||||||
|
|
||||||
|
* Descomente a linha 45 do código acima e preste atenção no que acontece.
|
||||||
|
|
||||||
|
* Comente as translações antes e depois da rotação, nas linhas 37 e 39, e observe as consequencias.
|
||||||
|
|
||||||
|
* Use rotações para melhorar a animação que você simulou no exercício de translação.
|
||||||
|
|
||||||
|
### Escala
|
||||||
|
|
||||||
|
Nós vimos como matrizes são usadas para mover e rotacionar objetos no espaço. (Ou mais precisamente, transformar o sistema de coordenadas para rotacionar e mover os objetos.) Se você já usou um software de modelagem 3D ou o as funções de matrizes push e pop em Processing, você verá que matrizes também podem ser usadas para escalonar o tamanho de um objeto.
|
||||||
|
|
||||||
|
![](scale.png)
|
||||||
|
|
||||||
|
Se baseando na fórmula anterior, podemos descobrir como fazer uma matriz 2D de escala:
|
||||||
|
|
||||||
|
```glsl
|
||||||
|
mat2 scale(vec2 _scale){
|
||||||
|
return mat2(_scale.x,0.0,
|
||||||
|
0.0,_scale.y);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
<div class="codeAndCanvas" data="cross-scale.frag"></div>
|
||||||
|
|
||||||
|
Tente os seguintes exercícios para entender mais profundamente como isso funciona.
|
||||||
|
|
||||||
|
* Descomente a linha 42 do código acima para ver coordenadas espaciais serem escalonadas.
|
||||||
|
|
||||||
|
* Veja o que acontece quando você comenta as translações antes e depois de escalonar nas linhas 37 and 39.
|
||||||
|
|
||||||
|
* Tente combinar a matriz de rotação junto com a matriz de escala. Note que a ordem das matrizes importa. Multiplique primeiramente pela matriz e então, multiplique os vetores.
|
||||||
|
|
||||||
|
* Agora que você sabe como desenhar diferentes formas, e mover rotacionar e escalona-las, stá na hora de fazer uma ótima composição. Projete e construa uma fake UI or HUD (heads up display)](https://www.pinterest.com/patriciogonzv/huds/). Use os seguintes exemplos do Shadertoy [Ndel](https://www.shadertoy.com/user/ndel) como referência e inspiração.
|
||||||
|
|
||||||
|
<iframe width="800" height="450" frameborder="0" src="https://www.shadertoy.com/embed/4s2SRt?gui=true&t=10&paused=true" allowfullscreen></iframe>
|
||||||
|
|
||||||
|
### Outros usos para matrizes : Cores YUV
|
||||||
|
|
||||||
|
[YUV](http://en.wikipedia.org/wiki/YUV) é um sistema de codificação de cores usado para transmissão analógica de fotos e vídeos que leva em consideração a percepção humana para reduzir a largura de banda dos componentes de crominância.
|
||||||
|
|
||||||
|
O código a seguir é uma interessante oportunidade de usar operações de matrizes em GLSL e transformar as cores de um modo para outro.
|
||||||
|
|
||||||
|
<div class="codeAndCanvas" data="yuv.frag"></div>
|
||||||
|
|
||||||
|
Como você pode ver, nós estamos tratando cores como vetores quando multiplicamos elas pelas matrizes. Desta forma podemos "mover" os valores.
|
||||||
|
|
||||||
|
Neste capítulo, nós aprendemos como usar transformações de matrizes para mover, rotacionar e escalonar vetores. Estas transformações serão essenciais para criar as composições além das formas que aprendemos no capítulo anterior. No próximo capítulo, nós vamos aplicat tudo que aprendemos para criar lindos padrões procedurais. Você irá descobrir que programar repetições e variações podem ser uma empolgante prática.
|
Loading…
Reference in New Issue
Block a user