2010-10-18 11 views
5

J'écris une petite application qui génère actuellement une carte aléatoire de textures.Android OpenGL - ES Texture saignée

Je dessine cette carte comme un groupe de "quadruples" de 10 x 15 qui sont en fait toutes les bandes de triangle. J'utilise la "carte" pour saisir un int que je prends alors comme l'emplacement de la texture pour ce carré dans le textureAtlas. Par exemple, 0 est la "tuile" en bas à gauche. L'atlas est 128 x 128 et divisé en carreaux de 32 pixels.

Cependant, il semble que je reçois des artefacts étranges où la texture de la tuile est insérée dans la tuile suivante. Je me demandais si c'était l'image elle-même mais pour autant que je puisse dire que les pixels sont exactement là où ils devraient être. J'ai ensuite regardé les coordonnées de texture que je spécifiais mais elles ont toutes l'air exactes (0.0, 0.25, 0.5, 0.75, 1.0 - en les divisant en 4 lignes et en colonnes).

La chose étrange est que si je l'exécute sur l'émulateur, je ne reçois aucun artefact.

Y a-t-il un paramètre qui me manque et qui provoquerait un saignement de 1 pixel? Il semblait être seulement vertical aussi - cela pourrait être lié au téléphone, je suis "étirer" l'image dans cette direction que l'écran du téléphone est plus grand que la normale dans cette direction.

que je charge la texture comme ceci:

//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; 

Je rends alors comme si:

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); 

je prendrais une photo, mais je ne suis pas sûr comment obtenir un bouchon d'écran de la téléphone ...

Si quelqu'un sait comment je peux capturer le cadre actuel et peut-être le mettre dans un fichier, je le ferai si cela aide à expliquer ce qui se passe!

Réjouissez-vous de votre réponse. Edit: Voici un screencap - note que je cours l'application en paysage mais le chapeau est en portrait. Excusez également les horribles textures: D ils étaient simplement un endroit/déconner.

ScreenCap

+0

Bien que je ne puisse pas vous aider avec le problème, vous pouvez utiliser le programme 'ddms' dans le répertoire tools du SDK pour prendre une capture d'écran du périphérique (ctrl-s). – richq

+0

Merci! Je savais qu'il devait y avoir une manière par laquelle les gens le faisaient. Ressemble à un outil généralement utile aussi. – iexus

Répondre

11

Eh bien, après avoir parlé à un ami, je réussi à résoudre ce petit problème.

Il s'avère que si vous souhaitez avoir des textures parfaites au pixel près, vous devez spécifier que le bord de la texture doit être à mi-chemin dans le pixel.

Pour ce faire, j'ai simplement ajouté un demi-pixel ou soustrait un demi-pixel à la mesure pour les coords de texture.

Comme si:

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

Cela a été calculé simplement lors du chargement de l'atlas de texture:

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

Bien que si la hauteur est différente de la largeur de chaque tuile (qui pourrait se produire), vous besoin de les calculer individuellement.

Cela a résolu tous les artefacts afin que je puisse continuer. J'espère que ça aide quelqu'un d'autre!

+0

salut. Pouvez-vous expliquer en plus de détails? Je ne comprends pas comment appliquer ces formules à mon atlas.vAs i c pour atlas non carrelé xAdjust il est x shift to sprite dans l'atlas. Mais pourquoi je devrais le multiplier pour atlas witdh. Sont-ils en pixels? Merci. –

+0

Cela a fonctionné très bien pour moi, même si j'ai toujours eu quelques problèmes avec les lignes lors du rendu au loin et en utilisant le mipmapping. –

Questions connexes