PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : OpenGL... bestimmte farbe transparent machen?


Pompos
2005-04-26, 16:16:02
Hey
Wie geht es recht einfach eine bestimmte Farbe in OpenGL transparent zu machen. Also so, dass wenn ne Textur an einer Stelle z.B. Weiß ist, dass dann die Texturen dahinter zu erblicken sind.

MeLLe
2005-04-26, 17:00:56
Nimm deine Textur, und bastel entweder in einem Pixelgrafik-Tool (Photoshop etc) einen Alphakanal dazu, mit Alpha = 0 an den Stellen, wo R=G=B=255. Oder aber bastel dir beim Laden der Textur einen Alphakanal dazu, indem du die 3 Byte/Texel-Textur durchackerst und da wo R=G=B=255 den entsprechenden Alphawert auf 0 setzt, sonst auf 1, und die Farben ansonsten in die neue 4-Bytige Textur übernimmst. Wenn du diesen Weg gehen willst kann ich dir morgen meinen Code dafür posten ...

Pompos
2005-04-26, 18:35:44
Das wäre natürlich super :D

Wie viel Aufwand wäre den die Methode wo man den Alphakanal den Grafiken hinzufügt (nur den zu codenden Teil meine ich)?

MeLLe
2005-04-27, 09:04:09
Das wäre natürlich super :D

Wie viel Aufwand wäre den die Methode wo man den Alphakanal den Grafiken hinzufügt (nur den zu codenden Teil meine ich)?
Code kommt gleich, aber erstmal zu deiner Frage:
Wieviel Zeit es braucht, um die Texturen mit nem Alphakanal via Pixelbearbeitung zu versehen, weisss ich nicht genau. Es kommt halt auch drauf an, wieviel Artwork du hast und wieviel davon gealphachannelt werden müsste. Da können dir die Grafiker sicher mehr sagen, ich bin nur Code-Tipse ;)

MeLLe
2005-04-27, 09:28:31
So, nun zum Code:

Beim Initialisieren der GL-States
glAlphaFunc(GL_GREATER, 0);
glEnable(GL_ALPHA_TEST);hinzufügen. Das bewirkt, dass der Alphatest aktiviert wird,
und nur Pixel mit Alpha > 0 gezeichnet werden.

Zum Laden der Texturen nutze ich diesen Code (sinngemäß):
FILE* hfile = NULL;
tImage *pImage = NULL;
UINT textureData[1];

pImage = LoadBMP("texture001.bmp");

if (hfile)
fclose(hfile);

if (pImage != NULL)
{
glGenTextures(1, &textureData[0]);
glPixelStorei (GL_UNPACK_ALIGNMENT, 1);
glBindTexture(GL_TEXTURE_2D, textureData[0]);

tImage* nImage = new tImage();
nImage->data = (unsigned char*)malloc(4*sizeof(unsigned char) * pImage->sizeX * pImage->sizeY);
nImage->channels = 4;
nImage->sizeX = pImage->sizeX;
nImage->sizeY = pImage->sizeY;

for (int x=0; x<pImage->sizeX; x++)
{
for (int y=0; y<pImage->sizeY; y++)
{
if ( (pImage->data[(x * pImage->sizeX + y) * pImage->channels] == 255) &&
(pImage->data[(x * pImage->sizeX + y) * pImage->channels + 1] == 255) &&
(pImage->data[(x * pImage->sizeX + y) * pImage->channels + 2] == 255))
{
nImage->data[(x * nImage->sizeX + y) * nImage->channels] = 0;
nImage->data[(x * nImage->sizeX + y) * nImage->channels + 1] = 0;
nImage->data[(x * nImage->sizeX + y) * nImage->channels + 2] = 0;
nImage->data[(x * nImage->sizeX + y) * nImage->channels + 3] = 0;
}
else
{
nImage->data[(x * nImage->sizeX + y) * nImage->channels] = pImage->data[(x * pImage->sizeX + y) * pImage->channels];
nImage->data[(x * nImage->sizeX + y) * nImage->channels + 1] = pImage->data[(x * pImage->sizeX + y) * pImage->channels + 1];
nImage->data[(x * nImage->sizeX + y) * nImage->channels + 2] = pImage->data[(x * pImage->sizeX + y) * pImage->channels + 2];
nImage->data[(x * nImage->sizeX + y) * nImage->channels + 3] = 255;
}
}
}

gluBuild2DMipmaps(GL_TEXTURE_2D, nImage->channels, nImage->sizeX, nImage->sizeY, GL_RGBA, GL_UNSIGNED_BYTE, nImage->data);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

if (nImage)
{
if (nImage->data) {
free(nImage->data); }
free(nImage); }

if (pImage)
{
if (pImage->data) {
free(pImage->data); }
free(pImage); }
printf("ok.\n");
}
else
{
printf("failed.\n");
}Hier wird erst die Textur in ein tImage geladen (3 Kanäle), dann ein neues temporäres tImage mit 4 Kanälen erzeugt und Pixel für Pixel geschaut, wo die Ursprungstextur R=G=B=255 (also weiss) ist, und entsprechend da im Temp-tImage Alpha auf 0 gesetzt, sonst auf 255. Am Ende wird dieses 4-Kanal-tImage zu einer OpenGL-Textur verwurstet.

Rendern funktioniert wie gehabt mit
glBindTexture(GL_TEXTURE_2D, textureData[0]);
glBegin(...)
...
glEnd();
Zum Laden der Texturdaten benötigst du nach dieser Lösung noch eine externe Lib, namentlich aus dem BSP-Loader-Tutorial von www.GameTutorials.com (http://www.gametutorials.com/gtstore/pc-84-1-quake3-bsp-loader.aspx) die Files "image.cpp" und "image.h" sowie die JPEGLib von www.ijg.org (http://www.ijg.org/files/) (bin mir nicht sicher ob die mit in dem GT-Tutorial gleich beiliegen).

Ich hoffe es ist halbwegs verständlich - bei Fragen einfach melden ;)

Corrail
2005-04-27, 12:35:24
Hey
Wie geht es recht einfach eine bestimmte Farbe in OpenGL transparent zu machen. Also so, dass wenn ne Textur an einer Stelle z.B. Weiß ist, dass dann die Texturen dahinter zu erblicken sind.

Wenn du Shader verwendest kannst du auch dort mit einer if-Abfrage den Alpha Wert setzen.

Pompos
2005-04-27, 12:45:05
Code kommt gleich, aber erstmal zu deiner Frage:
Wieviel Zeit es braucht, um die Texturen mit nem Alphakanal via Pixelbearbeitung zu versehen, weisss ich nicht genau. Es kommt halt auch drauf an, wieviel Artwork du hast und wieviel davon gealphachannelt werden müsste. Da können dir die Grafiker sicher mehr sagen, ich bin nur Code-Tipse ;)
Das war ja genau die Frage... wieviel Arbeit würde es machen, dass zu coden. Also dass mit den Alphachannel in den Texturen selbst. Wieviel Arbeit das beim Artwork macht ist egal ;)

Danke für den Code. Muss mal gucken ob sich Python gnädig zeigt und es mir gestattet solch Sachen zu machen :redface:

del_4901
2005-04-27, 16:37:23
Wenn du Shader verwendest kannst du auch dort mit einer if-Abfrage den Alpha Wert setzen.
um dann zur eigendlichen Laufzeit der Anwendung jedesmal Performance zu "verschwenden".

Die Lösung mit dem Alphakanal ist schon nicht schlecht, vorallem weil das gemacht wird bevor die Engine in ihre Hauptschleife eintritt.