Procedural Materials with Shaders in Three.js

July 24, 2024

Shaderek

Shaderekkel könnyen létrehozhatunk az előzőekben létrehozott területünkhöz vizuális effekteket (VFX) vagy hozzárendelhetünk procedurális anyagokat. A shaderek programozható egységek a grafikus hardveren, amelyek lehetővé teszik a különféle speciális effektusok és anyagok létrehozását. Ezek segítségével a fejlesztők valósághűbb és vizuálisan lenyűgözőbb jeleneteket készíthetnek.

Procedural Material

Egyszerűen létrehozhatunk anyagokat GLSL shaderek segítségével. A procedurális anyagok olyan textúrák és anyagok, amelyek matematikai algoritmusokkal jönnek létre, nem pedig előre elkészített képekkel. Ez lehetővé teszi a végtelen részletességet és variálhatóságot, miközben csökkenti a memóriahasználatot.

A procedurális anyagok legegyszerűbb létrehozása a különböző Perlin zajok összekeverésével és módosításával jön létre. A Perlin zaj egy algoritmus, amely sima, véletlenszerű mintázatot hoz létre, és gyakran használják természetes textúrák, például föld, víz, felhők és tűz szimulálására.

Perlin zaj

A visual depiction of what is being written about

A Perlin zaj algoritmusának megértése alapvető fontosságú a procedurális anyagok létrehozásához. Az alábbi GLSL kód egy egyszerű Perlin zaj implementációt mutat be:

GLSL
float noise( in vec3 p )
{
vec3 i = floor( p );
vec3 f = fract( p );
vec3 u = f*f*(3.0-2.0*f);
return mix( mix( mix( dot( hash( i + vec3(0.0,0.0,0.0) ), f - vec3(0.0,0.0,0.0) ),
dot( hash( i + vec3(1.0,0.0,0.0) ), f - vec3(1.0,0.0,0.0) ), u.x),
mix( dot( hash( i + vec3(0.0,1.0,0.0) ), f - vec3(0.0,1.0,0.0) ),
dot( hash( i + vec3(1.0,1.0,0.0) ), f - vec3(1.0,1.0,0.0) ), u.x), u.y),
mix( mix( dot( hash( i + vec3(0.0,0.0,1.0) ), f - vec3(0.0,0.0,1.0) ),
dot( hash( i + vec3(1.0,0.0,1.0) ), f - vec3(1.0,0.0,1.0) ), u.x),
mix( dot( hash( i + vec3(0.0,1.0,1.0) ), f - vec3(0.0,1.0,1.0) ),
dot( hash( i + vec3(1.0,1.0,1.0) ), f - vec3(1.0,1.0,1.0) ), u.x), u.y), u.z );
}

Fraktál zaj

A zaj kód részlet jó zaj textúrát ad, de ha valós világban előforduló egyenetlenségeket akarunk ábrázolni, túl egyenletes és inkább egy elmosódott rácsmintára hasonlít. A valós világ véletlenszerűsége dinamikusabb. Ezt elérhetjük több zajminta különböző méretekben történő összegzésével, amit Fraktál Brown-mozgásnak (Fractal Brownian Motion) nevezünk.

Az oktávok (zajok száma), az amplitúdó (intenzitás) és a frekvencia („szorosság”) szabályozásával sokkal dinamikusabb zajmintát kapunk. Az alábbi GLSL kód egy fraktál zaj (fBM) implementációt mutat be:

A 4.1-es Blenderben a zaj textúra is beállítható alapból már FBM-re

GLSL
float fbm(vec3 p, int octaves, float persistence, float lacunarity) {
float amplitude = 0.5;
float frequency = 1.0;
float total = 0.0;
float normalization = 0.0;
for (int i = 0; i < octaves; ++i) {
float noiseValue = noise(p * frequency);
total += noiseValue * amplitude;
normalization += amplitude;
amplitude *= persistence;
frequency *= lacunarity;
}
total /= normalization;
return total;
}

Egyéb ismert zajok:

Worley (Cellular) noise:

A Worley zaj, más néven celluláris zaj, olyan algoritmus, amelyet gyakran használnak szimulált sejtstruktúrák vagy egyéb természetes mintázatok létrehozására. Az alábbi képen egy példa látható:

A visual depiction of what is being written about

Az alábbi GLSL kód egy egyszerű Worley zaj implementációt mutat be:

GLSL
float worley(vec3 coords) {
vec2 gridBasePosition = floor(coords.xy);
vec2 gridCoordOffset = fract(coords.xy);
float closest = 1.0;
for (float y = -2.0; y <= 2.0; y += 1.0) {
for (float x = -2.0; x <= 2.0; x += 1.0) {
vec2 neighbourCellPosition = vec2(x, y);
vec2 cellWorldPosition = gridBasePosition + neighbourCellPosition;
vec2 cellOffset = vec2(
noise(vec3(cellWorldPosition, coords.z) + vec3(243.432, 324.235, 0.0)),
noise(vec3(cellWorldPosition, coords.z))
);
float distToNeighbour = length(
neighbourCellPosition + cellOffset - gridCoordOffset);
closest = min(closest, distToNeighbour);
}
}
return closest;
}

Turbulence FBM:

A Turbulence FBM egy másik ismert zajtípus, amelyet gyakran használnak a természetes mintázatok és textúrák szimulálására. Az alábbi képen egy példa látható:

A visual depiction of what is being written about

Az alábbi GLSL kód egy egyszerű Turbulence FBM implementációt mutat be:

GLSL
float turbulenceFBM(vec3 p, int octaves, float persistence, float lacunarity) {
float amplitude = 0.5;
float frequency = 1.0;
float total = 0.0;
float normalization = 0.0;
for (int i = 0; i < octaves; ++i) {
float noiseValue = noise(p * frequency);
noiseValue = abs(noiseValue);
total += noiseValue * amplitude;
normalization += amplitude;
amplitude *= persistence;
frequency *= lacunarity;
}
total /= normalization;
return total;
}

Materialok készítése

Az előbb leírt anyagok összekeverésével tudunk létrehozni különböző anyagokat vagy a megjelenítés valamilyen módosításával. Például lépcsős kialakítással elérhetünk fásabb hatású anyagot. Az alábbi GLSL kód egy ilyen implementációt mutat be:

GLSL
float stepped(float noiseSample) {
float steppedSample = floor(noiseSample * 10.0) / 10.0;
float remainder = fract(noiseSample * 10.0);
steppedSample = (steppedSample - remainder) * 0.5 + 0.5;
return steppedSample;
}

Rengeteg jó procedurális anyag van a ShaderToy oldalon, amelyeket minimális változtatással használhatunk three.js-ben.

ShaderToy használata egyszerű kockán

Az alábbi kódrészlet mutatja, hogyan adjuk hozzá a változókat az elejéhez:

GLSL
uniform float iTime;
uniform vec2 iResolution;
varying vec2 vUv;

A void mainImage-t is módosítjuk, hogy figyelembe vegye aszükséges változókat.

A fragCoord-ot a vUv és az iResolution szorzataként számoljuk, és a fragColor helyett pedig a gl_FragColor-t használjuk a végén. Ez lehetővé teszi a procedurális anyagok dinamikus alkalmazását és testreszabását a háromdimenziós jelenetekben.

Összegzés

A procedurális anyagok és zajok használata a GLSL shaderekkel rendkívül hatékony módja annak, hogy valósághű és részletgazdag textúrákat hozzunk létre. Az ilyen technikák nemcsak esztétikailag vonzóak, hanem optimalizálják a teljesítményt is, mivel kevesebb memóriát használnak, mint a hagyományos textúrák. A fent bemutatott példák és kódrészletek segítségével könnyedén létrehozhatunk és alkalmazhatunk különböző procedurális anyagokat a projektekben, legyen szó játékfejlesztésről, animációról vagy bármilyen más 3D alkalmazásról.

Oszd meg ezt a cikket

Merülj el az izgalmas tudásban, amíg a buszra vársz!

Indítsd a napod a legújabb technológiai áttörésekkel. Csatlakozz most, és merülj el az innovációban!

Kapcsolódó Cikkek