GetPixel in SDL

Liebe Leute

Mit SDL_Draw habe ich einige Pixel des Bildschirms z.B. rot und andere violett eingefärbt.

Nun möchte ich eine Funktion, mit der ich die Pixelfarbe eines Pixels (z.B. Pixel 30.48) abrufen kann.

Damit könnte man zum Beispiel ein Programm schreiben, dass alle roten Pixel auf dem Bildschirm blau färbt, die violetten aber lässt, wie sie sind. Ich werde die Funktion für ein Spiel benutzen.

Kennt jemand eine solche Funktion von SDL?

Liebe Grüsse
Kalsan

Zerwas

Vorweg, ich habe SDL noch nie verwendet.

Nun möchte ich eine Funktion, mit der ich die Pixelfarbe eines
Pixels (z.B. Pixel 30.48) abrufen kann.

Unter SDL sind meines Wissens auch OpenGL Funktionen verfügbar. OpenGL bietet die Funktion glReadPixels() an, um Pixeldaten aus dem Framebuffer zu lesen.

Damit könnte man zum Beispiel ein Programm schreiben, dass
alle roten Pixel auf dem Bildschirm blau färbt, die violetten
aber lässt, wie sie sind. Ich werde die Funktion für ein Spiel
benutzen.

Gut, das machst du aber anders besser. Für genau solche Zwecke hat man Shader erfunden. Das sind kleine Programme, die auf der Grafikkarte ablaufen und mit denen du teilweise direkten Zugang zur Grafikpipline hast.

OpenGL bietet dir da GLSL (OpenGL Shading Language) an. Man kann aber auch mit CG (C for Graphics) von NVIDIA im Zusammenhang mit OpenGL arbeiten.

Kleines Beispiel (GLSL):

void main()
{
 if(vec3(gl\_Color) == vec3(1.0, 0.0, 0.0))
 {
 gl\_FragColor = vec4(0.0, 0.0, 1.0, 1.0);
 }
 else
 gl\_FragColor = gl\_Color;
}

Wenn die Eingangsfarbe (gl_Color) rot (1.0, 0.0, 0.0) ist, wird die Ausgangsfarbe (gl_FragColor) auf blau (0.0, 0.0, 1.0) gesetzt mit 1.0 Alpha, ansonsten wird er Farbwert einfach weitergegeben. Das ist ein einfaches Beispiel für einen sogenannten Fragmentshader. Dieses kleine Program wird auf der Grafikkarte für jeden Pixel (Fragment) der gezeichnet werden soll ausgeführt.

Das sollte dein Problem besser lösen. Probiers aus, macht zum Teil ganz schön Spaß, was man mit Shadern alles machen kann =)

mfg dixxi

Hallo Dixxi

Herzlichen Dank für deine Antwort.

Von welchem Variablentyp sind denn vec3 & co? Wie kann ich das ganz bestimmte Pixel 3.15 anstuern?

Wie du mit SDL, so habe ich mit OpenGL noch nie bewusst gearbeitet :stuck_out_tongue:

Liebe Grüsse
Kalsan

Von welchem Variablentyp sind denn vec3 & co?

Das sind Typen der OpenGL Shading Language. vec3 ist im Prinzip ein float array mit 3 elementen. Sie dir am besten das an, bevor ich dir jetzt lange etwas erkläre:
http://www.lighthouse3d.com/opengl/glsl/index.php?intro
Da findest du alles zu GLSL was du brauchst.

Wie kann ich das ganz bestimmte Pixel 3.15 anstuern?

In einem Fragmentshader erhältst du die aktuelle Pixelposition über die Variable gl_FragCoord.

Wenn du aber nur einen Pixel manipulieren willst, ist vielleicht die Funktion glDrawPixels() besser geeignet. Mit glRasterPos steuerst du den Pixel an und mit glDrawPixel und einem 1 mal 1 Rechteck, kannst du dann in genau diesen einen Pixel zeichen.

mfg dixxi

Wie du mit SDL, so habe ich mit OpenGL noch nie bewusst
gearbeitet :stuck_out_tongue:

Liebe Grüsse
Kalsan

Ich möchte keinesfalls anmaßend erscheinen, lediglich helfen. Deswegen hoffe ich, dass du mich nicht falsch verstehst.
Aber an deiner Stelle würde ich mich fragen, ob es nicht einfacher wäre die Farbinformationen direkt z.B. in einem array zu speichern. Ich nehme einfach mal an, dass du sie gezeichnet hast und dir auch im klaren warst in welcher Farbe und Position. Denn Grafikkarten sind, soweit ich weiss, dafür konzipiert Informationen in ihren Ram zu schreiben, Lesevorgänge hingegen sind zumeist extrem langsam und sollten nur in absoluten Notfällen verwendet werden. Gerade in Spielen zählt ja bekanntlich die Performance. Sowieso sind Grafikfunktionen alâ drawpixel(x,y) oder getpixel(x,y) sehr langsam, da erst die Speicherstelle im Grafikram berechnet werden muss usw. Also am besten immer alles mit einemmal zeichnen z.B. mit nem Puffer.

Wenn du dir bereits darüber im Klaren warst und ich eigentlich nur dünnes geredet hab tut mir das wie gesagt leid.

ansonsten mfg HyDr0x

Wenn du dir bereits darüber im Klaren warst und ich eigentlich
nur dünnes geredet hab tut mir das wie gesagt leid.

Aber nein, die Idee hatte ich noch nicht, und ich finde sie sehr gut. Allerdings möchte ich sie nur anwenden, falls es wirklich keine andere Option gibt. Denn es befinden sich auch andere Objekte auf dem Bildschirm (png Bilder), die ich ebenfalls erkennen lassen möchte, falls irgendwie möglich. Deine Idee ist aber eine ausgezeichnete Notlösung, herzlichen Dank!
LG
Kalsan

*4u

Schön zu hören das ich dir helfen konnte.
Vielleicht kannst du es ja so einrichten, dass du am Anfang die png’s in das screenarray einließt. Dann könntest du mithilfe der png-Position aus der lokalen Pixelposition die globale ausrechnen und dann den jeweiligen Pixel verändern. Da ich keine konkreten Informationen hab ob sich z.B. die png’s bewegen oder nicht usw. kann ich nichts konkreteres liefern.
Falls die png’s statisch sind ist es meiner Meinung nach schneller eine einmalige Vorberechnung durchzuführen. Das bisschen Addition und Subtraktion wird dann immernoch signifikant schneller sein als jedesmal in einer Spielschleife alles mit getpixel(x,y) writepixel(x,y) Befehlen zu handeln.
Wenn die png’s sich bewegen wird es wesentlich schwieriger, dann verhält unser screenarray wie der Klon des frontbuffers der Grafikkarte und man müsste für jede Bewegung die das image macht wieder jeden Pixel einzeln neu in den Puffer kopieren. Ob es dann schneller ist ist fraglich.

Hoffe ich konnte dir ein wenig helfen. Gründsätzlich würde ich aber meine Methode vorziehen, je nachdem wie du dir das nun genau vorstellst. Grundsätzlich würde ich dir aber noch den Tipp geben in 2D nur dann etwas neu zu zeichnen wenn es auch unbedingt notwendig ist, sprich sich etwas verändert hat. Nicht jedesmal den kompletten Bildschirm neuzeichnen wenn sich garnix oder nur z.B. ein Image bewegte. Sonst wirds sehr schnell ziemlich langsam.

1 Like

Vielen Dank für diese weiteren Tipps.

Nicht brauchen kann ich den Tipp mit dem PNG vorberechnen, da die PNGs teiltransparent sind und ich so über 10’000 Pixel vorberechnen müsste…

Dagegen ist aber der Tipp mit dem nicht alles neu zeichnen hervorragend! Aus lauter Gewohnheit hätte ich nämlich einfach alles ständig neu geblittet. Im Gegesatz zu meinen gewohnten Programmen ist das hier in diesem speziellen Fall allerdings nicht nötig. Da kann ich natürlich viel Tempo machen.

Apropos: Der GetPixel-Befehl bezieht sich maximal auf 90 Pixel pro Aktualisierung. Deshalb sollte er den PC nicht zu stark verlangsamen.

Liebe Grüsse
Kalsan