2010-12-05 5 views
5

Ich habe Partikel, die ich in der Lage sein, die Farbe von Code zu ändern, so dass jede Farbe verwendet werden kann. So habe ich nur eine Textur, die grundsätzlich Leuchtdichte hat.OpenGL ES 1.1: Wie ändert man die Texturfarbe, ohne die Leuchtkraft zu verlieren?

Ich habe glColor4f(1f, 0f, 0f, 1f); verwendet, um die Farbe anzuwenden.

Jedes blendfunc, das ich ausprobiert habe, kommt fast wie das letzte Bild unten. Ich möchte immer noch die Leuchtkraft erhalten, wie im mittleren Bild. (Dies ist wie die Overlay oder Soft Light Filter in Photoshop, wenn die Farbschicht oben auf der Textur-Ebene war.)

Haben Sie Ideen, wie Sie dies ohne programmierbare Shader tun können? Da es sich um Partikel handelt, möchte ich auch keine schwarze Box dahinter haben. Ich möchte, dass sie in die Szene eingefügt wird.

alt text

+0

Ich glaube es nicht mit festen Pipeline möglich ist, werden Sie ein Fragment Shaders müssen, es zu erreichen. – ognian

Antwort

9

Hier ist eine Lösung, die nahe sein könnte, was Sie suchen:

glColor4f(1.0f, 0.0f, 0.0f, 1.0f); 

glActiveTexture(GL_TEXTURE0); 
glEnable(GL_TEXTURE_2D); 
glBindTexture(GL_TEXTURE_2D, spriteTexture); 
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); 

glActiveTexture(GL_TEXTURE1); 
glEnable(GL_TEXTURE_2D); 
glBindTexture(GL_TEXTURE_2D, spriteTexture);  
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_ADD); 

Was es tut, ist die ursprüngliche Textur, die durch die angegebene Farbe multiplizieren und fügt dann die Pixel-Werte die ursprünglichen Textur auf:

final_color.rgba = original_color.rgba * color.rgba + original_color.rgba; 

Dies in einem helleren Bild führt als das, was Sie gefragt haben, aber vielleicht mit etwas t gut genug sein, verweichend.

Wenn Sie den Alpha-Wert der Textur beibehalten möchten, müssen Sie GL_COMBINE anstelle von GL_ADD verwenden (+ GL_COMBINE_RGB und GL_COMBINE_ALPHA richtig einstellen).

Hier sind einige Ergebnisse mit dieser Technik auf Ihrer Textur. alt text

+0

BTW, vergessen Sie nicht, Texturkoordinatenzeiger für Textureinheit 1 zu setzen: glClientActiveTexture (GL_TEXTURE1); glEnableClientState (GL_TEXTURE_COORD_ARRAY); glTexCoordPointer (2, GL_SHORT, 0, SpriteTexcoords); – Ozirus

+0

Danke! Das sieht gut aus. Leider habe ich beim Ausprobieren auf Android festgestellt, dass Android 1.1 nur teilweise unterstützt und Multi-Texturing out ist. Aber es sieht so aus, als ob dies der einzige Weg wäre, es zu tun. – Tenfour04

2

NONSENSE! Sie müssen kein Multi-Texturing verwenden. Nur multiplizieren Sie Ihr Alpha.

Wenn Sie nach dem Laden Alpha in das Bild eingeben und bevor Sie die GL-Textur dafür erstellen, benötigen Sie nur eine Textureinheit für den Textur-Umgebungsmodus GL_ADD.

Wenn Sie auf iOS sind, dann kann Apple libs für Sie premultiply. Sehen Sie das Beispiel Texture2D-Klasse und suchen Sie nach dem kCGImageAlphaPremultipliedLast-Flag.

Wenn Sie keinen Image Loader verwenden, der Premultiply unterstützt, müssen Sie dies nach dem Laden des Images manuell tun. Pseudo-Code:

uint8* LoadRGBAImage(const char* pImageFileName) { 
    Image* pImage = LoadImageData(pImageFileName); 
    if (pImage->eFormat != FORMAT_RGBA) 
     return NULL; 

    // allocate a buffer to store the pre-multiply result 
    // NOTE that in a real scenario you'll want to pad pDstData to a power-of-2 
    uint8* pDstData = (uint8*)malloc(pImage->rows * pImage->cols * 4); 
    uint8* pSrcData = pImage->pBitmapBytes; 
    uint32 bytesPerRow = pImage->cols * 4; 

    for (uint32 y = 0; y < pImage->rows; ++y) { 
     byte* pSrc = pSrcData + y * bytesPerRow; 
     byte* pDst = pDstData + y * bytesPerRow; 
     for (uint32 x = 0; x < pImage->cols; ++x) { 
      // modulate src rgb channels with alpha channel 
      // store result in dst rgb channels 
      uint8 srcAlpha = pSrc[3]; 
      *pDst++ = Modulate(*pSrc++, srcAlpha); 
      *pDst++ = Modulate(*pSrc++, srcAlpha); 
      *pDst++ = Modulate(*pSrc++, srcAlpha); 
      // copy src alpha channel directly to dst alpha channel 
      *pDst++ = *pSrc++; 
     } 
    } 

    // don't forget to free() the pointer! 
    return pDstData; 
} 

uint8 Modulate(uint8 u, uint8 uControl) { 
    // fixed-point multiply the value u with uControl and return the result 
    return ((uint16)u * ((uint16)uControl + 1)) >> 8; 
} 

Ich persönlich bin mit libpng und premultiplying manuell.

Wie auch immer, nach dem Premultiply binden Sie einfach die Byte-Daten als RGBA OpenGL-Textur. GlTexEnvi verwenden (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_ADD); mit einer einzigen Textureinheit sollte alles sein, was Sie danach brauchen. Sie sollten genau (oder verdammt nah) bekommen, was Sie wollen. Möglicherweise müssen Sie glBlendFunc (GL_SRC_ALPHA, GL_ONE) verwenden; auch wenn du das Ding wirklich blank aussehen lassen willst.

Dies unterscheidet sich subtil von der Ozirus-Methode. Er reduziert niemals die RGB-Werte der Textur durch das Vormultiplizieren, so dass die RGB-Kanäle zu viel hinzugefügt werden und irgendwie ausgewaschen/übermäßig hell aussehen.

Ich nehme an, dass die Premultiply-Methode eher Overlay ähnelt, während die Ozirus-Methode Soft Light ist.

Weitere finden Sie unter:

http://en.wikipedia.org/wiki/Alpha_compositing

Suche nach "premultiplied alpha"

Verwandte Themen