Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

1

06.09.2012, 00:20

Farbübergänge

Hallo alle zusammen. Ich versuche eine Farbe kontinuierlich in eine andere übergehen zu lassen (ähnlich wie in einem Farbkreis). Die Reihenfolge ist ebenfalls wie auf einem "Farbkreis" (Rot, Orange, Gelb, grün, hellblau, dunkelblau, pink und dann wieder von vorne bei rot). Ich habe auch einen funktionierenden code:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// setup
    sf::Color color;

//...
// update loop ( fTime is the elapsed frame time)    

    fRed = color.r;
    fGreen = color.g;
    fBlue = color.b;
   
    if (fRed == 255 && fGreen < 255 && fBlue == 0)
        color = sf::Color(255, fGreen + 25 * fTime, 0);
    else if (fRed > 0 && fGreen == 255 && fBlue == 0)
        color = sf::Color(fRed - 25 * fTime, 255, 0);
    else if (fRed == 0 && fGreen == 255 && fBlue < 255)
        color = sf::Color(0, 255, fBlue + 25 * fTime);
    else if (fRed == 0 && fGreen > 0 && fBlue == 255)
        color = sf::Color(0, fGreen - 25 * fTime, 255);
    else if (fRed < 255 && fGreen == 0 && fBlue == 255)
        color = sf::Color(fRed + 25 * fTime, 0, 255);
    else if (fRed == 255 && fGreen == 0 && fBlue > 0)
        color = sf::Color(255, 0, fBlue - 25 * fTime);

// now use the color somehow

Allerdings kommt mir das ganze sehr sehr ineffizient vor und deshalb hab ich mich gefragt, ob jemand einen bessere Methode kennt um den gewünschten Effekt zu erreichen. Ich wäre wirklich sehr dankbar für Anregungen und Tipps :)
Danke im vor raus,
Foaly

dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

2

06.09.2012, 00:28

Sieht imo eigentlich ganz ok aus...

Das könnte für dich interessant sein: http://en.wikipedia.org/wiki/HSL_and_HSV#From_HSV

Hier noch ein kleines Snippet:

HLSL-Quelltext

1
2
3
4
5
6
7
float3 hsv_to_rgb(float3 hsv)
{
  float3 rgb = clamp(float3(abs(3 - 6 * hsv.x) - 1,
                            2 - abs(2 - 6 * hsv.x),
                            2 - abs(4 - 6 * hsv.x)), 0.0f, 1.0f) * hsv.y * hsv.z + hsv.z * (1 - hsv.y);
  return rgb;
}

Ist zwar HLSL, aber evtl. nützt es was... ;)

(hsv.x = hue zwischen 0 und 1, hsv.y = saturation, hsv.z = value)

3

06.09.2012, 00:42

Vielen dank erstmal für die schnelle Antwort.
Also falls ich die Option mit dem shader nehme. Meinst du dann das ich einfach beim hue zwischen 0 und 1 hin und her pendele und es dann per shader in RGB konvertiere und einfärbe? Ich verwende SFML und damit GLSL aber die Konvertierung dürfte ja nicht wozu schwer sein :)
Hat sonst noch jemand einen anderen Algorithmus?

dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

4

06.09.2012, 00:53

Ich wollte damit nicht sagen, dass du einen Shader verwenden sollst oder sowas, das würde im Kontext deiner Anwendung vermutlich nichtmal Sinn machen. Der Code zeigt einfach vor, wie man die Konvertierung von HSV nach RGB implementieren könnte. Sieh es als mögliche Inspiration für deine eigene Umsetzung, sofern du mit HSV in deiner Anwendung überhaupt was sinnvolles anfangen kannst. Wenn du einfach nur den Farbkreis durchlaufen willst und sonst nix, ist deine Lösung, wie gesagt, imo eigentlich schon ganz gut... ;)

Dieser Beitrag wurde bereits 4 mal editiert, zuletzt von »dot« (06.09.2012, 01:01)


5

06.09.2012, 11:35

Naja eigentlich arbeite ich meistens mit RGB... Aber in diesem Fall scheint es mir tatsächlich am einfachsten HSV zu nehmen und dann einfach S und V auf 1 setze und H zwischen 0 und 360 hin und her wandern lasse und dann das ganze zurück nach RGB konvertiere und als Farbe setzen. Ich möchte so effizient wie möglich arbeiten, weil sich die Farbe in jedem Frame neu berechnet wird und ich möglichst wenig Ressourcen dafür verschwenden möchte. (Deshalb ist ein Shader gar keine schlechte Idee...)

Trotzdem hab ich die Hoffnung noch nicht so ganz aufgegeben... :D Mein Code mit den ganzen if's und else's kommt mir klumpig vor. Hat jemand ne Idee wie ich das ganze in RGB bewerkstelligen könnte?

dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

6

06.09.2012, 12:24

Wenn du nur einen einzelnen Farbwert pro Frame berechnen willst, ist ein Shader völlig sinnlos und wäre, wenn natürlich auch technisch möglich, eine unglaublich ineffiziente Lösung. Du müsstest die Parameter von der CPU auf die GPU bringen, den Shader starten und das Ergebnis wieder zurücklesen. Dein Code da oben hat die Farbe schon lange ausgerechnet, bevor überhaupt auch nur beim Grafiktreiber angekommen ist, dass es so aussieht als ob es demnächst evtl. irgendwas zu tun gibt. Shader sind interessant, wenn du z.B. den ganzen Bildschirm füllen willst und jeder Pixel dabei einen eigenen Farbwert haben soll...

Nachdem du ja nur den Farbkreis durchlaufen willst, brauchst du ja keine vollwertige HSV -> RGB Konvertierung, sondern musst ja eigentlich nur zu einem gegebenen Hue die RGB Werte ausrechnen. Dieses Bild zeigt schön die einzelnen RGB Komponenten als Funktion des Hue. Das ganze kann man einfach als bei 0 und 1 abgeschnittene Hütchen betrachten:



Und genau diese Hütchen bekommt man über die Betragsfunktion. Und genau das ist die Idee hinter meiner Umsetzung oben:

§\begin{align} r'(h) &= |3 - 6 \cdot h| - 1 \\ g'(h) &= 2 - |2 - 6 \cdot h| \\ b'(h) &= 2 - |4 - 6 \cdot h| \end{align}§

wobei §r'(h)§ das rote, §g'(h)§ das grüne und §b'(h)§ das blaue Hütchen und §h§ der Hue (0 = 0°, 1 = 360°) ist. Um die RGB Farbwerte zu bekommen, müssen wir nur noch auf §[0, 1]§ begrenzen:

§\begin{align} r(h) &= \min(\max(r'(h), 0), 1) \\ g(h) &= \min(\max(g'(h), 0), 1) \\ b(h) &= \min(\max(b'(h), 0), 1) \end{align}§

Ich bin mir aber ziemlich sicher, dass es noch effizientere Lösungen gibt...

Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von »dot« (06.09.2012, 14:01)


7

06.09.2012, 13:49

Aaaaaaah jetzt hab ich den Wink mit dem Zaunpfahl von oben verstanden... Vielen Dank!
Ja ich hab in der zwischen zeit das implementiert, was ich oben beschrieben hab, aber jetzt fällt mir auf, das das wirklich viel zu umständlich ist. Ich muss ja tatsächlich einfach nur die Hue wert über zeit verändern und dann in RGB umrechnen und die Rechnung dafür scheint ja nicht sonderlich kompliziert zu sein :D Danke für die ausführliche Erklärung! An welcher Stelle besteht den deiner Meinung nach noch Optimierungspotential?

dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

8

06.09.2012, 13:55

Naja, du bist es ja selbst, der ständig sagt, dass dir deine Methode nicht effizient genug vorkommt. Wieso genau kommt dir das denn so vor?

Falls es dir um die ganzen ifs geht: Die Berechnung lässt sich nach meiner Methode eben praktisch ausschließlich mit arithmetischen Operationen durchführen, genau das war mein Ziel damals...

Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von »dot« (06.09.2012, 14:04)


9

06.09.2012, 15:31

Ja genau um die ganzen if's gings mir. Deine Version ist ja auch wesentlich effizienter als meine! Deshalb finde ich ja auch viel besser. Ich wollte nur wissen was du mit einer "noch effizienteren Lösung" meintest :)

dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

10

06.09.2012, 15:37

Damit meinte ich, dass ich davon ausgehe, dass es vermutlich irgendwo irgendjemanden gibt, der eine noch bessere Lösung kennt als ich. ;)

Werbeanzeige