[OpenGL] artefact en bordure sur images agrandies

Le côté programmation du développement d'un jeu vidéo.

artefact en bordure sur images agrandies

Messagepar aselius » 10 Nov 2010, 16:00

Bonjour,

Pour l'instant je débute alors j'utilise OpenGL dans un contexte 2D.

Je charge une image avec transparence et je l'affiche. Mais lorsque je fait un zoom (glScalef) pour agrandir cette image, il y a des artefacts sur les bords de l'image (entouré en jaune) :

Image

J'utilise cette fonction pour activer les textures transparentes :
Code: Tout sélectionner
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_BLEND);



Quelqu'un aurait-il une solution ou une piste à me proposer, parce que j'ai eu beau fouillé un peu partout je ne vois vraiment pas comment résoudre ce problème.

A noter que je charge les images depuis des méta-textures, et je les découpe avec glTexCoord2d. Ce qui est fait avec un calcul de ratio entre la taille de la texture et de la méta-texture. J'obtiens donc un nombre décimal avec généralement beaucoup de chiffre après la virgule et que la précision de découpe n'est peut-être pas parfaite !

Merci.
aselius
Hello World, I'm new !
 
Messages: 11
Inscription: 10 Nov 2010, 15:55

Messagepar iliak » 10 Nov 2010, 16:40

Je pense que c'est un problème de "quoi faire une fois que tu arrives en bord de texture". Regarde du côté de glTexParameter() avec comme paramètre :

GL_TEXTURE_WRAP_S
Sets the wrap parameter for texture coordinate $s$ to either GL_CLAMP, GL_CLAMP_TO_EDGE, or GL_REPEAT. GL_CLAMP causes $s$ coordinates to be clamped to the range [0,1] and is useful for preventing wrapping artifacts when mapping a single image onto an object. GL_CLAMP_TO_EDGE causes $s$ coordinates to be clamped to the range $left [ {1 over 2N}, 1 - {1 over 2N} right ]$, where $N$ is the size of the texture in the direction of clamping. GL_REPEAT causes the integer part of the $s$ coordinate to be ignored; the GL uses only the fractional part, thereby creating a repeating pattern. Border texture elements are accessed only if wrapping is set to GL_CLAMP. Initially, GL_TEXTURE_WRAP_S is set to GL_REPEAT.
GL_TEXTURE_WRAP_T
Sets the wrap parameter for texture coordinate $t$ to either GL_CLAMP, GL_CLAMP_TO_EDGE, or GL_REPEAT. See the discussion under GL_TEXTURE_WRAP_S. Initially, GL_TEXTURE_WRAP_T is set to GL_REPEAT.

Autre piste, regarde du côté de GL_NEAREST comme fliter de texture.

Autre point, au lieu de t'em#!@# à calculer les coordonnées en float pour chaque coin de ta texture, multiplie la matrice de ta texture pour qu'un pixel de glTexCoord() corresponde à 1 pixel dans ta texture. Regarde ici : http://code.google.com/p/arcadeengine/source/browse/trunk/Framework/Graphic/SpriteBatch.cs#307 :

Code: Tout sélectionner
Matrix4 textureMatrix = Matrix4.Scale(1.0f / texture.Size.Width, 1.0f / texture.Size.Height, 1.0f);
- Iliak -
[http://www.mimicprod.net ArcEngine : a free 2D .Net gaming framework]
[http://www.dungeoneye.net Dungeon Eye : Remake open source de Eye of the beholder II]
iliak
Hello World, I'm new !
 
Messages: 141
Inscription: 25 Fév 2010, 14:53

Messagepar aselius » 10 Nov 2010, 16:46

Ah, merci pour toutes ces infos !
Je vais regarder ça. C'est pas évident quand on débute, merci encore à toi.
aselius
Hello World, I'm new !
 
Messages: 11
Inscription: 10 Nov 2010, 15:55

Messagepar iliak » 10 Nov 2010, 16:58

Je ne sais pas quelle version d'OpenGL tu vises, mais tu peux jeter un œil à mon framework => http://www.mimicprod.net

Si plus précisément, tu fais de l'affichage de sprite, regarde du côté de ma classe SpriteBatch, tu vas trouver des infos.
- Iliak -
[http://www.mimicprod.net ArcEngine : a free 2D .Net gaming framework]
[http://www.dungeoneye.net Dungeon Eye : Remake open source de Eye of the beholder II]
iliak
Hello World, I'm new !
 
Messages: 141
Inscription: 25 Fév 2010, 14:53

Messagepar aselius » 10 Nov 2010, 17:56

Merci, mais si je ne m'abuse c'est du C, moi je passe par LWJGL un binding pour Java.
aselius
Hello World, I'm new !
 
Messages: 11
Inscription: 10 Nov 2010, 15:55

Messagepar aselius » 10 Nov 2010, 18:39

Le problème vient des méta-texture, avec les mêmes images sans méta texture, il n'y a pas ces artefacts.

J'ai un peu l'impression que le calcul du ratio entre la taille de méta texture et de l'image pour mapper la texture pose problème. Suivant le zoom, il y a un pixel de bordure qui se balade ou pas.
Si je fait en sorte que les images des méta texture ne se "touche" pas, mais soient séparées par un 1 pixel transparent, les artefacts n'apparaissent pas.

Aurais-tu une solution, car imposer un pixel vide de bordure aux infographistes c'est pas super !
aselius
Hello World, I'm new !
 
Messages: 11
Inscription: 10 Nov 2010, 15:55

Messagepar Atréides » 11 Nov 2010, 09:38

Ajouter dynamiquement une bordure aux images au chargement serait mieux que de devoir taper sur les graphistes. Par contre, comme dirait probablement Mokona, ça contourne le problème, ça ne le résout pas.
Souvent présent sur #gcn, irc.langochat.net
Site web : seuret . com (programmation, biostatistiques, CP Explo 2/1)
Avatar de l’utilisateur
Atréides
 
Messages: 1349
Inscription: 13 Mar 2005, 13:12
Localisation: Suisse

Messagepar iliak » 11 Nov 2010, 09:58

Je rencontre le même problème que toi, à savoir que de temps à autre j'ai des morceaux d'image qui apparaissent. Ce problème est reproductible, donc c'est rassurant d'un côté.

Je pense savoir ce que c'est mais je ne m'y suis pas encore penché dessus. Du peu que j'avais vu c'est que OpenGL (comme Direct3D) prend comme repère le milieu du pixel et nous on considère le bord du pixel (ou l'inverse). Ce qui fait que quand OpenGL est entre deux pixels, il bascule vers le pixel suivant. En gros c'est ça.

Bref c'est un problème connu et relativement simple à résoudre.
- Iliak -
[http://www.mimicprod.net ArcEngine : a free 2D .Net gaming framework]
[http://www.dungeoneye.net Dungeon Eye : Remake open source de Eye of the beholder II]
iliak
Hello World, I'm new !
 
Messages: 141
Inscription: 25 Fév 2010, 14:53

Messagepar aselius » 11 Nov 2010, 14:12

Bonjour,

c'est un problème connu et relativement simple à résoudre.


Aurais-tu un lien (même en anglais) qui explique cette notion, j'ai rien trouvé sur ça !
aselius
Hello World, I'm new !
 
Messages: 11
Inscription: 10 Nov 2010, 15:55

Messagepar iliak » 11 Nov 2010, 14:51

Justement je n'en retrouve plus, sinon je l'aurais mis...
- Iliak -
[http://www.mimicprod.net ArcEngine : a free 2D .Net gaming framework]
[http://www.dungeoneye.net Dungeon Eye : Remake open source de Eye of the beholder II]
iliak
Hello World, I'm new !
 
Messages: 141
Inscription: 25 Fév 2010, 14:53

Messagepar aselius » 11 Nov 2010, 15:06

OK, merci pour ton aide précieuse.

Si je trouve quelque chose, je posterais le lien.

@+
aselius
Hello World, I'm new !
 
Messages: 11
Inscription: 10 Nov 2010, 15:55

Messagepar Kremtak » 11 Nov 2010, 15:42

Salut,

J'ai eu 2 fois ce problème... deux fois résolu avec une solution différente

La 1ere, c'était plutôt simple : les paramètres de texture. Lesquels utilises-tu?
Si tu mets ça :
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT);
Ca permet d'utiliser l'avant dernier pixel comme pixel "suivant" la bordure, et je suppose que dans la tambouille interne de GL il interpole les valeurs de ces deux pixels pour déterminer le pixel de bordure.

L'autre fois où j'avais eu ce problème je m'arrachais les cheveux car impossible à résoudre du côté d'opengl... avant de comprendre que le problème venait de la texture elle-même. Pour une raison que j'ignore photoshop m'avait mis une valeur alpha différente sur les bords de la texture, ce qui causait le même genre d'artefacts à l'affichage.
But there's no sense crying over every mistake
You just keep trying until you run out of cake
Avatar de l’utilisateur
Kremtak
Hello World, I'm new !
 
Messages: 167
Inscription: 12 Déc 2007, 23:27
Localisation: Aubagne

Messagepar aselius » 11 Nov 2010, 16:12

Salut Kremtak,

Merci de t'intéresser au problème.
Malheureusement, l'utilisation de glTexParameteri ne donne rien. Et l'image est parfaite du côté du canal alpha.

J'utilise un glScale pour pouvoir faire un zoom global du rendu. Il n'y a aucun artefact lorsque je fait une mise à l'échelle du sprite seul, les artefacts apparaissent seulement lors de l'utilisation du zoom global, et seulement avec des méta-textures.
aselius
Hello World, I'm new !
 
Messages: 11
Inscription: 10 Nov 2010, 15:55

Messagepar Kremtak » 12 Nov 2010, 17:05

Tu as trouvé le problème?
Envoie le code où tu charges les textures, à tout hasard, peut-être que quelqu'un remarquera un problème...
But there's no sense crying over every mistake
You just keep trying until you run out of cake
Avatar de l’utilisateur
Kremtak
Hello World, I'm new !
 
Messages: 167
Inscription: 12 Déc 2007, 23:27
Localisation: Aubagne

Messagepar aselius » 12 Nov 2010, 17:39

Non, je n'ai pas trouvé :(

Voici le code de génération des textures et polygones (c'est du java) :

Code: Tout sélectionner
// paramètre ---> BufferedImage bufferedImage
//         l'image du sprite

int srcPixelFormat = 0;
int textureID = glGenTextures();          
glBindTexture(GL_TEXTURE_2D, textureID);

if (bufferedImage.getColorModel().hasAlpha()) {
    srcPixelFormat = GL_RGBA;
} else {
    srcPixelFormat = GL_RGB;
}

ByteBuffer textureBuffer = null;
WritableRaster raster;
BufferedImage texImage;

int textureWidth = GlTools.getTextureSize2Pow(bufferedImage.getWidth());
int textureHeight = GlTools.getTextureSize2Pow(bufferedImage.getHeight());

if (bufferedImage.getColorModel().hasAlpha()) {
    raster = Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE, textureWidth, textureHeight, 4, null);
    texImage = new BufferedImage(glAlphaColorModel, raster, false, null);
} else {
    raster = Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE, textureWidth, textureHeight, 3, null);
    texImage = new BufferedImage(glColorModel, raster, false, null);
}

Graphics g = texImage.getGraphics();
g.setColor(new Color(0f, 0f, 0f, 0f));
g.fillRect(0, 0, textureWidth, textureHeight);
g.drawImage(bufferedImage, 0, 0, null);

byte[] data = ((DataBufferByte) texImage.getRaster().getDataBuffer()).getData();

textureBuffer = ByteBuffer.allocateDirect(data.length);
textureBuffer.order(ByteOrder.nativeOrder());
textureBuffer.put(data, 0, data.length);
textureBuffer.flip();

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);

glTexImage2D(GL_TEXTURE_2D,
              0,
              GL_RGBA,
              textureWidth,
              textureHeight,
              0,
              srcPixelFormat,
              GL_UNSIGNED_BYTE,
              textureBuffer);


// paramètre ---> Rectangle[] rectangle
//         les différentes zones/images de la méta-texture à découper

int base = glGenLists(rectangle.length);
int[] widths = new int[rectangle.length];
int[] heights = new int[rectangle.length];
for (int i = 0 ; i < rectangle.length ; i++) {
   widths[i] = rectangle[i].width;
   heights[i] = rectangle[i].height;
   glNewList(base + i, GL_COMPILE);
          glBegin(GL_QUADS);                
             double x = (double) rectangle[i].x / textureWidth;
             double x2 = x + ((double) rectangle[i].width / textureWidth);
             double y = (double) rectangle[i].y / textureHeight;
             double y2 = y + ((double) rectangle[i].height / textureHeight);
             glTexCoord2d(x, y);
             glVertex2d(0, 0);
             glTexCoord2d(x, y2);
             glVertex2d(0, rectangle[i].height);
             glTexCoord2d(x2, y2);
             glVertex2d(rectangle[i].width, rectangle[i].height);
             glTexCoord2d(x2, y);
             glVertex2d(rectangle[i].width, 0);                
      glEnd();
    glEndList();
}


Merci pour votre aide.
aselius
Hello World, I'm new !
 
Messages: 11
Inscription: 10 Nov 2010, 15:55

Messagepar iliak » 16 Nov 2010, 16:48

- Iliak -
[http://www.mimicprod.net ArcEngine : a free 2D .Net gaming framework]
[http://www.dungeoneye.net Dungeon Eye : Remake open source de Eye of the beholder II]
iliak
Hello World, I'm new !
 
Messages: 141
Inscription: 25 Fév 2010, 14:53

Messagepar aselius » 22 Nov 2010, 17:20

Bonjour,

Merci pour le lien :) mais cela ne m'a pas permis de régler le problème.
aselius
Hello World, I'm new !
 
Messages: 11
Inscription: 10 Nov 2010, 15:55


Retourner vers Programmation

Qui est en ligne

Utilisateurs parcourant ce forum: Google [Bot] et 8 invités

cron