Bienvenue, Invité. Merci de vous connecter ou de vous inscrire.
Avez-vous perdu votre e-mail d'activation ?

Auteur Sujet: Texture mapping ! Oui, mais... *tousse*  (Lu 7582 fois)

0 Membres et 5 Invités sur ce sujet

CINEfilHD77

  • Newbie
  • *
  • Messages: 38
    • Voir le profil
Texture mapping ! Oui, mais... *tousse*
« le: Juillet 24, 2014, 12:26:07 am »
Bonjour à tous !  :)

J'en profite de passer par là pour que vous m'aidiez à résoudre un petit problème.

(click to show/hide)

EDIT : J'en ai marre de passer des jours et des jours sur un problème, et de trouver la solution pure et dure à la minute où j'ai posté sur votre forum !!! Ce forum est magique, merci Laurent ! :P
« Modifié: Juillet 24, 2014, 12:42:47 am par CINEfilHD77 »

G.

  • Hero Member
  • *****
  • Messages: 1593
    • Voir le profil
Re : Texture mapping ! Oui, mais... *tousse*
« Réponse #1 le: Juillet 24, 2014, 01:01:39 am »
Bah si t'as la solution donne la. :p

Laurent

  • Administrator
  • Hero Member
  • *****
  • Messages: 32498
    • Voir le profil
    • SFML's website
    • E-mail
Re : Texture mapping ! Oui, mais... *tousse*
« Réponse #2 le: Juillet 24, 2014, 07:31:28 am »
De rien :P
Laurent Gomila - SFML developer

CINEfilHD77

  • Newbie
  • *
  • Messages: 38
    • Voir le profil
Re : Texture mapping ! Oui, mais... *tousse*
« Réponse #3 le: Juillet 24, 2014, 01:07:27 pm »
Bah si t'as la solution donne la. :p

En fait, c'est pas dur !
Admettons que tu as deux textures :

On va dire ici que la texture de base de ton terrain (La principale) est l'herbe, et que tu veux mettre des bouts de sable un peu partout.
Pour réaliser ça, il te faut ce qu'on appelle une alpha map (En fait ça a genre plein de noms), qui va permettre, en nuances de gris, de représenter la répartition de la-dite texture, avec comme base : Noir = Rien, Blanc = Ta texture, Gris = Mix
Par exemple, pour un terrain 200x200, on va dire que, pour la texture de sable, j'ai cette alpha map :



Donc, tu vois, au final, je suis sensé avoir de l'herbe sur ton mon terrain, sauf vers le centre où on doit avoir un banc de sable.

Pour réaliser cette effet, donc, il faut les objets SFML suivants :
Deux sf::Texture pour l'herbe et le sable.
Deux autres, une pour l'alpha-map, une autre pour son inverse (J'expliquerai plus loin).
Quatre sf::RectangleShape (ou sf::Sprite) pour représenter les calques de terrain (Un contiendra seulement l'herbe, l'autre seulement le sable), les alpha-map.
Deux sf::Sprite pour avoir le calque du sable final, et le sol texturé final à afficher.
Deux sf::RenderTexture pour composer avec ces différents objets via sf::BlendMode.

Voyons du côté du code :

sf::Texture t_herbe, t_sable, t_alphamap, t_alphamap_inv;

sf::RenderTexture r_sol, r_sable;

sf::RectangleShape herbe, sable, alphamap, alphamap_inv;

sf::Sprite sable_final, sol_final;

Ensuite, tu fais tes chargements de fichiers :

t_herbe.loadFromFile("herbe.png");
t_herbe.setRepeated(true);

t_sable.loadFromFile("sable.png");
t_sable.setRepeated(true);

t_alphamap.loadFromFile("alpha.png");

t_alphamap_inv.loadFromFile("alpha_inv.png");

Puis tu fais les réglages sur les sf::RenderTexture :

r_sol.create(200, 200);
r_sol.clear(sf::Color::White);

r_sable.create(200, 200);
r_sable.clear(sf::Color::White);

et sur les sf::RectangleShape :

herbe.setSize(sf::Vector2f(200, 200));
herbe.setTexture(&t_herbe);

/* (IDEM pour les autres) */

Et puis maintenant, on se met au boulot !

D'abord, tu fais le rendu de ta texture de base (ici, l'herbe), en entier.

r_sol.draw(herbe, sf::BlendMultiply);

Puis tu dégages toutes les parties où le sable doit être (C'est là qu'intervient l'alpha-map inversée, en gros ça te fais du masking), avec de la multiplication de texture (Le noir efface, le blanc conserve).

r_sol.draw(alphamap_inv, sf::BlendMultiply);

Tu actualises la sf::RenderTexture (Pour éviter les inversions d'axe) :

r_sol.display();

Avec mon exemple, ma sf::RenderTexture contient, à présent, quelque chose comme ça :


Ensuite, tu fais la même chose pour le sable :

r_sable.draw(sable, sf::BlendMultiply);
r_sable.draw(alphamap, sf::BlendMultiply);
r_sable.display();

Ce qui te donne quelque chose comme ça :



Maintenant, il reste plus qu'à composer, via les sf::Sprite.

sable_final.setTexture(r_sable.getTexture());
sol_final.setTexture(r_sol.getTexture())

r_sol.draw(sable_final, sf::BlendAdd);
r_sol.display();

Et puis bah il te reste plus qu'à afficher le tout dans ta boucle principale, c'est-à-dire seulement le sf::Sprite sol_final !

Tu as donc :



Et voilà ! :)

Après, c'est peut-être bordélique, et puis j'explique pas bien, et si c'est pas très optimisé, je remercie d'avance les personnes qui pourraient aider à l'amélioration de la chose !

P.S. : Tu peux très bien faire ça avec plus de deux textures, il suffit à chaque fois de faire du masking sur les textures selon laquelle superpose laquelle.

P.S. 2 : Au lieu de charger une autre alpha-map pré-inversée, tu peux l'inverser dans le programme, j'imagine que c'est possible avec la SFML sans aucun problème.
« Modifié: Juillet 24, 2014, 01:09:10 pm par CINEfilHD77 »

Laurent

  • Administrator
  • Hero Member
  • *****
  • Messages: 32498
    • Voir le profil
    • SFML's website
    • E-mail
Re : Texture mapping ! Oui, mais... *tousse*
« Réponse #4 le: Juillet 24, 2014, 02:32:55 pm »
Sinon, avec un pixel shader ça doit être plus simple et moins gourmand (aucun sf::RenderTexture intermédiaire).
Laurent Gomila - SFML developer

CINEfilHD77

  • Newbie
  • *
  • Messages: 38
    • Voir le profil
Re : Texture mapping ! Oui, mais... *tousse*
« Réponse #5 le: Juillet 24, 2014, 03:33:53 pm »
Oui, j'ai lu ça sur le Net hier soir, mais je suis pas très à l'aise avec les Shaders pour l'instant, et je trouve pas de shader pré-fait pour ce genre de chose... :)

kimci86

  • Full Member
  • ***
  • Messages: 128
    • Voir le profil
Re : Texture mapping ! Oui, mais... *tousse*
« Réponse #6 le: Juillet 24, 2014, 05:35:34 pm »
Bonjour,

Il n'est pas utile d'appliquer l'alphamap en négatif sur l'herbe, cela crée une couronne grise autour du sable.

Il me semble plus approprié d'utiliser l'alpha map en tant que calque alpha pour le sable. On peut le faire au début du programme grâce une sf::Image dans laquelle on change l'alpha des pixels et que l'on charge ensuite dans une sf::Texture mais c'est probablement un peu lent et ça demande de faire une Texture par alpha map et par terrain.
Avec un sf::Shader, je ne suis pas expert mais ça devrait ressembler à ça :
uniform sampler2D texture;
uniform sampler2D alpha;

void main(void)
{
    gl_FragColor = gl_Color * texture2D(texture, gl_TexCoord[0].xy);
    gl_FragColor.w *= texture2D(alpha, gl_TexCoord[0].xy).x;
}
(edit: code corrigé)

Pour chaque pixel, on multiplie l'alpha du sable avec la nuance de gris de l'alpha map.

Du code pour le tester :
#include <SFML/Graphics.hpp>

int main()
{
    sf::Texture sandTex, grassTex, alphaTex;
    sandTex.loadFromFile("sand.jpg");
    grassTex.loadFromFile("grass.jpg");
    alphaTex.loadFromFile("alpha.png");

    sf::Sprite sand(sandTex), grass(grassTex);

    sf::Shader alpha;
    alpha.loadFromFile("alpha.frag", sf::Shader::Fragment);
    alpha.setParameter("texture", sf::Shader::CurrentTexture);
    alpha.setParameter("alpha", alphaTex);

    sf::RenderWindow window(sf::VideoMode(256, 256), "sfml window");

    while(window.isOpen())
    {
        sf::Event event;
        while(window.pollEvent(event))
            if(event.type == sf::Event::Closed)
                window.close();

        window.clear();
        window.draw(grass);
        window.draw(sand, &alpha);
        window.display();
    }

    return 0;
}
« Modifié: Juillet 30, 2014, 07:37:11 pm par kimci86 »

CINEfilHD77

  • Newbie
  • *
  • Messages: 38
    • Voir le profil
Re : Texture mapping ! Oui, mais... *tousse*
« Réponse #7 le: Juillet 24, 2014, 09:50:09 pm »
En fait, en utilisant sf::BlendMode, j'étais obligé d'utiliser une alphamap inversée pour l'herbe, sinon, avec le BlendMode en multiplication quand on dessine le sable sur l'herbe, ça mélange tout et ça fait du sable vert... :P

Mais donc, du coup, avec ce shader que tu proposes, ci je comprends bien, il faut que l'alphamap soit transparente, avec des tâches plus ou moins opaques de blanc, ou alors on conserve la nuance de gris avec le code Noir = Rien, Blanc = Plein comme ce que j'ai ?

kimci86

  • Full Member
  • ***
  • Messages: 128
    • Voir le profil
Re : Texture mapping ! Oui, mais... *tousse*
« Réponse #8 le: Juillet 25, 2014, 11:21:23 am »
Mais donc, du coup, avec ce shader que tu proposes, ci je comprends bien, il faut que l'alphamap soit transparente, avec des tâches plus ou moins opaques de blanc, ou alors on conserve la nuance de gris avec le code Noir = Rien, Blanc = Plein comme ce que j'ai ?

On utilise des nuances de gris. D'ailleurs je vois que j'ai oublié quelque chose dans mon shader: Il faut multiplier la transparence du pixel par un scalaire bien sûr, pas par un vec4.
Pour obtenir ce scalaire, on peut choisir n'importe quel canal de l'alphamap entre rouge, vert et bleu puisqu'elle est composée de nuances de gris. J'ai choisi ici le rouge.

uniform sampler2D texture;
uniform sampler2D alpha;

void main(void)
{
    gl_FragColor = gl_Color * texture2D(texture, gl_TexCoord[0].xy);
    gl_FragColor.w *= texture2D(alpha, gl_TexCoord[0].xy).x;
}

CINEfilHD77

  • Newbie
  • *
  • Messages: 38
    • Voir le profil
Re : Texture mapping ! Oui, mais... *tousse*
« Réponse #9 le: Juillet 26, 2014, 06:27:26 pm »
D'accord, parfait ! Du coup, là j'ai pas le temps de tester, mais la semaine prochaine je regarde et je vous dis ! :)

CINEfilHD77

  • Newbie
  • *
  • Messages: 38
    • Voir le profil
Re : Texture mapping ! Oui, mais... *tousse*
« Réponse #10 le: Juillet 30, 2014, 04:58:52 pm »
Rebonjour !
Donc, du coup voilà, j'ai testé, la texture se peint parfaitement, mais j'ai un souci...
En fait, vu que sur mon terrain la texture de sable se répète (Elle fait 256x256 pixels), et bah quand j'applique le shader, voilà ce que ça fait : (Mon alpha-map fait 800x600 pixels)



Vous avez une idée du pourquoi ? Parce que je sèche moi (Vu que les Shaders j'avais jamais touché avant...) :)

P.S. : Faites pas gaffe au texte qui parle de FPS sur l'image, j'avais la flemme de l'enlever de mon code... :P

kimci86

  • Full Member
  • ***
  • Messages: 128
    • Voir le profil
Re : Texture mapping ! Oui, mais... *tousse*
« Réponse #11 le: Juillet 30, 2014, 07:34:41 pm »
Vous avez une idée du pourquoi ?

Le pourquoi de quoi ? Quel est le problème ?

CINEfilHD77

  • Newbie
  • *
  • Messages: 38
    • Voir le profil
Re : Texture mapping ! Oui, mais... *tousse*
« Réponse #12 le: Juillet 30, 2014, 08:57:42 pm »
Ah oui désolé, en relisant je me suis rendu compte qu'il manque l'explication :P
Bah, en fait, c'est que la tache de sable qu'on voit, elle est censée être beaucoup plus grosse et au milieu. Là, elle s'est adaptée à la taille de la texture de sable... Apparemment, le masking se fait sur la texture de base, et pas sur la surface entière remplie par répétition...
J'espère être clair ! :)

kimci86

  • Full Member
  • ***
  • Messages: 128
    • Voir le profil
Re : Texture mapping ! Oui, mais... *tousse*
« Réponse #13 le: Juillet 31, 2014, 11:48:38 am »
En effet gl_TexCoord[0].xy donne la position normalisée du pixel en cours de traitement dans la texture de sable. Pour avoir la position correspondante dans la texture de l'alphamap, on peut multiplier ce vecteur par le rapport des tailles des textures. Ce n'est peut être pas la meilleure façon de procéder, je ne suis pas expert, mais ça marche bien.

uniform sampler2D texture;
uniform vec2 textureSize;

uniform sampler2D alpha;
uniform vec2 alphaSize;

void main(void)
{
    gl_FragColor = gl_Color * texture2D(texture, gl_TexCoord[0].xy);
    gl_FragColor.w *= texture2D(alpha, gl_TexCoord[0].xy * textureSize / alphaSize).x;
}

Il ne faut pas oublier de donner les valeurs correspondantes aux vecteurs textureSize et alphaSize à l'aide de la méthode setParameter du sf::Shader.

CINEfilHD77

  • Newbie
  • *
  • Messages: 38
    • Voir le profil
Re : Texture mapping ! Oui, mais... *tousse*
« Réponse #14 le: Juillet 31, 2014, 01:41:30 pm »
Ah oui en effet, ça fonctionne, c'est parfait ! Merci beaucoup ! :)