parallax shader

2D-ko irudietan sakonera efektua lortzeko, kapa desberdinak banatu eta bakoitzari mugimendu koefiziente desberdin bat emanez egiten nuen. Super Mario edo antzeko jokoetan aritua bazara, efektu hau ezaguna izanen duzu. kklrd webguneko goiburuan egin genuen, probatu nahi izanez gero. Xaguaren mugimenduaren arabera desplazatuko ziren kapak, “hurbil” daudenak 0.8-eko koefizientearekin eta “urrunekoak” 0.1-ekoarekin, adibidez. Hau da, kameratuk urrunago daudenek mugimendu ttikiagoa dute.

Kapak argi eta garbi desberdinak eta elkarren arteko distantzia dutenean funtzionatzen du hobekien sistema honek. Baina imajina dezagun pertsona bat gezi bat jaurtitzekotan dagoen irudi bat eta horri sakonera aplikatu nahi diogula. Geziaren puntatik hasi eta gibeleko ukondora arte, zenbat kapa daude eta zein dira?

Sakonera mapa

Horrelako irudiei sakonera aplikatzeko, sakonera mapa (depth map) delakoa aplikatzen zaio. Sakonera mapa hori, berezko irudiaren zuri-beltzeko kopia bat da. Berezko irudiko elementuak hurbil edo urrun dauden definitzeko informazioa duen irudi bat da. Zati argi edo zurienak kameratik hurbil daudenei dagozkie eta ilunak urrunekoei.

Berezko irudia:

Sakonera mapa:

Shader-a

Berezko irudia bistaratzen den bakoitzean shader honen bidez manipulatuko dugu. Sakonera mapa irakurri eta honek erranen digu berezko irudiaren pixel bakoitzak zein desplazamendu izan behar duen. Kasu hauekin ulertzen ahal da funtzionamendu orokorra.

  • Sakonera mapako pixela 100% beltza bada (0 balioa badu), alde baterako erabateko desplazamendua izanen du.
  • Sakonera mapako pixela 100% zuria bada (1 balioa badu), bertze alderako erabateko desplazamendua izanen du.
  • Sakonera mapako pixela 50% zuria eta 50% beltza bada (0.5 balioa badu), erakutsiko den irudian pixel horrek ez du aldaketarik izanen.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
varying vec2 tcoord;

uniform sampler2D texture;
uniform sampler2D depthTex;

void main() {
// Prozesatzen ari garen pixelak sakonera mapan
// duen balio hartu
float depth = texture2D(depthTex, tcoord).r;

// balio hori [0, 1] tartetik [-1, 1] pasatu
float displacement = (depth - .5) * 2;

// Pixel honen lekuan bistaratuko den kolorea
// hartu berezko texturatik. Sakonera maparen balioaren
// bidez kalkulatutako da inguruko zein pixeletik hartu
// kolore hori
gl_FragColor = texture2D(texture, tcoord.xy - vec2(displacement));
}

Emaitza

Goitian aipatutako irudien eta shaderraren konbinazioaren emaitza hau da: