Annonces Google
Serveur IRC
Serveur : irc.portlane.se
Canal : #AmigaNG
Activité du Site

Pages vues depuis 25/07/2007 : 25 366 932

  • Nb. de membres 187
  • Nb. d'articles 1 271
  • Nb. de forums 19
  • Nb. de sujets 20
  • Nb. de critiques 24

Top 10  Statistiques

Index du forum »»  Création-Développement »» Oui on peut faire du bump mapping avec Warp3D/Os4

Oui on peut faire du bump mapping avec Warp3D/Os4#1414

6Contributeur(s)
thellierAmiDARKCrisotElwoodK-LYesCop
3 Modérateur(s)
K-LElwoodcorto
Elwood Elwoodicon_post
ça faisait longtemps que j'avais pas lu une discussion sur un site Amiga dans laquelle je comprends rien :-)
--
Philippe Ferrucci
Avec une Sam460 et AmigaOS 4.1, je suis eco-responsable. Cool !
K-L K-Licon_post
Ah, toi aussi, j'avais peur d'être seul sur ce coup là :-P

Il y a encore de grands développeurs sur notre système ;-)
--
AmigaONE X1000/1,8 Ghz (A-Eon), Radeon RX560, 2 Go de Ram et OS4.1 FE
YesCop YesCopicon_post
Pour moi aussi !
La différence est que je comprends entre les lignes mais comme je ne me suis jamais vraiment intéressé aux "ligthsources" et autres choses dans le genre, je serai incapable de les programmer.

Tout cela pour dire que je suis HEUREUX de ne pas être le seul à la tra?ne ! :-D
thellier thelliericon_post
Bonsoir
Désolé d'avoir été si incompréhensible: je réalise que ce que j'ai écris est assez décousu : mais j'étais tellement excité de voir ce truc de bump-mapping (enfin) marcher sur AmigaOS4 qu'il fallait absolument que je l'écrive :-)

Bon on va prendre le truc à la base:
En 3D un objet est constitué de faces (généralement des triangles mais des faces quelconques ce serait pareil)
Ces faces sont orientées dans une direction appelée "Normale de face"
Qu'est ce une Normal de face ? : imaginez juste une fleche perpendiculaire à la surface de la face

Les normales de face servent à l'éclairage de l'objet

Regardez cet objet avec ces normales de face
http://flylib.com/books/4/423/1/html/2/images/08_125.jpg
si la lampe est à la place de l'observateur alors on comprends aisement que c'est les normales qui regardent vers nous (cad vers la lampe) qui seront eclairées
Ce raisonnement s'étend pour une lampe qui regarde dans dans une autre direction = seront éclairées les faces dans la direction de la lampe
Il s'ensuit que l'éclairage de base revient à dire si angle(direction lampe,direction normale) est faible alors éclairé sinon pas éclairé

Or justement le dotproduct(direction1,direction2) est une formule mathématique qui renvoie une valeur
qui varie avec cette angle

Donc un modele simple d'éclairage fera
pour chaque face
eclairage=dotproduct(Normal de face,direction de la lampe)
RGB[0]=faceRGB[0]*eclairage;
RGB[1]=faceRGB[1]*eclairage;
RGB[2]=faceRGB[2]*eclairage;
tracer face de cette couleur RGB
Voilà

Mais là les faces sont plates de couleur unie = c nul

Donc on va faire du gouraud et là il nous faut les vertex-normals (normale de sommet)
Regarder cette image il y a 4 normales de faces a b c d
http://www.mactech.com/articles/mactech/Vol.14/14.11/PoorMansBrycePartII/fig03.gif
On comprend aisement que N la vertex-normal (normale de sommet) est la moyenne des 4 normales de face a b c d qui sont autour = on calcule tout ça (ou on demande à Blender de le faire...)
On se retrouve donc avec autant de vertex-normals que de points donc 3 ou 4 par Face (triangle ou quad)
http://flylib.com/books/4/423/1/html/2/images/08_121.jpg

C mieux car avec ça on peut calculer plusieurs valeurs d'éclairage aux 4 coins de la face
Donc on peut calculer la valeur de couleur avec éclairage aux 4 coins
Un coin sera rouge, un autre rouge plus sombre, etc...

Que fait Gouraud ? il interpole juste entre ces valeurs de couleurs : genre si on a dix pixels à tracer qui passent de noir (codée 0) à rouge (codée 255) alors on aura un "pas" de 25 entre chaque pixel = c l'interpolation linéaire
Gouraud permet donc des dégradés uniforme de couleur sur une face

Et le bump mapping ?
L'idée c'est de plus rendre le dégradé uniforme pour simuler un mini relief de la face (rides,grains,fissures,etc..) au niveau du pixel
Admettons que l'on veille juste modifier un pixel au milieu de la face = un mini trou en somme.
Si ce pixel rouge est mis plus sombre on se dira c un trou et plus clair on se dira c une mini bosse

On peut imaginer (multitexturing) tracer une nouvelle texture avec ce(s) point(s) plus sombre plus clair par dessus notre face déjà tracée = ça marcherait = on appelle ça une lightmap et c'est juste une image en niveau de gris appliquée sur une face = on en a dans Blitzquake

Le probleme des lightmaps c'est quelle bougent pas : c'est pas grave pour une lampe fixe mais c un problème pour celles qui bougent : imaginez une voiture sur une route mouillée, le bitume sera d'un gris plus ou moins dégradé uniforme (gouraud) et on verra les aspérités(=bump) du bitume QUAND elle passsent dans la direction des phares
Bref on se dit la ligtmap c'est bien mais il faudrait que cela donne du blanc quand c'est dans la direction de la lampe et sinon en gris ou noir

Vous vous dites "mais c'est un dotproduct() au niveau du pixel !!!"
OUI

et justement le multitexturing de Warp3D OS4 cad la V5 sait faire ça = je sais c'est peu connu que Warp3D sache faire ce genre de truc (même Crisot l'ignorais la semaine dernière ;-P même Alain Thellier en doutais ;-P )

Là on se dit oui mais je connais pas "la normale de chaque pixel" ?
Comment les obtenir à partir d'une lightmap ?
Continuons avec notre example de dix pixels avec un mini trou (noir) au milieu
admettons que cette ligne de dix pixels de lightmap soit ainsi avec 1=blanc 0=noir
1111101111
qui represente ce relief avec un trou
---------_------
si on soustrait chaque point au suivant
0 0 0 0 0 -1 1000
on voit apparaitre la pente en x par pixel
On fait pareil pour toutes les lignes horizontales de la lightmap
de même on obtient les pentes en y avec les lignes verticales de la lightmap
Nous avons donc une pente en x et une pente en y par pixel donc on a presque la direction où regarde le pixel (= normale du pixel) on met juste la pente en z à 1.0 et ça y est on obtient une normale par pixel dans notre lightmap = cela devient donc une "normale map"

Bon là dans mon exemple je triche un peu
normalement je devrais lancer Warp3D pour qu'il fasse
un dotproduct(normale du pixel,direction de la lampe) au niveau du pixel et obtienne donc
une lightmap en temps réel

Petite triche1: Mais je connais pas la "direction de la lampe vu de chaque face" (*) alors j'utilise les vertex normale de la face que je connais
Petite triche2: Comme le multitexturing ne traite que des couleurs et des textures alors je prends comme
paramétres de mon W3D_COMBINE_DOT3RGB (= Warp3D qui fait le dotproduct(A,B) ) :
A une texure =la normale map
Bune couleur =la couleur des sommets (**) où je mets en fait mes vertex normales faute de savoir où les mettre
===> donne une lightmap

Après je fais une simple deuxieme passe de multitexturing avec la texture "peau de vache" modulée
par la lightmap précédente

Et voilà

Alain

(*) En fait il faudrait juste tourner toutes les vertex normale dans la direction de la lampe. Si on le fait pas c'est comme si on avait la lampe à la place de l'observateur.

(**) Mais là je perds le gouraud qui était stocké dans la couleur des sommets = à améliorer




























YesCop YesCopicon_post
Merci c'est beaucoup plus clair. Encore merci d'avoir passé du temps à écrire.
Quelques questions pour ma culture personnel (et peut-être celle des autres lecteurs).

La lightmap = Bump mapping ?
Est-ce un tableau bidimensionnel contenant des 0 et des 1 ou des valeurs pour gérer plus finement les bosses et donc des valeurs entre 0 et 255 (ou plus si on utilise des couleurs 24 bits) ?

Le dot product me fait penser en fait à un produit scalaire, non ?

Je n'ai pas bien compris la normale pour les pixels.
On a une série de 0 et de 1 qui indique si oui ou non on a de la lumière sur les pixels de la face.
Donc par pixel on a une seule valeur 0 ou 1. Donc je ne comprends pas la notion de pente en x et en y, ce qui impliquerait pour moi au moins deux valeurs par pixel.

Un amateur pas trop éclairé, bien près du 0 :-D
thellier thelliericon_post





>La lightmap = Bump mapping ?
Non pas vraiment la lightmap c'est juste une texture fixe comme un calque où on aurait dessiné les parties éclairé/pas éclairées en niveau de gris noir blanc : imagine un mur avec une lampe en applique alors la lightmap serait juste un calque avec un rond plus clair au niveau de la lampe
On peut faire une lightmap dans Dpaint à la main...
Le bump mapping c'est générer à la volée une lightmap à partir d'une normalemap

>Est-ce un tableau bidimensionnel contenant des 0 et des 1 ou des valeurs pour gérer plus finement les bosses et donc des valeurs entre 0 et 255 (ou plus si on utilise des couleurs 24 bits) ?
Tout à fait
On part d'une image quelconque dont on dit que "telle valeur de pixel equivaudra à une hauteur"
Ca peut donc marcher effectivement avec n'importe quelle type de texture comme tu le dis
De toute façon au final on obtient une texture qui contient une normale par pixel c'est avec cette texture
(normale map) que Warp3D va bosser
http://faculty.ycp.edu/~dbabcock/PastCourses/cs470/labs/images/normalVectors.png
Donc n'importe quelle fonction capable de convertir chacun des pixels depuis 3 valeurs R G B vers nx ny nz (normale de pixels) pourrait faire l'affaire

>Le dot product me fait penser en fait à un produit scalaire, non ?
Oui c'est ça mon niveau de math et anglais est devenu faible avec le temps ...

>Je n'ai pas bien compris la normale pour les pixels.
>On a une série de 0 et de 1 qui indique si oui ou non on a de la lumière sur les pixels de la face.
>Donc par pixel on a une seule valeur 0 ou 1.
Effectivement 0 et 1 c'est le cas limite mais on comprend bien que
si 2 pixels de suite sont à 0 la pente est à 0 (on est monté de 0 millimetres)
si le premier est à 0 le deuxième à 1 la pente est à 1 (on est monté de 1 millimetre)
une fois qu'on a la pente alors la normale est là
http://thellier.free.fr/pixels-normals.gif


>Donc je ne comprends pas la notion de pente en x et en y, ce qui impliquerait pour moi au moins deux valeurs par pixel.
C'est car on parcoure la texture en x et en y
Admettons une tex de 4x4 pixels en niveau de gris de 0 à 100
10 10 10 10
10 20 10 10
10 15 10 10
10 10 10 10

On a un point "plus haut" qui est à 20 entouré de 2 pixels
20 10
15

Calculons sa normale de pixels
en x = 10 -20 = -10 sur 100 soit -10/100 donc normale.x=0.10
en y = 15 -20 = -5 sur 100 soit -5/100 donc normale.y=0.05
oui je change le signe car la normale regarde vers le haut pas comme la pente
on met normale.z=1.0; faute de mieux ;-) et comme en mathematique la
longueur d'une normale n doit valoir 1.0
alors on calcule sa longueur long=racinecarrée(n.x * n.x + n.y*n.y + n.z*n.z)
et on fait
n.x = n.x/long ;
n.y = n.y/long ;
n.z = n.z/long ;
on obtient une normale standard par pixel
on la stocke dans la texture qui elle contenait juste 3 UBYTE R G B (donc des valeurs de 0 à 255)
R=(n.x/2.0+0.5)*255;
G=(n.y/2.0+0.5)*255;
B=(n.z/2.0+0.5)*255;
Ca y est on a une normale map

après on laisse juste Warp3D faire le boulot : un dotproduct par pixel
qui va générer à la volée une lightmap

Alain











Un amateur pas trop éclairé, bien près du 0
AmiDARK AmiDARKicon_post
http://fr.wikipedia.org/wiki/Normal_mapping


Laisse un espace devant un lien : c'est suffisant pour le rendre actif ! :-)
Message édité par : Creols / 25-11-2012 14:47
Crisot Crisoticon_post
Bon, ca fait 2 jours que je bosses là dessus.

Donc la partie normal-map brute de décoffrage, ça prends quelques minutes

Par contre, je me casse les dents depuis 2 jours sur le problème de transformation entre le repère de chaque poly affecté d'une lightmap (le repère tangent) et le repère usuel du monde.

Bref, j'ai un bumpmap réaliste pour les poly verticaux face à la lumière (poly dans le plan X/Y) mais fantaisiste sitot que le poly sort de ce plan.

Mais voila, je me demande si je vais me prendre le choux à régler ce problème. Car même sans lui, le normal mapping à révélé un autre problème: Celui des performances de nos Radeons. Le fait d'utiliser une normalmap combinée divise les performances par 2. Je ne suis pas sur que le jeu en vaille la chandèle.
--
AmigaOne X1000 - 2 Go DDR2 - Sapphire R9 280x Toxic - Crucial MX200 500 Go - Alim/Cooling BeQuiet
thellier thelliericon_post
Deja si tu utilise les vertex normals des sommets du triangle tu te retrouve avec une bumpmap realiste dans tout les cas puisque tu fais ton dotproduct entre la normale-map et cellles de la face a ce point cad interpolee entre les 3 sommets du tri

Bon apres, je l ai deja ecrit, il aurait fallu mettre toutes les normales map dans la direction de la lampe pour etre ok sinon
c comme si la lampe etait l observateur.

Sur les performances c sur ca bouffe donc faut limiter le bump aux polys proche d une lampe qui bouge genre torche du heros ou boule de feu envoyees au fond du tunnel

btw peut etre pourra tu m aider je bugge sur des matrices:
je voudrais faire comme un bras de robot cad un 1er objet a une position x1,y1,z1 avec une rotation r1x,r1y,r1y
cet objet en tient un deuxieme a une position x2,y2,z2 avec une rotation r2x,r2x,r2x etc...
Normalement je devrais faire mes matrices d objet et les multiplier entre elles. .. Mais ca buggue...aurais tu un exemple
de code qui marche?
MERCI

Alain
Crisot Crisoticon_post
En fait c'est assez compliqué, il faut créer un repère pour chaque polygone. On l'appelle le repère Tangent.

Exemple tout simple. Tu es face à un mur, ton R sert de bump horizontal, et ton G de bump vertical. Maintenant imagine que, sans bouger ta camera ni ta light, tu réutilises ce mur en le tournant de 90? autour de l'axe Z, ou tout bêtement que tu le texture dans l'autre sens: Il est toujours face à toi, sauf que cette fois ci, ton R sert de bump vertical, et ton G sert de bump horizontal. D'où la création d'un repère "tangent" pour chaque polygone, basé non pas sur la géométrie de l'objet mais sur les UV du polygone.

Bref, après 2 jours sur google "repère tangent normal map", un pote m'a dépanné en me filant son code. Résultat:



Pour les matrices, rien de bien compliqué. Copier/coller brut... (repère main droite: X à droite, Y en haut, Z vers l'utilisateur).

Entité:

matrix[0][0]=1; matrix[0][1]=0; matrix[0][2]=0; matrix[0][3]=0;
matrix[1][0]=0; matrix[1][1]=1; matrix[1][2]=0; matrix[1][3]=0;
matrix[2][0]=0; matrix[2][1]=0; matrix[2][2]=1; matrix[2][3]=0;
matrix[3][0]=0; matrix[3][1]=0; matrix[3][2]=0; matrix[3][3]=1;

Rotation axe X:

matrixB[0][0]=1; matrixB[0][1]=0; matrixB[0][2]=0; matrixB[0][3]=0;
matrixB[1][0]=0; matrixB[1][1]=cos(ang); matrixB[1][2]=-sin(ang); matrixB[1][3]=0;
matrixB[2][0]=0; matrixB[2][1]=sin(ang); matrixB[2][2]=cos(ang); matrixB[2][3]=0;
matrixB[3][0]=0; matrixB[3][1]=0; matrixB[3][2]=0; matrixB[3][3]=1;

Rotation axe Y:

matrixB[0][0]=cos(ang); matrixB[0][1]=0; matrixB[0][2]=sin(ang); matrixB[0][3]=0;
matrixB[1][0]=0; matrixB[1][1]=1; matrixB[1][2]=0; matrixB[1][3]=0;
matrixB[2][0]=-sin(ang); matrixB[2][1]=0; matrixB[2][2]=cos(ang); matrixB[2][3]=0;
matrixB[3][0]=0; matrixB[3][1]=0; matrixB[3][2]=0; matrixB[3][3]=1;

Rotation axe Z:

matrixB[0][0]=cos(ang); matrixB[0][1]=-sin(ang); matrixB[0][2]=0; matrixB[0][3]=0;
matrixB[1][0]=sin(ang); matrixB[1][1]=cos(ang); matrixB[1][2]=0; matrixB[1][3]=0;
matrixB[2][0]=0; matrixB[2][1]=0; matrixB[2][2]=1; matrixB[2][3]=0;
matrixB[3][0]=0; matrixB[3][1]=0; matrixB[3][2]=0; matrixB[3][3]=1;

Translation:

matrixB[0][0]=1; matrixB[0][1]=0; matrixB[0][2]=0; matrixB[0][3]=x;
matrixB[1][0]=0; matrixB[1][1]=1; matrixB[1][2]=0; matrixB[1][3]=y;
matrixB[2][0]=0; matrixB[2][1]=0; matrixB[2][2]=1; matrixB[2][3]=z;
matrixB[3][0]=0; matrixB[3][1]=0; matrixB[3][2]=0; matrixB[3][3]=1;

Et la multiplication des matrices

void PXS_MatrixMultiply(float matrixA[4][4], float matrixB[4][4])
{
int i;
float matrixC[4];
for (i=0; i<4; i++)
{
matrixC[0] = matrixA[i][0] * matrixB[0][0] + matrixA[i][1] * matrixB[1][0] + matrixA[i][2] * matrixB[2][0] + matrixA[i][3] * matrixB[3][0];
matrixC[1] = matrixA[i][0] * matrixB[0][1] + matrixA[i][1] * matrixB[1][1] + matrixA[i][2] * matrixB[2][1] + matrixA[i][3] * matrixB[3][1];
matrixC[2] = matrixA[i][0] * matrixB[0][2] + matrixA[i][1] * matrixB[1][2] + matrixA[i][2] * matrixB[2][2] + matrixA[i][3] * matrixB[3][2];
matrixC[3] = matrixA[i][0] * matrixB[0][3] + matrixA[i][1] * matrixB[1][3] + matrixA[i][2] * matrixB[2][3] + matrixA[i][3] * matrixB[3][3];
matrixA[i][0]=matrixC[0]; matrixA[i][1]=matrixC[1]; matrixA[i][2]=matrixC[2]; matrixA[i][3]=matrixC[3];
}

J'admet que ma multplication est très crade. Tu donnes une matrice A en B en entrée, la A est écrasée en étant multipliée par la B... Faudra que je fasse un truc plus propre à l'occase...

Attention à l'ordre de multiplication de 2 matrices. Si tu as une matrice A de translation et une matrice B de rotation et que tu fais A*B, tu va avoir l'objet translaté PUIS tourné. Si tu fais B*A, l'objet sera tourné PUIS translaté (à moins que ce ne soit l'inverse).
--
AmigaOne X1000 - 2 Go DDR2 - Sapphire R9 280x Toxic - Crucial MX200 500 Go - Alim/Cooling BeQuiet
Petites Annonces

0 annonce(s) publiée(s)

Consulter

AmigaOS 4.1

Laissez-vous tenter par
AmigaOS 4.1
AmiTheme

AmiTheme