2010-10-18 13 views
5

Sto scrivendo una piccola app che al momento genera una mappa casuale di trame.Android OpenGL - ES Texture bleeding

Sto disegnando questa mappa come un gruppo di 10 x 15 "quad" che sono infatti tutte le strisce triangolari. Io uso la "mappa" per afferrare un int che poi prendo come la posizione della trama per questo quadrato nella textureAtlas. quindi per esempio 0 è la "tessera" in basso a sinistra. L'atlante è 128 x 128 e diviso in 32 tessere pixel.

Tuttavia, mi sembra di avere degli strani artefatti in cui la trama della tessera si sta insinuando nella tessera successiva. Mi chiedevo se fosse l'immagine stessa, ma per quanto posso dire i pixel sono esattamente dove dovrebbero essere. Ho quindi esaminato le texture coords che stavo specificando ma sembrano tutte esatte (0.0, 0.25, 0.5, 0.75, 1.0 - suddividendola nelle 4 righe e colonne che mi aspetterei).

La cosa strana è che se l'eseguo sull'emulatore non ottengo alcun artefatto.

C'è un'impostazione che mi manca e che causerebbe un sanguinamento di 1 pixel? Sembrava essere solo verticale - questo potrebbe essere collegato al telefono "sto stirando" l'immagine in quella direzione come lo schermo del telefono è più grande del normale in quella direzione.

ho caricare la trama in questo modo:

//Get a new ID 
    int id = newTextureID(gl); 

    //We will need to flip the texture vertically 
    Matrix flip = new Matrix(); 
    flip.postScale(1f, -1f); 

    //Load up and flip the texture 
    Bitmap temp = BitmapFactory.decodeResource(context.getResources(), resource); 

    //Store the widths for the texturemap 
    int width = temp.getWidth(); 
    int height = temp.getHeight(); 
    Bitmap bmp = Bitmap.createBitmap(temp, 0, 0, width, height, flip, true); 
    temp.recycle(); 

    //Bind 
    gl.glBindTexture(GL10.GL_TEXTURE_2D, id); 

    //Set params 
    gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, gl.GL_LINEAR); 
    gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, gl.GL_LINEAR); 

    //Push onto the GPU 
    GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bmp, 0); 

    TextureAtlas atlas = new TextureAtlas(id, width, height, tileSize); 
    return atlas; 

Ho poi renderlo in questo modo:

gl.glBindTexture(GL10.GL_TEXTURE_2D, currentAtlas.textureID); 
    //Enable the vertices buffer for writing and to be used during our rendering 
    gl.glEnableClientState(GL10.GL_VERTEX_ARRAY); 
    //Specify the location and data format of an array of vertex coordinates to use 
    gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer); 

    //Enable the texture buffer 
    gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY); 
    gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, textureBuffer); 
    gl.glDrawElements(GL10.GL_TRIANGLES, indices.length, GL10.GL_UNSIGNED_SHORT, indexBuffer); 

vorrei fare una foto, ma non sono sicuro come ottenere un tappo schermo dal telefono ...

Se qualcuno sa di come posso acquisire il fotogramma corrente e magari lo metto in un file, lo farò se aiuta a spiegare cosa sta succedendo!

Attendo con ansia la vostra risposta.

Modifica: Ecco uno screencap - nota eseguo l'app in orizzontale ma cap è in verticale. Scusate anche le trame orribili: D erano semplicemente un segnaposto/pasticciavano.

ScreenCap

+0

Mentre non posso aiutarti con il problema, puoi usare il programma 'ddms' nella directory tools dell'SDK per fare uno screenshot del dispositivo (ctrl-s). – richq

+0

Grazie! Sapevo che doveva esserci un modo in cui le persone lo facevano. Sembra anche uno strumento generalmente utile. – iexus

risposta

11

Ebbene, dopo aver parlato con un amico sono riuscito a risolvere questo piccolo problema.

Si scopre che se si desidera avere trame perfette pixel esatte è necessario specificare il bordo della trama per essere a metà strada nel pixel.

Per fare ciò, ho semplicemente aggiunto mezzo pixel o sottratto mezzo pixel alla misurazione per le texture coords.

Come così:

//Top Left 
      textureCoords[textPlace] = xAdjust*currentAtlas.texSpaceWidth + currentAtlas.halfPixelAdjust;  textPlace++; 
      textureCoords[textPlace] = (yAdjust+1)*currentAtlas.texSpaceHeight - currentAtlas.halfPixelAdjust; textPlace++; 

Questo è stato semplicemente calcolato quando si carica l'atlante di texture:

(float)(0.5 * ((1.0f/numberOfTilesInAtlasRow)/pixelsPerTile)); 

Anche se l'altezza era diverso per la larghezza di ogni piastrella (che potrebbe accadere) si farebbe bisogno di calcolarli individualmente

Questo ha risolto tutti gli artefatti così posso continuare. Spero che aiuti qualcun altro!

+0

ciao. puoi spiegarlo in maggiori dettagli? Non capisco come applicare queste formule al mio atlas.vAs i c per atlanti non piastrellati xAdjust è x shift a sprite in atlas. Ma perché dovrei moltiplicarlo per l'atlante. Sono in pixel? Grazie. –

+0

Questo per me ha funzionato alla perfezione, anche se ho avuto ancora problemi con le linee durante il rendering in remoto e l'utilizzo di mipmapping. –