Domanda

Al momento sto sviluppando un piccolo gioco OpenGL per la piattaforma Android e mi chiedo se c'è un modo semplice per rendere il testo sulla parte superiore del telaio reso (come un HUD con dello riproduttore punteggio, ecc). Il testo avrebbe bisogno di utilizzare un carattere personalizzato anche.

Ho visto un esempio di utilizzo di una vista come una sovrapposizione, ma non so se voglio farlo dal momento che potrei voler porta il gioco su altre piattaforme successivamente.

Tutte le idee?

È stato utile?

Soluzione

L'SDK di Android non sono dotati di un modo semplice per disegnare testo sulle viste OpenGL. lasciando con le seguenti opzioni.

  1. Mettere un TextView sopra il vostro SurfaceView. Questo è lento e male, ma l'approccio più diretto.
  2. Rendering stringhe comuni alle texture, e semplicemente disegnare quelle trame. Questo è di gran lunga il più semplice e veloce, ma meno flessibile.
  3. roll-your-own codice di rendering del testo sulla base di uno sprite. Probabilmente secondo miglior scelta se 2 non è un'opzione. Un buon modo per avere i piedi bagnati ma nota che mentre sembra semplice (e le caratteristiche di base sono), si ottiene di più duro e più impegnativo quando si aggiungono più funzioni (consistenza-allineamento, che si occupano di line-breaks, font a larghezza variabile etc. ) - se si prende questa strada, rendere il più semplice come si può ottenere via con
  4. Utilizzare una libreria di off-the-shelf / open-source. Ci sono pochi in giro se si caccia su Google, il po 'complicato sta ottenendo loro integrato e funzionante. Ma almeno, una volta fatto questo, avrete tutta la flessibilità e la maturità che forniscono.

Altri suggerimenti

rendering del testo per una texture è più semplice di quello che la Sprite Testo demo rendono sembra, l'idea di base è quella di utilizzare la classe Canvas per rendere a una bitmap e quindi passare il Bitmap per una 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();

Ho scritto un esercitazione che si espande sulla risposta pubblicato da JVitela . Fondamentalmente, si utilizza la stessa idea, ma invece di rendere ogni stringa ad una texture, rende tutti i caratteri da un file di font da una texture e lo utilizza per consentire la piena rendering del testo dinamico senza ulteriori rallentamenti (una volta completata l'inizializzazione) .

Il vantaggio principale del mio metodo, rispetto ai vari generatori atlante di carattere, è che si può spedire file di font di piccole dimensioni (TTF .otf) con il progetto, invece di dover spedire bitmap di grandi dimensioni per ogni variazione e la dimensione del carattere. Può generare caratteri perfetti di qualità a qualsiasi risoluzione usando solo un file di font:)

Il esercitazione include codice completo che può essere utilizzato in qualsiasi progetto:)

In base a questo link:

http: //code.neenbedankt .com / how-to-render-un-android-view-a-un-bitmap

È possibile eseguire il rendering qualsiasi Visualizza per una bitmap. E 'probabilmente la pena partendo dal presupposto che è possibile layout di una vista come richiedete (inclusi testi, immagini, ecc) e poi renderlo ad un bitmap.

Utilizzando di JVitela sopra si dovrebbe essere in grado di utilizzare tale bitmap come una texture OpenGL.

Date un'occhiata al CBFG e il porto Android del codice di carico / rendering. Si dovrebbe essere in grado di rilasciare il codice nel progetto e utilizzarlo immediatamente.

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

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

Ho guardato il testo di esempio sprite e sembra terribilmente complicato per un tale compito, ho considerato il rendering ad una trama troppo, ma sono preoccupato per il calo di prestazioni che potrebbero causare. Potrei andare in vista, invece, e preoccuparsi di porting quando è il momento di attraversare quel ponte:)

Guardate la "Sprite testo" campione nel GLSurfaceView campioni .

IMHO ci sono tre motivi per utilizzare OpenGL ES in un gioco:

  1. evitare differenze tra le piattaforme mobili utilizzando uno standard aperto;
  2. Per avere più il controllo del processo di rendering;
  3. Per beneficiare di elaborazione in parallelo della GPU;

Disegno di testo è sempre un problema nel game design, in quanto si sta disegnando le cose, quindi non si può avere l'aspetto di un'attività comune, con i widget e così via.

È possibile utilizzare un framework per generare caratteri bitmap da font TrueType e renderli. Tutti i quadri che ho visto funzionano allo stesso modo: generano il vertice e coordinate texture per il testo in tempo pareggio. Questo non è l'uso più efficiente delle OpenGL.

Il modo migliore è quello di allocare remote buffer (vertice oggetti buffer - VBOS). Per i vertici e texture presto nel codice, evitando le operazioni di trasferimento memoria pigri in tempo tiraggio

Tenete a mente che i giocatori non piace leggere il testo, in modo da non scrivere un testo lungo generato dinamicamente. Per le etichette, è possibile utilizzare le texture statiche, lasciando il testo dinamico per il tempo e il punteggio, ed entrambi sono numerica con pochi caratteri.

Quindi, la mia soluzione è semplice:

  1. Creare texture per le etichette e le avvertenze comuni;
  2. Crea texture per i numeri 0-9, ":", "+" e "-". Una texture per ogni personaggio;
  3. Genera VBOs a distanza per tutte le posizioni nella schermata. Posso rendere il testo statico o dinamico che le posizioni, ma i VBOs sono statici;
  4. Genera un solo Texture VBO, come il testo viene sempre reso un modo;
  5. In tempo pareggio, rendo il testo statico;
  6. Per il testo dinamico, che può sbirciare nella posizione VBO, ottenere la consistenza carattere e disegnarlo, un carattere alla volta.

Draw operazioni sono veloci, se si utilizzano i buffer remoto statici.

creo un file XML con posizioni dello schermo (sulla base di percentuali diagonale dello schermo) e le texture (statiche e caratteri), e poi mi carico questo XML prima del rendering.

Per ottenere un alto tasso di FPS, si dovrebbe evitare di generare VBOs in fase di sorteggio.

Se ti ostini a usare GL, si potrebbe rendere il testo a texture. Supponendo che la maggior parte del HUD è relativamente statico, non si dovrebbe avere per caricare le texture di memoria texture troppo spesso.

Date un'occhiata al CBFG e il porto Android del carico / resa codice. Si dovrebbe essere in grado di rilasciare il codice nel progetto e usarlo subito.

  1. CBFG

  2. caricatore Android

ho problemi con questa implementazione. Esso mostra un solo carattere, quando provo fare il formato bitmap cambiamento del tipo di carattere (Ho bisogno di lettere speciali) tutto il pareggio fallisce: (

Ho cercato per questo per un paio d'ore, questo è stato il primo articolo ho mai incontrato e anche se ha la migliore risposta, le risposte più popolari Penso che sono fuori luogo. Certamente per quello che mi serviva. Le risposte di shakazed Weichsel di ed erano proprio sul pulsante, ma un po 'oscurata negli articoli. A voi messo proprio al progetto. Qui: Basta creare un nuovo progetto Android sulla base del campione esistente. Scegli ApiDemos:

guardare sotto la cartella di origine

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

E troverete tutto il necessario.

testo statico :

  • Generare un'immagine con tutte le parole usate sul vostro PC (per esempio con GIMP).
  • Caricarvi come una trama e usarlo come materiale per un aereo.

testo lungo che deve essere aggiornato di tanto in tanto:

  • Lasciate pareggio Android su una tela bitmap (soluzione di JVitela).
  • Caricare questo come materiale per un aereo.
  • coordina Usa consistenza diversa per ogni parola.

un numero (formattato 00.0):

  • Generare un'immagine con tutti i numeri e un punto.
  • Caricare questo come materiale per un aereo.
  • Usa sotto shader.
  • Nel vostro evento OnDraw aggiornare solo la variabile valore inviato allo 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;
    
    }
    

Sopra codice funziona per un atlante struttura dove i numeri partono da 0 al 7 ° colonna della seconda fila dell'atlante dei font (texture).

Fare riferimento a https://www.shadertoy.com/view/Xl23Dw per la dimostrazione ( con trama sbagliato però)

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top