Ich arbeite an einem Megaman- ähnlichen Spiel, bei dem ich zur Laufzeit die Farbe bestimmter Pixel ändern muss. Als Referenz : Wenn Sie in Megaman Ihre ausgewählte Waffe ändern, ändert sich die Palette des Hauptcharakters entsprechend der ausgewählten Waffe. Nicht alle Farben des Sprites ändern sich, nur bestimmte .
Diese Art von Effekt war weit verbreitet und auf dem NES recht einfach zu erzielen, da der Programmierer Zugriff auf die Palette und die logische Zuordnung zwischen Pixeln und Palettenindizes hatte. Bei moderner Hardware ist dies jedoch etwas schwieriger, da das Konzept der Paletten nicht dasselbe ist.
Alle meine Texturen sind 32-Bit und verwenden keine Paletten.
Ich kenne zwei Möglichkeiten, um den gewünschten Effekt zu erzielen. Ich bin jedoch gespannt, ob es bessere Möglichkeiten gibt, diesen Effekt auf einfache Weise zu erzielen. Die beiden mir bekannten Optionen sind:
- Verwenden Sie einen Shader und schreiben Sie etwas GLSL, um das Verhalten "Palettentausch" auszuführen.
- Wenn Shader nicht verfügbar sind (z. B. weil sie von der Grafikkarte nicht unterstützt werden), können Sie die "ursprünglichen" Texturen klonen und mit den vorab angewendeten Farbänderungen verschiedene Versionen erstellen.
Im Idealfall würde ich gerne einen Shader verwenden, da dieser unkompliziert zu sein scheint und im Gegensatz zur Methode der duplizierten Textur nur wenig zusätzliche Arbeit erfordert. Ich mache mir Sorgen, dass das Duplizieren von Texturen, nur um eine Farbe in ihnen zu ändern, VRAM verschwendet - sollte ich mir darüber keine Sorgen machen?
Bearbeiten : Ich habe die Technik der akzeptierten Antwort verwendet und hier ist mein Shader als Referenz.
uniform sampler2D texture;
uniform sampler2D colorTable;
uniform float paletteIndex;
void main()
{
vec2 pos = gl_TexCoord[0].xy;
vec4 color = texture2D(texture, pos);
vec2 index = vec2(color.r + paletteIndex, 0);
vec4 indexedColor = texture2D(colorTable, index);
gl_FragColor = indexedColor;
}
Beide Texturen sind 32-Bit, eine Textur wird als Nachschlagetabelle verwendet, die mehrere Paletten enthält, die alle die gleiche Größe haben (in meinem Fall 6 Farben). Ich verwende den roten Kanal des Quellpixels als Index für die Farbtabelle. Dies hat wie ein Zauber gewirkt, um einen Megaman-ähnlichen Palettentausch zu erreichen!
Ich kann mir das auf zwei Arten vorstellen.
Weg # 1: GL_MODULATE
Sie können das Sprite in Graustufen erstellen und
GL_MODULATE
die Textur, wenn es mit einer einzelnen Volltonfarbe gezeichnet wird.Beispielsweise,
Dies lässt Ihnen jedoch nicht viel Flexibilität zu. Grundsätzlich können Sie nur heller und dunkler werden, wenn Sie denselben Farbton haben.
Weg # 2:
if
Aussage (schlecht für die Leistung)Sie können Ihre Texturen auch mit einigen Schlüsselwerten für R, G und B einfärben. So ist beispielsweise die erste Farbe (1,0,0), die zweite Farbe (0,1,0) und die dritte Farbe Farbe ist (0,0,1).
Sie erklären ein paar Uniformen wie
Im Shader ist die endgültige Pixelfarbe ungefähr so
color1
,color2
,color3
, Sind Uniformen , so dass sie vor den Shader - Läufe eingestellt werden (je nachdem , was „Anzug“ Megaman ist in), dann wird der Shader einfach den Rest.Sie könnten auch
if
Anweisungen verwenden, wenn Sie mehr Farben benötigen, aber die Gleichheitsprüfungen müssten korrekt funktionieren (Texturen sind normalerweiseR8G8B8
zwischen 0 und 255 in der Texturdatei, aber im Shader haben Sie rgba floats).Methode 3: Speichern Sie die Bilder in verschiedenen Farben redundant in der Sprite-Map
Dies ist möglicherweise der einfachste Weg, wenn Sie nicht wahnsinnig versuchen, Speicherplatz zu sparen
quelle
Ich würde Shader verwenden. Wenn Sie sie nicht verwenden möchten (oder nicht können), würde ich eine Textur (oder einen Teil einer Textur) pro Farbe verwenden und nur sauberes Weiß verwenden. Auf diese Weise können Sie die Textur (z. B. durchgehend
glColor()
) tönen, ohne zusätzliche Texturen für Farben erstellen zu müssen. Sie können sogar während des Laufs die Farben tauschen, ohne dass zusätzliche Texturarbeiten anfallen.quelle
"Nicht alle Farben des Sprites ändern sich, nur bestimmte."
Alte Spiele machten Palettentricks, weil das alles war, was sie hatten. Heutzutage können Sie mehrere Texturen verwenden und auf verschiedene Arten kombinieren.
Sie können eine separate Graustufenmasken-Textur erstellen, mit der Sie entscheiden, welche Pixel die Farbe ändern. Weiße Bereiche in der Textur erhalten die volle Farbmodifikation und schwarze Bereiche bleiben unverändert.
In Shader-Sprache:
Oder Sie können die Mehrfachtexturierung mit festen Funktionen mit verschiedenen Texturkombinierermodi verwenden.
Es gibt offensichtlich viele verschiedene Wege, wie Sie dies erreichen können. Sie können Masken für verschiedene Farben in jeden der RGB-Kanäle einfügen oder die Farben durch Farbtonverschiebung in einem HSV-Farbraum modulieren.
Eine andere, vielleicht einfachere Möglichkeit besteht darin, das Sprite einfach mit einer separaten Textur für jede Komponente zu zeichnen. Eine Textur für die Haare, eine für die Rüstung, eine für die Stiefel usw. Jede Farbe ist separat tönbar.
quelle
Erstens wird es allgemein als Radfahren (Palettenradfahren) bezeichnet, was Ihrem Google-fu möglicherweise hilft.
Dies hängt genau davon ab, welche Effekte Sie erzeugen möchten und ob Sie sich mit statischen 2D-Inhalten oder dynamischen 3D-Inhalten beschäftigen (dh, Sie möchten nur mit Spites / Texturen arbeiten oder eine ganze 3D-Szene rendern und diese dann auf Paletten tauschen). Auch wenn Sie sich auf eine Reihe von Farben beschränken oder Vollfarben verwenden.
Ein vollständigerer Ansatz unter Verwendung von Shadern wäre, tatsächlich farbindizierte Bilder mit einer Palettentextur zu erzeugen. Erstellen Sie eine Textur, aber anstatt Farben zu haben, verwenden Sie eine Farbe, die einen Index zum Nachschlagen darstellt, und verwenden Sie dann eine andere Textur von Farben, nämlich die Platte. Beispielsweise könnte Rot die t-Koordinate der Texturen und Grün die s-Koordinate sein. Verwenden Sie einen Shader, um die Suche durchzuführen. Und Animieren / Ändern Sie die Farben dieser Palettentextur. Dies kommt dem Retro-Effekt sehr nahe, funktioniert jedoch nur für statische 2D-Inhalte wie Sprites oder Texturen. Wenn Sie echte Retro-Grafiken erstellen, können Sie möglicherweise tatsächlich indizierte Farbsprites erstellen und etwas schreiben, um sie und die Paletten zu importieren.
Sie sollten auch herausfinden, ob Sie eine "globale" Palette verwenden. So wie alte Hardware funktionieren würde, weniger Speicher für Paletten, da Sie nur eine benötigen, aber schwerer zu produzieren sind, da Sie die Palette über alle Bilder hinweg synchronisieren müssen) oder jedem Bild eine eigene Palette zuweisen müssen. Das würde Ihnen mehr Flexibilität geben, aber mehr Speicherplatz verbrauchen. Natürlich können Sie beides tun, aber Sie können auch nur Paletten für die Dinge verwenden, die Sie mit dem Farbrad fahren. Überlegen Sie auch, inwieweit Sie Ihre Farben nicht einschränken möchten. In alten Spielen werden beispielsweise 256 Farben verwendet. Wenn Sie eine Textur verwenden, erhalten Sie die Anzahl der Pixel, sodass Sie eine 256 * 256 erhalten
Wenn Sie nur einen billigen Fake-Effekt wie fließendes Wasser wünschen, können Sie eine zweite Textur erstellen, die eine Graustufenmaske für den Bereich enthält, den Sie ändern möchten. Verwenden Sie dann die Mastertexturen, um den Farbton / die Sättigung / die Helligkeit um den Betrag im zu ändern Graustufenmaske Textur. Sie könnten sogar fauler sein und einfach den Farbton / die Helligkeit / die Sättigung von irgendetwas in einem Farbbereich ändern.
Wenn Sie es in 3D benötigen würden, könnten Sie versuchen, das indizierte Bild im laufenden Betrieb zu generieren, aber es wäre langsam, da Sie die Palette nachschlagen müssten, und Sie wären wahrscheinlich auch in der Farbpalette eingeschränkt.
Andernfalls könnten Sie es einfach im Shader vortäuschen. Wenn color == swapping color ist, tauschen Sie es aus. Das wäre langsam und würde nur mit einer begrenzten Anzahl von Farbwechseln funktionieren, sollte aber keine der heutigen Hardware belasten, insbesondere wenn Sie sich nur mit 2D-Grafiken befassen und immer markieren können, welche Sprites Farbwechsel aufweisen und einen anderen Shader verwenden.
Ansonsten fälsche sie wirklich, mache ein paar animierte Texturen für jeden Zustand.
Hier ist eine großartige Demo des Palettenradfahrens in HTML5 .
quelle
Ich glaube, wenns schnell genug sind, um den Farbraum [0 ... 1] in zwei Teile zu unterteilen:
Auf diese Weise werden Farbwerte zwischen 0 und 0,5 für normale Farbwerte reserviert; und 0,5 - 1,0 sind für "modulierte" Werte reserviert, wobei 0,5 - 1,0 jedem vom Benutzer ausgewählten Bereich zugeordnet sind.
Nur die Farbauflösung wird von 256 Werten pro Pixel auf 128 Werte gekürzt.
Wahrscheinlich kann man integrierte Funktionen wie max (color-0.5f, 0.0f) verwenden, um die ifs vollständig zu entfernen (um sie gegen Multiplikationen mit Null oder Eins zu tauschen ...).
quelle