Set a sphere on fire with three js

Set a sphere on fire with three js

Ett element i naturen, rök och eld!

Observera först att kodsnuttarna nedan har tagits ur sitt sammanhang och att de använder inbyggda variabler och syntax från three.js. Om du har gjort shaders tidigare så kommer du att känna igen variabler som mvPosition och viewMatrix, eller uniformer och texturuppslagningar.

Bruset genereras i en fragmentskuggning, appliceras på ett plan inuti en dold scen, återges till en textur och länkas till målmaterialet. Innan vi lindar strukturen runt sfären så måste vi justera uteffekten av bruset för att det ska vara lämplig för sfärisk kartläggning. Om vi ​​inte gör det så kommer texturen att se klämd ut vid stolparna, vilket kan ses i många exempel.

Detta är en av fördelarna med att generera procedurbrus; att du kan modifiera utgången redan från början. Genom att göra detta så får varje fragment på sfären samma nivå av detaljer i texturen istället för att sträcka bilden över en yta. För sfärer är den här följande tekniken ett sätt att hitta var (i den tänkta brusvolymen) du ska hämta brusvärdet:

float PI = 3.14159265;
float TWOPI = 6.28318531;
float baseRadius = 1.0;

vec3 sphere( float u, float v) {
u *= PI;
v *= TWOPI;
vec3 pSphere;
pSphere.x = baseRadius * cos(v) * sin(u);
pSphere.y = baseRadius * sin(v) * sin(u);
pSphere.z = baseRadius * cos(u);
return pSphere;
}

Lägg märke till 2d-positionen som går in i funktionen och den återkommande vec3-typen. UV-koordinaterna översätts till en 3d-position på sfären. Nu kan man bara slå upp det brusvärdet och plotta det till ursprungets uv-position. Att ändra baseRadius påverkar upprepningen av texturen.

Ett annat tillvägagångssätt är att göra allt i samma shader-par, både brus och slutresultat. Vi får den interpolerade världspositionen för varje fragment från vertex-shadern, så inget behov av att manipulera eller hur? Men eftersom det här exemplet använder förskjutningar i vertex-shadern måste man skapa texturen i ett separat pass och skicka den som en platt textur till den sista shadern.

Så nu har vi en sfär med en brustextur applicerad på den. Det ser snyggt ut men ytan är platt.

Jag nämnde förskjutningar, det här är allt du behöver göra:

#ifdef VERTEX_TEXTURES
vec3 texturePosition = texture2D( tHeightMap, vUv ).xyz;
float dispFactor = uDispScale * texturePosition.x + uDispBias;
vec4 dispPos = vec4( normal.xyz * dispFactor, 0.0 ) + mvPosition;
gl_Position = projectionMatrix * dispPos;
#else
gl_Position = projectionMatrix * mvPosition;
#endif

uDispScale och uDispBias är enhetliga variabler som man kan kontrollera med javascript vid körning. Man lägger bara till ett värde till den ursprungliga positionen längs den normala riktningen. #ifdef-villkoret låter oss använda en reserv för det på webbläsare eller miljöer som inte stöder texturer i vertex-shader. Det är inte tillgängligt i alla implementeringar av webGL, men beroende på din hårdvara och drivrutiner så bör det fungera i de senaste versionerna av Chrome och Firefox. Rätta mig om jag har fel här. Den här funktionen är avgörande för den här demon.

Efter att ha lagt till förskjutning animerar man också hörnen. Man kan t.ex. ändra vertexpositionerna baserat på tid, själva vertexpositionen eller uv-koordinaterna för att göra effekterna mer dynamiska. En av effekterna som finns tillgängliga i inställningspanelen är ”twist”.

Här är den om du är intresserad:

vec4 DoTwist( vec4 pos, float t )
{
float st = sin(t);
float ct = cos(t);
vec4 new_pos;

new_pos.x = pos.x*ct – pos.z*st;
new_pos.z = pos.x*st + pos.z*ct;

new_pos.y = pos.y;
new_pos.w = pos.w;

return( new_pos );
}

//this goes into the main function
float angle_rad = uTwist * 3.14159 / 180.0;
float force = (position.y-uHeight*0.5)/-uHeight * angle_rad;

vec4 twistedPosition = DoTwist(mPosition, force);
vec4 twistedNormal = DoTwist(vec4(vNormal,1.0), force);

//change matrix
vec4 mvPosition = viewMatrix * twistedPosition;

Den variabla kraften måste ändras efter ditt behov. I grund och botten vill du ställa in en startposition och ett intervall som kommer att ändras.

Sedan når vi den sista fragment-shadern. Den här är ganska enkel. Man blandar två färger. Multiplicera dem med en av kanalerna i höjdkartan (brusstrukturen). Blanda sedan denna färg med rökfärgen. Alla färger får sina värden baserat på skärmkoordinationen, en snabbfix för denna lösning. Till sist applicerar man dimma för att få elden att smälta in i bakgrunden och det ser mindre ut som en sfär.

För en sista touch appliceras ett bloom-filter och några partiklar kastas in också.

Lämna ett svar

Din e-postadress kommer inte publiceras.