Question

Je développe actuellement un petit jeu OpenGL pour la plate-forme Android et je me demande s'il y a un moyen facile de rendre le texte sur le dessus du cadre rendu (comme un HUD avec les player's scores, etc.). Le texte aurait besoin d'utiliser une police personnalisée aussi.

Je l'ai vu un exemple en utilisant une vue comme une superposition, mais je ne sais pas si je veux faire depuis que je pourrais avoir besoin de porter le jeu vers d'autres plates-formes plus tard.

Toutes les idées?

Était-ce utile?

La solution

Le SDK Android ne vient pas avec un moyen facile de dessiner le texte sur les vues OpenGL. vous laissant avec les options suivantes.

  1. Placez un TextView sur votre SurfaceView. Ceci est lent et mauvais, mais l'approche la plus directe.
  2. Rendu des chaînes communes aux textures et simplement dessiner ces textures. Ceci est de loin la plus simple et plus rapide, mais moins flexible.
  3. roulées propre code de rendu de texte basé sur une image-objet. Probablement le deuxième meilleur choix si 2 n'est pas une option. Une bonne façon de se mouiller les pieds mais notez que tout cela semble simple (et les caractéristiques de base sont), il se est plus difficile et plus difficile que vous ajouter plus de fonctionnalités (texture alignement, traitant des sauts de ligne, les polices de largeur variables, etc. ) - si vous prenez cette route, le rendre aussi simple que vous pouvez vous en sortir avec
  4. Utilisez un impromptu / bibliothèque open source. Il y a quelques autour si vous chassez sur Google, le plus délicat est Incitant intégré et en cours d'exécution. Mais au moins, une fois que vous faites cela, vous aurez toute la flexibilité et la maturité qu'ils fournissent.

Autres conseils

Le rendu du texte à une texture est plus simple que ce que la démo du texte Sprite font ressemble, l'idée de base est d'utiliser la classe Canvas pour rendre à un Bitmap, puis passer le Bitmap à une texture OpenGL:

// Create an empty, mutable bitmap
Bitmap bitmap = Bitmap.createBitmap(256, 256, Bitmap.Config.ARGB_4444);
// get a canvas to paint over the bitmap
Canvas canvas = new Canvas(bitmap);
bitmap.eraseColor(0);

// get a background image from resources
// note the image format must match the bitmap format
Drawable background = context.getResources().getDrawable(R.drawable.background);
background.setBounds(0, 0, 256, 256);
background.draw(canvas); // draw the background to our bitmap

// Draw the text
Paint textPaint = new Paint();
textPaint.setTextSize(32);
textPaint.setAntiAlias(true);
textPaint.setARGB(0xff, 0x00, 0x00, 0x00);
// draw the text centered
canvas.drawText("Hello World", 16,112, textPaint);

//Generate one texture pointer...
gl.glGenTextures(1, textures, 0);
//...and bind it to our array
gl.glBindTexture(GL10.GL_TEXTURE_2D, textures[0]);

//Create Nearest Filtered Texture
gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_NEAREST);
gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR);

//Different possible texture parameters, e.g. GL10.GL_CLAMP_TO_EDGE
gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_S, GL10.GL_REPEAT);
gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T, GL10.GL_REPEAT);

//Use the Android GLUtils to specify a two-dimensional texture image from our bitmap
GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap, 0);

//Clean up
bitmap.recycle();

J'ai écrit un tutoriel qui se développe sur la réponse affichée par JVitela . En fait, il utilise la même idée, mais au lieu de rendre chaque chaîne à une texture, il rend tous les caractères d'un fichier de police à une texture et utilise pour permettre le rendu de texte dynamique complet sans ralentissement accru (une fois l'initialisation terminée) .

Le principal avantage de ma méthode, par rapport aux différents générateurs d'atlas de police, est que vous pouvez envoyer de petits fichiers de polices (.ttf .otf) avec votre projet au lieu d'avoir à expédier de grandes bitmaps pour chaque variation de la police et la taille. Il peut générer des polices de qualité parfaite à toute résolution en utilisant uniquement un fichier de police:)

tutoriel comprend code complet qui peut être utilisé dans tout projet:)

D'après ce lien:

http: //code.neenbedankt .com / comment-rendre-une-vue androïde à un bitmap

Vous pouvez rendre Voir tout un bitmap. Il est probablement utile de supposer que vous pouvez la mise en page en vue que vous avez besoin (y compris les textes, images, etc.), puis le rendre à un Bitmap.

En utilisant du code de JVitela ci-dessus vous devriez être en mesure de utiliser cette Bitmap comme une texture OpenGL.

Jetez un oeil à CBFG et le port Android du code de chargement / rendu. Vous devriez être en mesure de laisser tomber le code dans votre projet et de l'utiliser immédiatement.

CBFG - http://www.codehead.co.uk/cbfg

Android loader - http://www.codehead.co.uk/cbfg/TexFont.java

Je regardais l'exemple de texte de sprites et il semble terriblement compliqué pour une telle tâche, je considérais le rendu à une texture trop, mais je suis inquiet au sujet de la baisse de performance qui pourraient causer. Je pourrais avoir juste aller avec une vue au lieu et se soucier de portage quand il est temps de franchir ce pont:)

Regardez l'échantillon "Texte Sprite" dans le GLSurfaceView échantillons .

à mon humble avis, il y a trois raisons d'utiliser OpenGL ES dans un jeu:

  1. Évitez les différences entre les plates-formes mobiles en utilisant un standard ouvert;
  2. Pour avoir plus de contrôle du processus de rendu;
  3. Pour bénéficier du traitement parallèle du GPU;

texte Le dessin est toujours un problème dans la conception du jeu, parce que vous dessinez les choses, de sorte que vous ne pouvez pas avoir l'apparence d'une activité commune, avec des widgets et ainsi de suite.

Vous pouvez utiliser un cadre pour générer des polices Bitmap de polices TrueType et les rendre. Tous les cadres que j'ai vu fonctionnent de la même façon: générer le sommet et les coordonnées de texture pour le texte dans le temps de tirage au sort. Ce n'est pas l'utilisation la plus efficace d'OpenGL.

La meilleure façon est d'allouer des tampons à distance (objets de mémoire tampon de sommet - VBOs). Pour les sommets et les textures début de code, en évitant les opérations de transfert de mémoire paresseux dans le temps d'étirage

Gardez à l'esprit que les joueurs n'aiment pas lire le texte, de sorte que vous n'écrire un long texte généré dynamiquement. Pour les étiquettes, vous pouvez utiliser des textures statiques, laissant le texte dynamique pour le temps et le score, et les deux sont numérique avec quelques caractères.

Alors, ma solution est simple:

  1. Créer la texture pour les étiquettes communes et mises en garde;
  2. Créer la texture pour les nombres 0-9, ":", "+" et "-". Une texture pour chaque caractère;
  3. Générer VBOs à distance pour toutes les positions à l'écran. Je peux imprimer le texte statique ou dynamique en ce que les positions, mais les VBOs sont statiques;
  4. Générer une seule texture VBO, sous forme de texte est toujours rendu d'une façon;
  5. Dans le temps de tirage au sort, je rends le texte statique;
  6. texte dynamique, je peux jeter un regard à la VBO position, obtenir la texture de caractère et dessiner, un caractère à la fois.

Dessiner les opérations sont rapides, si vous utilisez des tampons statiques à distance.

Je crée un fichier XML avec des positions d'écran (en fonction du pourcentage de la diagonale de l'écran) et textures (statiques et caractères), puis-je charger cette XML avant de rendre.

Pour obtenir un taux élevé FPS, vous devez éviter de générer VBOs au moment du tirage au sort.

Si vous insistez sur l'utilisation de GL, vous pouvez rendre le texte sur les textures. En supposant que la plupart du HUD est relativement statique, vous ne devriez pas avoir à charger les textures dans la mémoire de texture trop souvent.

Jetez un oeil à CBFG et le port Android du chargement / rendu code. Vous devriez être en mesure de laisser tomber le code dans votre projet et de l'utiliser tout de suite.

  1. CBFG

  2. Android loader

J'ai des problèmes avec cette mise en œuvre. Il affiche un seul caractère, lorsque je tente de faire la taille changement de bitmap de la police (j'ai besoin des lettres spéciales) ne ensemble nul: (

Je cherchais cela pendant quelques heures, ce fut le premier article, je suis tombé et bien qu'il ait la meilleure réponse, je pense que les réponses les plus populaires sont loin du compte. Certes, pour ce que je avais besoin. de Weichsel et les réponses de shakazed avaient raison sur le bouton, mais un peu obscurci dans les articles. Pour vous mettre droit au projet. Ici: Il suffit de créer un nouveau projet Android basé sur un échantillon existant. Choisissez ApiDemos:

Rechercher dans le dossier source

ApiDemos/src/com/example/android/apis/graphics/spritetext

Et vous trouverez tout ce dont vous avez besoin.

texte statique :

  • Générer une image avec tous les mots utilisés sur votre PC (par exemple avec GIMP).
  • Charger cela comme une texture et l'utiliser comme matériau pour un avion.

long texte qui doit être mis à jour de temps en temps:

  • Soit tirage Android sur une toile bitmap (solution de JVitela).
  • Chargez ce matériau comme pour un avion.
  • Utiliser la texture coordonnées différentes pour chaque mot.

plusieurs (au format 00.0):

  • Générer une image avec tous les chiffres et un point.
  • Chargez ce matériau comme pour un avion.
  • Utilisez ci-dessous shader.
  • Dans votre cas onDraw seule mise à jour de la variable de valeur envoyée au shader.

    precision highp float;
    precision highp sampler2D;
    
    uniform float uTime;
    uniform float uValue;
    uniform vec3 iResolution;
    
    varying vec4 v_Color;
    varying vec2 vTextureCoord;
    uniform sampler2D s_texture;
    
    void main() {
    
    vec4 fragColor = vec4(1.0, 0.5, 0.2, 0.5);
    vec2 uv = vTextureCoord;
    
    float devisor = 10.75;
    float digit;
    float i;
    float uCol;
    float uRow;
    
    if (uv.y < 0.45) {
        if (uv.x > 0.75) {
            digit = floor(uValue*10.0);
            digit = digit - floor(digit/10.0)*10.0;
            i = 48.0 - 32.0 + digit;
            uRow = floor(i / 10.0);
            uCol = i - 10.0 * uRow;
            fragColor = texture2D( s_texture, uv / devisor * 2.0 + vec2((uCol-1.5) / devisor, uRow / devisor) );
        } else if (uv.x > 0.5) {
            uCol = 4.0;
            uRow = 1.0;
            fragColor = texture2D( s_texture, uv / devisor * 2.0 + vec2((uCol-1.0) / devisor, uRow / devisor) );
        } else if (uv.x > 0.25) {
            digit = floor(uValue);
            digit = digit - floor(digit/10.0)*10.0;
            i = 48.0 - 32.0 + digit;
            uRow = floor(i / 10.0);
            uCol = i - 10.0 * uRow;
            fragColor = texture2D( s_texture, uv / devisor * 2.0 + vec2((uCol-0.5) / devisor, uRow / devisor) );
        } else if (uValue >= 10.0) {
            digit = floor(uValue/10.0);
            digit = digit - floor(digit/10.0)*10.0;
            i = 48.0 - 32.0 + digit;
            uRow = floor(i / 10.0);
            uCol = i - 10.0 * uRow;
            fragColor = texture2D( s_texture, uv / devisor * 2.0 + vec2((uCol-0.0) / devisor, uRow / devisor) );
        } else {
            fragColor = vec4(0.0, 0.0, 0.0, 0.0);
        }
    } else {
        fragColor = vec4(0.0, 0.0, 0.0, 0.0);
    }
    gl_FragColor = fragColor;
    
    }
    

code ci-dessus fonctionne pour un atlas de texture où le nombre commence à 0 à la 7e colonne de la 2ème ligne de l'atlas de police (texture).

Reportez-vous à https://www.shadertoy.com/view/Xl23Dw pour la démonstration ( avec mauvaise texture bien)

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top