IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

SDL Discussion :

Afficher du texte avec SDL et OpenGL


Sujet :

SDL

  1. #1
    Futur Membre du Club
    Profil pro
    Étudiant
    Inscrit en
    Novembre 2007
    Messages
    15
    Détails du profil
    Informations personnelles :
    Âge : 33
    Localisation : Belgique

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Novembre 2007
    Messages : 15
    Points : 7
    Points
    7
    Par défaut Afficher du texte avec SDL et OpenGL
    Bonjour,

    Je crée un jeu (Othello-Reversi) pour un projet scolaire, et je suis confronté à un problème lors de l'écriture du nom du joueur.

    Je désire écrire avec SDL_ttf du texte sur la grille dessinée grâce à OpenGL. Il n'y aura pas de 3D dans le jeu, il est inutile d'utiliser un buffer DEPTH.

    À partir de ce code :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    #include <iostream>
    #include <SDL/SDL.h>
    #include <SDL/SDL_ttf.h>
    #include <GL/gl.h>
    #include <GL/glu.h>
    #include <string>
    #define _USE_MATH_DEFINES
    #include <math.h>
     
    #define LARGEUR_FENETRE 700
    #define HAUTEUR_FENETRE 480
    #define Nlignes 8
    #define Ncolonnes 8
     
    using namespace std;
     
    void ecrire(...);
     
    int main(int argc, char *argv[]) {
    	bool continuer = true;
    	SDL_Surface *fenetre = NULL;
    	SDL_Event evenement;
    	SDL_Color couleur_txt = {0, 0, 0};
     
    	SDL_Init(SDL_INIT_VIDEO); // Initialisaion de SDL en mode vidéo.
    	TTF_Init();
    	fenetre = SDL_SetVideoMode(LARGEUR_FENETRE, HAUTEUR_FENETRE, 32, SDL_OPENGL); // Création de la fenêtre pour OpenGL.
    	SDL_WM_SetCaption("Jeu Othello-Reversi", NULL); // Titre de la fenêtre.
    	glClearColor(0.85, 1, 0.9, 0); // Couleur de fond
    	glEnable(GL_BLEND);  // Permet d'utiliser l'opacité
    	glEnable(GL_TEXTURE_2D);
    	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // Pour l'opacité
    	do {
    		glMatrixMode(GL_MODELVIEW);
    		glLoadIdentity();
    		glClear(GL_COLOR_BUFFER_BIT);
    		gluOrtho2D(0, LARGEUR_FENETRE, HAUTEUR_FENETRE, 0);
     
    		glBegin(GL_QUADS);
    			glColor4ub(16, 116, 21, 255);
    			glVertex2d(40, 40); // Cadre de la grille
    			glVertex2d(40, 440);
    			glVertex2d(440, 440);
    			glVertex2d(440, 40);
    		glEnd();
     
    		glBegin(GL_LINES);
    			glColor4ub(9, 62, 12, 255);
    			for (int i = 40; i <= 440; i++) { // Lignes horizontales de la grille
    				glVertex2d(40, i);
    				glVertex2d(440, i);
    				i += 49;
    			}
    			for (int i = 40; i <= 440; i++) { // Lignes verticales de la grille
    				glVertex2d(i, 40);
    				glVertex2d(i, 440);
    				i += 49;
    			}
    		glEnd();
     
    		ecrire(...);
     
    		SDL_PollEvent(&evenement); // Gestion des événements
    		switch (evenement.type) {
    			case SDL_QUIT:
    				continuer = false;
    			break;
    		}
     
    		SDL_GL_SwapBuffers();
    	} while(continuer);
     
    	TTF_Quit();
    	SDL_FreeSurface(fenetre);
    	SDL_Quit();
     
    	return EXIT_SUCCESS;
    }
     
    void ecrire(...) {
     
    }
    Quel doit-être le contenu de la fonction ecrire ? Est-ce que les éléments déclarés dans le main sont corrects (glEnable, glBlendFunc) ou en manque-t-il ? Je voudrais garder le gluOrtho2D(0, LARGEUR_FENETRE, HAUTEUR_FENETRE, 0);, est-ce possible ?

    Voici la fonction que j'ai tenté d'écrire, mais qui ne fonctionne pas :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    void ecrire(string texte, string nom_police, SDL_Color couleur, int pos_x, int pos_y, int taille) {
    	SDL_Rect position;
    	TTF_Font *police;
    	police = TTF_OpenFont(nom_police.c_str(), taille);
    	position.x = pos_x;
    	position.y = pos_y;
    	SDL_Surface *message = TTF_RenderText_Blended(police, texte.c_str(), couleur);
    	GLuint texture = 0;
    	int largeur_texture, hauteur_texture;
     
    	glGenTextures(1, &texture);
    	glBindTexture(GL_TEXTURE_2D, texture);
     
    	// Il faut que les dimensions de la texture soient de taille 2^n (32, 64, 128,...).
    	largeur_texture = (int)(pow(2, ceil(log((float)message->w) / log(2.0))) + 0.5);
    	hauteur_texture = (int)(pow(2, ceil(log((float)message->h) / log(2.0))) + 0.5);
     
    	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, largeur_texture, hauteur_texture, 0, GL_RGBA, GL_UNSIGNED_BYTE, message->pixels);
    	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
     
    	glBegin(GL_QUADS);
    		glTexCoord2i(0, 0); glVertex2d(position.x, position.y);
    		glTexCoord2i(1, 0); glVertex2d(position.x+message->w, position.y);
    		glTexCoord2i(1, 1); glVertex2d(position.x+message->w, position.y+message->h);
    		glTexCoord2i(0, 1); glVertex2d(position.x, position.y+message->h);
    	glEnd();
     
    	glDeleteTextures(1, &texture);
    	SDL_FreeSurface(message);
    	TTF_CloseFont(police);
    }
    Et l'appel dans le main :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    ecrire("Hello", "verdana.ttf", couleur_txt, 50, 100, 50);

    Ça fait deux jours que je cherche à corriger l'erreur obtenue, à savoir celle-ci :



    Lorsque je n'ai pas cette erreur, j'obtiens un truc déformé :


    Quel est le problème ? Si vous ne voyez pas la source de l'erreur, comment coderiez-vous la fonction ecrire (à savoir que j'en ai essayé pas mal et que j'ai déjà beaucoup recherché sur le net et par moi-même) ?

    Merci d'avance.

  2. #2
    Expert éminent sénior
    Avatar de Kannagi
    Homme Profil pro
    cyber-paléontologue
    Inscrit en
    Mai 2010
    Messages
    3 225
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : cyber-paléontologue

    Informations forums :
    Inscription : Mai 2010
    Messages : 3 225
    Points : 10 168
    Points
    10 168
    Par défaut
    Je pense que erreur viens de la:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, largeur_texture, hauteur_texture, 0, GL_RGBA, GL_UNSIGNED_BYTE, message->pixels);
    Le problème c'est que ,je sais pas si tu sais comment cela fonctionne mais quand tu met les valeur de largeur , hauteur elle doive correspondre a message->w et message->h , il faut pas les changer , pour un exemple simple (une image grosso modo c'est un tableau unsigned char), opengl a besoin de savoir donc comme ce lis ce jolie tableau (RVBA, largeur, hauteur du tableau ects) , Donc si tu met des valeur plus grande que message->h et message->w il lira plus loin que le tableau et tu peux avoir une segmentation de mémoire.

    Pour avoir des puissance de 2^N , pour ma part je rempli les trous par une valeur transparente , et modifie après les valeur de la largeur/hauteur.

  3. #3
    Futur Membre du Club
    Profil pro
    Étudiant
    Inscrit en
    Novembre 2007
    Messages
    15
    Détails du profil
    Informations personnelles :
    Âge : 33
    Localisation : Belgique

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Novembre 2007
    Messages : 15
    Points : 7
    Points
    7
    Par défaut
    Merci beaucoup pour ces explications, je comprends désormais l'origine de l'erreur, ce qui n'était pas le cas avant. Je trouve que les tutos n'expliquent pas assez de genre de résolutions internes, et pourtant c'est important pour détecter l'origine des problèmes, ou simplement pour information.

    Par contre, je ne comprends pas comment résoudre le problème. Comment fais-tu pour boucher les trous par du transparent ? Aurais-tu un exemple ? Ou mieux, peux-tu rapidement modifier ma fonction ecrire afin qu'elle fonctionne ? Je devrais être capable de comprendre par moi-même après ça normalement. Enfin, j'espère !

    Déjà merci beaucoup pour ces indications en tout cas.

  4. #4
    Expert éminent sénior
    Avatar de Kannagi
    Homme Profil pro
    cyber-paléontologue
    Inscrit en
    Mai 2010
    Messages
    3 225
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : cyber-paléontologue

    Informations forums :
    Inscription : Mai 2010
    Messages : 3 225
    Points : 10 168
    Points
    10 168
    Par défaut
    Je suis d'accord que les tutoriaux reste assez évasive.

    Pour le code tu aurais pu te renseigner sur la Doc officiel de la SDL mais bref.
    Ce code je ne l'ai pas testé sur opengl donc il se peux que ça marche pas (m'enfin j’espère que ça marchera =P ).
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    	SDL_Surface *image = TTF_RenderText_Solid(police,"test",couleur);
        unsigned char *pixels = image->pixels;
     
        int w = image->w + 10; // si on veut rajouter + 10 en w
        int h = image->h + 0;
        int taille = (w*h*image->format->BytesPerPixel);
        unsigned char *cpixels = malloc(taille * sizeof(unsigned char) );
     
        i = 0;
        int k = 0;
        for(y=0;y <h;y++)
        {
            for(x=0;x <w;x++)
            {
                if( (x < image->w) && (y < image->h) )
                {
                    cpixels[k] = pixels[i];
                    //cpixels[k+1] = pixels[i+1]; //dépend de image->format->BytesPerPixel;
                    //cpixels[k+2] = pixels[i+2];//dépend de image->format->BytesPerPixel;
     
                    i = i +image->format->BytesPerPixel;
                }else
                    cpixels[k] = 0;//sera transparent si c'est un RVBA
     
                k = k+image->format->BytesPerPixel;
            }
        }
     
        free(pixels);
     
        image->pixels = cpixels;
     
        image->w = w;
        image->h = h;
    Ce code serait en partie faux pour la SDL (si on utilise SDL_Blit vu qu'il faut modifier image->pitch au lieu de image->w;

    D’ailleurs je viens de capter mais pas sur que ça soit des RGBA les image.
    Il faut le vérifié avec soit BytesPerPixel ou BitsPerPixel.

  5. #5
    Futur Membre du Club
    Profil pro
    Étudiant
    Inscrit en
    Novembre 2007
    Messages
    15
    Détails du profil
    Informations personnelles :
    Âge : 33
    Localisation : Belgique

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Novembre 2007
    Messages : 15
    Points : 7
    Points
    7
    Par défaut
    J'ai trouvé une autre solution, qui me paraît plus simple.
    J'ai rempli la texture en couleur quelconque (celle en cours). Ensuite, j'y ai ajouté le texte proprement dit, dessiné par SDL_ttf. Le texte est plus petit que la texture (vu que la texture a été agrandie en une taille puissance 2), il faut donc repérer les limites du textes dans la texture. Je fais cela grâce aux ratios largeur_texte / largeur_texture et hauteur_texte / hauteur_texture.

    Ce code fonctionne donc :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    #include <iostream>
    #include <SDL/SDL.h>
    #include <SDL/SDL_ttf.h>
    #include <GL/gl.h>
    #include <GL/glu.h>
    #include <string>
    #define _USE_MATH_DEFINES
    #include <math.h>
     
    #define LARGEUR_FENETRE 700
    #define HAUTEUR_FENETRE 480
    #define Nlignes 8
    #define Ncolonnes 8
     
    using namespace std;
     
    void ecrire(string texte, string nom_police, SDL_Color couleur, int pos_x, int pos_y, int taille);
     
    int main(int argc, char *argv[]) {
    	bool continuer = true;
    	SDL_Surface *fenetre = NULL;
    	SDL_Event evenement;
    	SDL_Color couleur_txt = {0, 0, 0};
     
    	SDL_Init(SDL_INIT_VIDEO); // Initialisaion de SDL en mode vidéo.
    	TTF_Init();
    	fenetre = SDL_SetVideoMode(LARGEUR_FENETRE, HAUTEUR_FENETRE, 32, SDL_OPENGL); // Création de la fenêtre pour OpenGL.
    	SDL_WM_SetCaption("Jeu Othello-Reversi", NULL); // Titre de la fenêtre.
    	glClearColor(0.85, 1, 0.9, 0); // Couleur de fond
    	glEnable(GL_BLEND);  // Permet d'utiliser l'opacité
    	glEnable(GL_TEXTURE_2D);
    	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // Pour l'opacité
    	glMatrixMode(GL_PROJECTION);
    	gluOrtho2D(0, LARGEUR_FENETRE, HAUTEUR_FENETRE, 0);
    	do {
    		glMatrixMode(GL_MODELVIEW);
    		glLoadIdentity();
    		glClear(GL_COLOR_BUFFER_BIT);
     
    		glBegin(GL_QUADS);
    			glColor4ub(16, 116, 21, 255);
    			glVertex2d(40, 40); // Cadre de la grille
    			glVertex2d(40, 440);
    			glVertex2d(440, 440);
    			glVertex2d(440, 40);
    		glEnd();
     
    		glBegin(GL_LINES);
    			glColor4ub(9, 62, 12, 255);
    			for (int i = 40; i <= 440; i++) { // Lignes horizontales de la grille
    				glVertex2d(40, i);
    				glVertex2d(440, i);
    				i += 49;
    			}
    			for (int i = 40; i <= 440; i++) { // Lignes verticales de la grille
    				glVertex2d(i, 40);
    				glVertex2d(i, 440);
    				i += 49;
    			}
    		glEnd();
     
    		ecrire("Hello", "verdana.ttf", couleur_txt, 400, 100, 50);
    		ecrire("Hello !", "verdana.ttf", couleur_txt, 400, 180, 50);
     
    		SDL_PollEvent(&evenement); // Gestion des événements
    		switch (evenement.type) {
    			case SDL_QUIT:
    				continuer = false;
    			break;
    		}
     
    		SDL_GL_SwapBuffers();
    	} while(continuer);
     
    	TTF_Quit();
    	SDL_FreeSurface(fenetre);
    	SDL_Quit();
     
    	return EXIT_SUCCESS;
    }
     
    void ecrire(string texte, string nom_police, SDL_Color couleur, int pos_x, int pos_y, int taille) {
    	SDL_Rect position;
    	TTF_Font *police;
    	police = TTF_OpenFont(nom_police.c_str(), taille);
    	position.x = pos_x;
    	position.y = pos_y;
    	SDL_Surface *message = TTF_RenderText_Blended(police, texte.c_str(), couleur);
    	GLuint texture = 0;
    	int largeur_texture, hauteur_texture;
    	float ratio_largeur, ratio_hauteur;
     
    	glGenTextures(1, &texture);
    	glBindTexture(GL_TEXTURE_2D, texture);
     
    	// Il faut que les dimensions de la texture soient de taille 2^n (32, 64, 128,...).
    	largeur_texture = (int)(pow(2, ceil(log((float)message->w) / log(2.0))) + 0.5);
    	hauteur_texture = (int)(pow(2, ceil(log((float)message->h) / log(2.0))) + 0.5);
     
    	// On va prolonger les images pour avoir des puissances de 2. Mais ce prolongement sera coloré et n'aura rien à voir avec le texte à afficher. Nous ne devrons donc pas l'insérer dans la texture. On retient donc un ratio pour repérer la séparation entre la fin du texte et le prolongement de la texture.
    	ratio_largeur = (float)message->w / (float)largeur_texture;
    	ratio_hauteur = (float)message->h / (float)hauteur_texture;
     
    	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, largeur_texture, hauteur_texture, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); // Texture aux dimensions 2^n.
    	glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, message->w, message->h, GL_RGBA, GL_UNSIGNED_BYTE, message->pixels); // Insertion du texte dans la texture. Celui-ci ne prend pas forcément toute la place (largeur_texture et hauteur_texture sont >= à message->w et message->h).
     
    	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
     
    	glBegin(GL_QUADS);
    		glTexCoord2f(0, 0); glVertex2d(position.x, position.y);
    		glTexCoord2f(ratio_largeur, 0); glVertex2d(position.x+message->w, position.y);
    		glTexCoord2f(ratio_largeur, ratio_hauteur); glVertex2d(position.x+message->w, position.y+message->h);
    		glTexCoord2f(0, ratio_hauteur); glVertex2d(position.x, position.y+message->h);
    	glEnd();
     
    	glDeleteTextures(1, &texture);
    	SDL_FreeSurface(message);
    	TTF_CloseFont(police);
    }

    Mais en tout cas un grand merci pour ta réponse, car sans connaître l'origine du problème, j'étais loin de trouver une solution.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Afficher du texte avec SDL_ttf dans un environnement OpenGL
    Par Davidlouiz dans le forum API graphiques
    Réponses: 2
    Dernier message: 11/05/2012, 22h52
  2. Réponses: 3
    Dernier message: 11/07/2011, 17h51
  3. Afficher du texte avec OpenGL
    Par Happy dans le forum Contribuez
    Réponses: 0
    Dernier message: 27/09/2009, 00h29
  4. Afficher du texte avec SDL.
    Par kmitz dans le forum SDL
    Réponses: 14
    Dernier message: 30/04/2006, 19h56
  5. Comment afficher du texte avec swing ?
    Par meda dans le forum AWT/Swing
    Réponses: 8
    Dernier message: 27/10/2004, 14h35

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo