Shaders
Exemplo de shader de animação por deslocamento.
Os exemplos utilizados nesta aula estão neste link.
De forma básica, shaders são programas que recebem informações sobre o estado do mundo do jogo e desenham uma imagem baseada nessas informações. Isso acontece na etapa de render do gameloop. Shaders, então, podem servir tanto para processar informações sobre um jogo 2D quanto 3D, dependendo do caso.
Existem duas etapas básicas de processamento em shaders 3D: vertex shaders e fragment shaders. Os vertex shaders recebem informações sobre cada vértice de uma mesh 3D e a convertem em um conjunto de fragments dependendo do quanto a geometria definida pelos vértices está visível. Um fragment shader recebe esses fragmentos e os processa até chegar na cor de cada pixel que deve aparecer na tela.
Na Unity, também é possível definir surface shaders, que são basicamente uma forma de criar vertex e fragment shaders de forma parcialmente automática para facilitar a criação de efeitos mais avançados em shaders 3D. Para ter uma ideia melhor desses shaders, vale a pena estudar estes exemplos no link.
Shader branco
Shader "Exemplos/Básico"
{
SubShader
{
Tags
{
"PreviewType" = "Plane"
}
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct appdata
{
float4 vertex : POSITION;
};
struct v2f
{
float4 vertex : SV_POSITION;
};
v2f vert(appdata v)
{
v2f o;
o.vertex = mul(UNITY_MATRIX_MVP, v.vertex);
return o;
}
float4 frag(v2f i) : SV_Target
{
float4 color = float4(1,1,1,1);
return color;
}
ENDCG
}
}
}
Shader de textura
Shader "Exemplos/Textura simples"
{
Properties
{
_MainTex("Texture", 2D) = "white" {}
}
SubShader
{
Tags
{
"PreviewType" = "Plane"
}
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};
struct v2f
{
float4 vertex : SV_POSITION;
float2 uv : TEXCOORD0;
};
v2f vert(appdata v)
{
v2f o;
o.vertex = mul(UNITY_MATRIX_MVP, v.vertex);
o.uv = v.uv;
return o;
}
sampler2D _MainTex;
float4 frag(v2f i) : SV_Target
{
float4 color = tex2D(_MainTex, i.uv);
return color;
}
ENDCG
}
}
}
Efeitos de imagem
Efeitos de imagem funcionam como shaders que são aplicados à imagem que está sendo renderizada pela câmera, ao invés de processar a aparência de cada objeto de forma separada. Podemos pensar nesse tipo de efeito como um filtro de processamento de imagem em tempo real, parecido com o que encontramos em softwares como After Effects ou Photoshop. Pro trás dos panos, é como se a engine estivesse criando um grande quad com a iamgem do frame atual do jogo e esse quad é passado para a função OnRenderImage( RenderTexture src, RenderTexture dst)
. A estrutura básica de um efeito de imagem está representada abaixo.
using UnityEngine;
// para poder ver os resultados no editor
[ExecuteInEditMode]
public class EfeitoDeImagemBasico : MonoBehaviour {
// material com o shader e infos para o efeito
public Material material;
void OnRenderImage(RenderTexture src, RenderTexture dst) {
// chamada que copia os pixels da origem no destino
Graphics.Blit(src, dst, material);
}
}
Por que usar shaders?
Shaders, quando utilizados em objetos ou como efeitos de imagem, podem criar muita flexibilidade e dinamismo para a estética visual de seu jogo. Coisas como animação procedural (veja o exemplo no topo da página), criar variedade para um asset, aplicar uma paleta de cores ou mostrar o efeito de uma interação com o jogador podem ser alcançadas utilizando shaders. Em conjunto com a criação de modelos e texturas, essa ferramenta pode ajudar a criar um estilo visual mais elaborado e consistente para seu jogo.
Referências
- O canal Makin’ Stuff Look Good in Unity tem ótimos tutoriais em vídeo sobre shaders e partículas. Vale a pena dar uma fuçada e extrapolar a partir dos exemplos.
- No site Catlike Coding você pode encontrar tutoriais mais avançados sobre uma série de assuntos relacionados à computação gráfica e shaders.