Lightmaps OpenGL

manolobis Messages postés 21 Date d'inscription dimanche 5 juin 2005 Statut Membre Dernière intervention 17 décembre 2006 - 15 déc. 2006 à 23:12
manolobis Messages postés 21 Date d'inscription dimanche 5 juin 2005 Statut Membre Dernière intervention 17 décembre 2006 - 17 déc. 2006 à 23:00
Bonjour,


Après avoir épuisé les ressources de la gestion des lumières sous openGL (Windows / Dev++) qui sont trop limitées pour mon application je me suis lancé dans les LightMaps.


Pour faire simple j'ai pris l'exemple du site 3ddrome qui m'a semblé simple et explicite et facile à mettre en oeuvre:


- Une structure pour les polygones


- Un générateur de LightMap qui renvoie un 'Unsigned Int' qui est en fait un pointeur sur une texture des composantes d'éclairage de mon polygone.


- Un Multitexturage qui permet de combiner une Texture normal et ma Texture d'éclairage.


Pas de pb jusque là, l'exemple fonctionne parfaitement sauf que l'exemple utilise des rectangles 'Quads' et que sous certains angles d'éclairage mon carré se divise en deux triangles qui ne sont pas éclairés de la même façon (ou plutôt on voit la diagonale qui divise le carré en deux triangles et qui est en fait plus sombre).


J'ai adapté le programmme pour fonctionner avec des traingles (car dans mon appli je n'utilise que des triangles) et là c'est encore pire. Quand la lumière est de face, pas de pb, quand la lumière arrive un peu sur les côtés, même pb les deux triangles de mon carré (qui sont dans le même plan, donc ont un vecteur 'normal' iddentique) ne sont plus éclairés de la même intensité (on voit la diagonale).
J'ai testé avec plusieurs sources lumineuses, c'est encore pire. Si une lumière rouge est à gauche, une lumière verte est à droite, mon triangle de gauche est plus rouge et celui de droite plus vert.

Y-a-t'il moyen de résoudre ce problème de façon à ce que la lumière soit homogère quelque soit l'angle de la source et quelque soit le nombre de sources lumineuses?

Si quelqu'un à une suggestion, car je doit dire que tel quel c'est pas très pro et pas très exploitable pour ce que je désire en faire...

D'avance merci.

9 réponses

luhtor Messages postés 2023 Date d'inscription mardi 24 septembre 2002 Statut Membre Dernière intervention 28 juillet 2008 6
16 déc. 2006 à 12:16
Tu calcules surement tes normales pour chaque face et c'est cette
normale que tu mets pour chaque vertex de ton triangle. Pour chaque
vertex, essai de faire la moyenne des normales des faces voisines.


Ou sinon, c'est quoi le filtrage que tu as mis pour la texture lightmap ?
0
manolobis Messages postés 21 Date d'inscription dimanche 5 juin 2005 Statut Membre Dernière intervention 17 décembre 2006
16 déc. 2006 à 20:58
En fait, Luhtor, je n'ai fait que recopier la démo:
- DynamicLightMap de chez 3ddrome.
Elle utilise les 'QUADS' et sans rien ajouter de plus, j'avais déjà ce problème lorsque la lumière n'est pas de face on voit la diagonale qui sépare le QUADS en 2 triangles et qui est plus sombre. Puis j'ai adapté la démo aux 'TRIANGLES' et le pb est le même et même pire puisque les bords aussi étaient plus sombres.
Pour résoudre les pb de bordures j'ai ensuite rajouté le filtrage:
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T GL_CLAMP_TO_EDGE);
au moment de l'affichage après le glBindTexture(...), ce qui à résolu le pb de bord mais pas des triangles d'intensité lumineuse différentes pour les triangles dans un même plan.
Le pb étant déjà apparu dans la démo copiée telle quelle je pense que le pb est ailleurs, mais où ?
Je n'ose pas croire qu'on puisse pas avoir un meilleur résultat avec les lighmaps car j'ai vu des démos parfaites qui utilisait cette technique.

A+
0
luhtor Messages postés 2023 Date d'inscription mardi 24 septembre 2002 Statut Membre Dernière intervention 28 juillet 2008 6
16 déc. 2006 à 22:09
Mais il faut que tu précises au moins filtrage linéaire à opengl pour
la lightmap sinon ca ne m'étonne pas qu'on trouve des trucs un peu
bizzare.

Ou alors, ya un pb dans le calcul des normales et de la luminosité.
0
luhtor Messages postés 2023 Date d'inscription mardi 24 septembre 2002 Statut Membre Dernière intervention 28 juillet 2008 6
16 déc. 2006 à 22:15
Mais il faut que tu précises au moins filtrage linéaire à opengl pour
la lightmap sinon ca ne m'étonne pas qu'on trouve des trucs un peu
bizzare.

Ou alors, ya un pb dans le calcul des normales et de la luminosité.
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
manolobis Messages postés 21 Date d'inscription dimanche 5 juin 2005 Statut Membre Dernière intervention 17 décembre 2006
16 déc. 2006 à 23:56
Le filtrage linéaire se trouve dans le calcul de la lightmap dont voici le code qui génère une texture de luminosité à partir d'une surface 'QUADS' et une source lumineuse:
static unsigned int generate_lightmap(struct surface *surf)
{
static unsigned char data[LIGHTMAP_SIZE * LIGHTMAP_SIZE * 3];
static unsigned int lightmap_tex_num = 0;
unsigned int i, j;
float pos[3];
float step, s, t;

if(lightmap_tex_num == 0) glGenTextures(1, &lightmap_tex_num);

step = 1.0f / (float)LIGHTMAP_SIZE;
s t 0.0f;

for(i = 0; i < LIGHTMAP_SIZE; i++)
{

for(j = 0; j < LIGHTMAP_SIZE; j++)
{

float d;

float tmp;

pos[0] = surf->s_dist * s;

pos[1] = surf->t_dist * t;

pos[2] = 0.0f;

multiply_vector_by_matrix(surf->matrix, pos);

pos[0] += surf->vertices[0][0];
pos[1] += surf->vertices[0][1];
pos[2] += surf->vertices[0][2];

pos[0] -= light_pos[0];
pos[1] -= light_pos[1];
pos[2] -= light_pos[2];

d = dot_product(pos, pos) * 0.5f;

if(d < 1.0f)

d = 1.0f;

tmp = 1.0f / d;

data[i * LIGHTMAP_SIZE * 3 + j * 3 + 0] = (unsigned char)(255.0f * tmp * light_color[0]);
data[i * LIGHTMAP_SIZE * 3 + j * 3 + 1] = (unsigned char)(255.0f * tmp * light_color[1]);
data[i * LIGHTMAP_SIZE * 3 + j * 3 + 2] = (unsigned char)(255.0f * tmp * light_color[2]);

s += step;

}

t += step;

s = 0.0f;

}

glBindTexture(GL_TEXTURE_2D, lightmap_tex_num);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glTexImage2D(GL_TEXTURE_2D, 0, 3, LIGHTMAP_SIZE, LIGHTMAP_SIZE, 0, GL_RGB, GL_UNSIGNED_BYTE, data);

return lightmap_tex_num;

}

Maintenant faut-il répéter les filtrages GL_LINEAR lors de l'affichage, ce qui n'est pas précisé dans la démo ?
La démo affiche ainsi:

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();

glTranslatef(0.0f, 0.0f, -5.0f);
glRotatef(cam_rot[0], 1.0f, 0.0f, 0.0f);
glRotatef(cam_rot[1], 0.0f, 1.0f, 0.0f);
glRotatef(cam_rot[2], 0.0f, 0.0f, 1.0f);

glActiveTextureARB(GL_TEXTURE0_ARB);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, surface_tex_num);

glActiveTextureARB(GL_TEXTURE1_ARB);

if(lighting)
glEnable(GL_TEXTURE_2D);

for(i = 0; i < 6; i++) {

if(!surfaces[i])

break;

if(lighting)

glBindTexture(GL_TEXTURE_2D, generate_lightmap(surfaces[i]));

glBegin(GL_QUADS);

glMultiTexCoord2fARB(GL_TEXTURE0_ARB, 0.0f, 0.0f);
glMultiTexCoord2fARB(GL_TEXTURE1_ARB, 0.0f, 0.0f);
glVertex3fv(surfaces[i]->vertices[0]);

glMultiTexCoord2fARB(GL_TEXTURE0_ARB, 0.0f, 1.0f);
glMultiTexCoord2fARB(GL_TEXTURE1_ARB, 0.0f, 1.0f);
glVertex3fv(surfaces[i]->vertices[1]);

glMultiTexCoord2fARB(GL_TEXTURE0_ARB, 1.0f, 1.0f);
glMultiTexCoord2fARB(GL_TEXTURE1_ARB, 1.0f, 1.0f);
glVertex3fv(surfaces[i]->vertices[2]);

glMultiTexCoord2fARB(GL_TEXTURE0_ARB, 1.0f, 0.0f);
glMultiTexCoord2fARB(GL_TEXTURE1_ARB, 1.0f, 0.0f);
glVertex3fv(surfaces[i]->vertices[3]);

glEnd();

}
0
luhtor Messages postés 2023 Date d'inscription mardi 24 septembre 2002 Statut Membre Dernière intervention 28 juillet 2008 6
17 déc. 2006 à 12:22
Tes sur que c'est correct ta fonction de calcul de lightmap, car ya des trucs vraiment étrange.

pos[0] += surf->vertices[0][0];   <= Ca dépend pas de "i" ni de "j" ?
pos[1] += surf->vertices[0][1];
pos[2] += surf->vertices[0][2];

d = dot_product(pos, pos) * 0.5f; <= T'es sur de ton calcul la ? La normale rentre jamais en compte ?

A mon avis, c'est la fontion de calcul de Lightmap, qui ne marche pas.
0
manolobis Messages postés 21 Date d'inscription dimanche 5 juin 2005 Statut Membre Dernière intervention 17 décembre 2006
17 déc. 2006 à 16:36
L'exemple que j'ai donné n'est qu'un copié-collé de la démo qu'est donné sur le tut de 3ddrome, jette un oeil sur le site:
http://www.3ddrome.com/articles/dynamiclightmaps.php
c'est exactement ça, or ça marche (à peu près) avec des QUADS, bien que sous certains angle de lumière on voit une diagonale plus sombre sur le quads.
Effectivement on pourrai croire que 'i' et 'j' n'interviennent pas (directement) mais ils interviennent dans l'initialisation de:
pos[0] = surf->s_dist * s;
pos[1] = surf->t_dist * t;
pos[2] = 0.0f;

par l'intermédiaire de 's' et 't' qui sont incrémenté à chaque boucle.
Pour ce qui est des normals effectivement je ne vois pas où qu'ils interviennent.

En tous cas ça ne marche pas tip-top même si dans l'ensemble ça fonctionne.

Maintenant si t'a un site (tuto avec démo) à me conseiller, je suis preneur car je n'arrête pas de me promener sur la toile sans rien trouver d'efficace...

Cette démo me convenait bien (si elle fonctionnait à 100%) car à partir d'un polygone et d'une source lumineuse elle 'fabrique' une texture et renvoie un handle (c'est le principe des lightmap je pense), c'est exactement ce qu'il me faut pour mon application.
Donc si tu as une adresse avec un 'truc' équivalent je suis preneur...

D'avance merci, a+
0
luhtor Messages postés 2023 Date d'inscription mardi 24 septembre 2002 Statut Membre Dernière intervention 28 juillet 2008 6
17 déc. 2006 à 21:20
Ah oui, mais on parlait pas tout a fait de la meme chose, pour moi une
lightmap, c'est un truc qu'on applique sur un terrain. Et du coup, je
comprend pk les normales n'interviennent pas. Mais par contre, comment
détecter les faces qui sont de dos a la lumière sans normale... le
tutoriel est basique kan meme.


Mais t'as ptet pas besoin de tutoriel pour ca. Maintenant que tu as vu
le principe, tu peux faire toi meme ta fonction de calcul.


Mais dans tous les cas, tu dois avoir exactement le meme résultat avec
des quads ou avec des triangles. Si c'est pas le cas, c'est que tu t'es
planté dans ta décomposition.
0
manolobis Messages postés 21 Date d'inscription dimanche 5 juin 2005 Statut Membre Dernière intervention 17 décembre 2006
17 déc. 2006 à 23:00
En fait ce que j'essaie de faire c'est une texture qui représente l'éclairage de ma face et que je combine avec ma texture normale grâce au multitexturing de façon à éclairer mon objet en fonction de la position de la lumière tout cela en évitant le système d'éclairage d'OpenGL.
Je pensais, d'après les tutos que j'ai vu, qu'on appelait ça le LightMapping d'où le terme de LightMap.


Bon, mon pb n'est pas résolu, mais comme tu dis j'ai suffisamment bien compris le principe pour que je garde espoir d'en revoir le principe de calcul ou trouver un autre tuto plus fouillé.


Il est vrai que ce tuto avait l'avantage d'être simple, mais ce ne sont pas toujours les solutions les plus simples qui sont les plus efficaces...


Tchao et merci quand même pour tes réponses...
0
Rejoignez-nous