Auteur Sujet: Effets Tunnels  (Lu 21015 fois)

0 Membres et 1 Invité sur ce sujet

Oh j'avais eu le même problème de ligne verticale avec atan... ça devait être la même raison.

Bon ben moi comme d'hab, je me délecte des posts de Patapom quand il décrit des effets, et je lui repompe tout :D
Donc pour l'occase, je me suis fait un petit tunnel, mais free-directionnal (libre-directionnel on dirait en français). Bref la caméra n'est pas fixée sur l'axe Z mais peut se balader et tourner dans tous les sens.
Avec deux lampes dynamiques mais sans normal map (contrairement à certains, j'en ai pas sous la main :P).

Sinon, oui, je sais, la texture est moche :D

[EDIT] Rhaaaa zut on dirait que mes captures ont foiré... Bon les artifacts que vous voyez c'est uniquement dû à la capture hein, c'est pas un problème de texture ni de atan ;)

sympa la visite du colon :)

Normal pour un lendemain de fête ;)

sympa vos screens flure & nystep


Tain Pata, tu déchires ;)

Ca fait plaisir de voir des gens prendre le temps de mettre tout ca par écrit proprement!

Les sorciers ouvrent leurs grimoires poussiéreux et c’est Proust qui nous ressort sa madeleine : le cœur se serre, la nostalgie gagne l'œil droit d'où sourd lentement une larme salée.

« La prochaine fois, tonton pata, tu nous fais tremper un objet 3D en phong dans de l’eau ! Dis, promet-le nous ! »

Tain Pata, tu déchires ;)

Ca fait plaisir de voir des gens prendre le temps de mettre tout ca par écrit proprement!

Les sorciers ouvrent leurs grimoires poussiéreux et c’est Proust qui nous ressort sa madeleine : le cœur se serre, la nostalgie gagne l'œil droit d'où sourd lentement une larme salée.

« La prochaine fois, tonton pata, tu nous fais tremper un objet 3D en phong dans de l’eau ! Dis, promet-le nous ! »

Haha t'es là aussi toi ? Bon allez, assez de viles flatteries : sors-nous tes recettes ancestrales perso à la sauce Alkama, vieux bisounours confit ! ;D

D'ailleurs, ça me fait penser : quelqu'un a posté j'sais plus où la "Megablast" d'Orange, qui est un exemple du genre dans l'utilisation de tables d'offset folles.
La majeure partie des trucs délires qu'ils obtiennent vient essentiellement d'un truc dont j'ai oublié de parler : le mixing de tables d'offsets.

Il faut faire comme Flure : calculer une table d'offsets + grande que l'écran dans laquelle on scrolle, ça permet entre autres de se déplacer dans le tunnel sus-cité.
Mais imaginez maintenant que vous ayez une seconde table d'offsets, plus grande que l'écran également, dans la quelle vous scrollez différemment.

Si vous ajoutez les offsets obtenus en tapant dans les 2 tables, vous obtiendrez la combinaison des 2 : un truc bien cheulou.

for ( y )
 for ( x )
 {
    Vector2  Offset0 = Table0.Sample( UV0 );  // 1ère table cheulou
    Vector2  Offset1 = Table1.Sample( UV1 );  // 2ème table cheulou (avec UV0 != UV1 )
    Display( Texture.Sample( Offset0 + Offset1 ) ); // Bisou moëlleux
 }

J'ai pas d'image à fournir passkeu j'ai plus le code du tunnel de l'autre fois mais si vous avez déjà le tunnel, c'est facile de tester avec une 2nde table mirobolante.

+ king of tunnel.


Eh ben chapeau patapom, c'est l'ultime tuto tunnels pour les noobs!  ;)

Donnez lui deux jours et il vous fait un tunnel carré avec déformation en voxel landscape et bien sûr, free directional.

+ king of tunnel.

(TPOLM)

Ouais alors là il s'agit des tunnels ray-tracés... C'est plus la même technique, j'ai évoqué le sujet à la fin de mon tuto.
Dans ce cas (je peux me gourer passkeu j'en ai fait un ou 2 mais c'était y a bien longtemps), on subdivisait l'écran en carrés (genre 8x8 il me semble) et on shootait des rayons vers un tube du coup on obtenait des UVs qu'on rendait en interpolant dans la texture.
C'est avec cette technique particulière qu'il fallait faire super gaffe au rebouclage de l'atan (dans mes souvenirs d'ailleurs, je me souviens pas avoir trouvé comment faire pour éviter la ligne de rebouclage).

Dans ce cas, l'effet se sépare en 2 boucles qu'on effectue toujours à chaque frame.
La première pour calculer le tableau d'UVs :

int SizeX = width/8;  // Taille de l'écran / 8 puisqu'on remplit des carrés de 8x8
int SizeY = height/8;

Vector3   CameraPos = (0,0,0);      // Position de la caméra, qui peut bouger librement (même à l'extérieur du tounel)
Vector3   CameraAt = (0,0,-1);      // Vecteur visée
Vector3   CameraUpRef = (0,1,0);      // vecteur Up de référence

// Ici on calcule les vrais vecteurs X et Y
Vector3   CameraRight = normalize( cross( CameraAt, CameraUpRef ) );
Vector3   CameraUp = cross( CameraRight, CameraAt );

Vector2[,]  UVs = new Vector2[SizeY, SizeX];
for ( y=0; y < SizeY; y++ )
{
   float   fY = 1.0f - 2.0f * (float) y / (SizeY-1);
   for ( x=0; x < SizeX; x++ )
   {
      float   fX = 2.0f * (float) x / (SizeX-1) - 1.0f;
      Vector3   View( AspectRatio * fX, fY, 1.0f );
      View.Normalize();   // Alors ici, évidemment, le mieux serait de précalculer une table de vecteur View plutôt que de renormaliser à chaque fois

      // On transforme en world space
      Vector3   ViewWorld = View.X * CameraRight + View.Y * CameraUp + View.Z * CameraAt;

      // On calcule l'intersection avec le tunnel
      // (Ici, toujours notre cylindre de la dernière fois, aligné sur Z, mais on peut imaginer d'autres formes)
      float   HitDistance = CylinderRadius / (1.0f - ViewWorld.Z);   // Distance à laquelle le rayon touche le cylindre
      Vector3   HitPosition = HitDistance * ViewWorld;                 // Position du hit dans l'espace

      // On convertit en UV
      UVs[y,x].X = TableArctangente2D[HitPosition.Y,HitPosition.X];   // Cette table précalculée permet de faire atan2( HitPosition.Y, HitPosition.X )
      UVs[y,x].Y = 0.1f * HitPosition.Z;
   }
}

La seconde boucle va afficher le résultat en relisant la table :

Color*   pScanline = Screen.FirstScanline;   // Un pointeur sur la première scanline de l'écran (on suppose que l'on peut écrire RGB, chacun sur un octet)
for ( y=1; y < SizeY; y++ )
{
   for ( x=1; x < SizeX; x++ )
   {
      // On choppe les 4 UVs des 4 coins de notre carré 8x8
      Vector2   UV00 = UVs[y-1,x-1];
      Vector2   UV01 = UVs[y-1,x];
      Vector2   UV10 = UVs[y,x-1];
      Vector2   UV11 = UVs[y,x];

      // On précalcule quelques bisous
      Vector2   dUV0 = (UV10 - UV00) / 8;
      Vector2   dUV1 = (UV11 - UV01) / 8;

      // Ici, il s'agit de faire un bilinear dans le petit carré de 8x8
      for ( cy=0; cy < 8; cy++ )
      {
         Vector2   UV = UV00;               // On commence à gauche
         Vector2   dUV = (UV01 - UV00) / 8;   // Pente

         for ( cx=0; cx < 8; cx++ )
         {
            Vector3   Color = Texture.Sample( UV );   // Fetch texture
            *pScanline++ = Float2Byte( Color.X );
            *pScanline++ = Float2Byte( Color.Y );
            *pScanline++ = Float2Byte( Color.Z );

            // On incrémente l'UV courant
            UV += dUV;
         }

         // On incrémente les UVs gauche et droit
         UV00 += dUV0;
         UV01 += dUV1;
      }
   }
}

Alors évidemment, il faut optimiser, virer les floats et les remplacer par de la virgule fixe et tout le toutim hein.
Et puis surtout, il y aura ce bug des coordonnées qui rebouclent dans le cas où une valeur vaut UV=(255,0) à gauche et UV=(0,0) à droite => ça va interpoler de 255 à 0 (=256 & 0xFF) au lieu d'interpoler de 255 à 256 comme on le souhaiterait.
(si certains ont des infos sur la façon de vaincre ce problème, ça m'intéresse toujours, même si c'est plus trop d'actualité)

Bref...
L'intérêt de cette technique est qu'on peut se balader partout dans le tunnel, le regarder dans toutes les directions, et (surprise surprise) trifouiller les vecteurs views pour tracer des vecteurs bien cheulous. Là j'ai fait un bête camera frustum perspective mais on est en ray-tracing donc vous pouvez vraiment vous éclater !
Essayez donc des perspectives cylindriques ou fish eye, ou déformez les vecteurs view avec une table de Perlin noise et vous aurez des effets déments ! (et garantis gerbants !)

Pour la démo de TPOLM, le fait qu'ils tracent plus un rectangle infini qu'un cylindre c'est à mon avis un simple changement dans la primitive à ray-tracer, genre ils ont fait mumuse avec leurs vecteurs view et hop, ils sont tombés sur une chouette forme. Et p'têt même une forme qui cache le rebouclage d'UVs dans un coin du rectangle !  ;D

Citer
l faut faire comme Flure : calculer une table d'offsets + grande que l'écran dans laquelle on scrolle, ça permet entre autres de se déplacer dans le tunnel sus-cité.

Ben en fait pour mon tunnel j'ai pas fait une lookup plus grande comme tu le préconises, j'ai fait un tunnel raytracé... Et j'ai ni eu besoin de le faire par cases de 8x8 ni eu le problème de la barre de atan...

En fait j'aime mieux ta version mais je voulais juste en plus que la caméra puisse se retourner dans le tunnel et regarder derrière elle, ça peut faire des choses sympa je trouve...

Bon par contre sur ma vielle cg pourrie j'ai péniblement 70fps en 640x480...
On fait comment pour faire ça dans des cases et interpoler ? Je suis obligé d'appliquer mon shader à un quad subdivisé en plein de petits, ou bien il y a une autre manière avec un seul quad ? mmmmh peut-être en passant le code principal dans le vertex shader j'imagine...

C'était plus pour dire que ce tunnel m'avait marqué en fait :)
Sinon, plus d'explications sur les tunnels ont l'air d'être montrées dans cette prod: http://pouet.net/prod.php?which=379 (hihi)