Version 2.0!
Features
Tutorials
Files
Glossary
Projects
Contact
Links
Message Board
Extras
LuckyCam
Old News
Sign Guestbook
View Guestbook
VB Horoscope
VB Photo Album
.
ATTENTION READERS! Lucky's VB Gaming Site is no longer active. For updated game programming information and tutorials, please visit The Game Programming Wiki!

Ändern der Darstellung mit der "Gamma Contol"

Zieht euch eure Windeln an, weil ihr kurz davor seit euch in die Hosen zu machen. Ich habe das "GammaControl"-Objekt entschlüsselt, welches in DirectX7 enthalten ist, und habe jetzt die Möglichkeit die ausgegebenen Bildschirmfarben nach belieben zu verändern. Ich kann Einblenden, Ausblenden und den Rot-, Blau-, Grünkanal oder eine beliebige Farbkombination herauszufiltern. Ich kann Lichtblitze erzeugen (so wie das rote Aufleuchten des Bildschirmes, wenn ihr in Quake getroffen werdet) und jede Menge andere coole Sachen. Na, habt ihr euch schon nass gemacht?

Es gab ein paar Hindernisse, die VB-Programmierer davon abgehalten haben, "GammaControl" zu benutzen. Der Hauptgrund war der, dass die sog. "Gamma Ramps" Datenfelder sind, die sog. "unsigned" Integer-Variablen enthalten. Visual Basic unterstützt diese "unsigned" Integer aber nicht, also habe ich zwei schöne kleine Funktionen geschrieben, die diese Konvertierung übernehmen:

Public Function ConvToUnSignedValue(intValue As Integer) As Long

    If intValue >= 0 Then
	    ConvToUnSignedValue = intValue
        Exit Function
    End If
    ConvToUnSignedValue = intValue + 65535

End Function

Public Function ConvToSignedValue(lngValue As Long) As Integer

    If lngValue <= 32767 Then
        ConvToSignedValue = CInt(lngValue)
        Exit Function
    End If
    ConvToSignedValue = CInt(lngValue - 65535)

End Function

Wie ihr sehen könnt, reicht ein "unsigned" Integer von 0 bis 65355, wobei ein "signed" Integer von -32767 bis 32767 reicht. Ja, es ist die gleiche Anzahl an Werten, aber die Bits werden anders interpretiert. Wenn wir die "GammaControl" verwenden, erhalten wir "unsigned" Integer als Daten zurück. Visual Basic interpretiert diese jedoch als "signed" Integer und die Daten sind falsch. Jeder Wert unter 32767 wird zwar richtig behandelt, aber jedes Ergebnis darüber (z. B. 32768 bis 65535) werden das negative Gegenteil ergeben. Die Funktionen oben korrigieren diese Fehler. Sicherlich hätte ich sie eleganter schreiben können (vielleicht unter verwendung von Hexzahlen) aber sie erfüllen ihre Aufgabe gut genug.

Halten wir dieses Wissen also im Hinterkopf und fahren fort. Es wäre empfehlenswert, sich erst zu versichern, ob die Hardware "GammaRamp"-Unterstützung bietet, bevor wir weiter gehen:

Dim dx As New DirectX7
Dim dd As DirectDraw7
Dim hwCaps As DDCAPS
Dim helCaps As DDCAPS

    Set dd = dx.DirectDrawCreate("")
    dd.GetCaps hwCaps, helCaps
    If (hwCaps.lCaps2 And DDCAPS2_PRIMARYGAMMA) = 0 Then
        MsgBox "Your system does not have Gamma Ramp Support", vbOKOnly, "No Gamma Support"
        End
    End If

Dieser Code erstellt das DirectDraw-Objekt und überprüft dann seine Fähigkeiten. Wenn die DDSCAPS2_PRIMARYGAMMA-Fähigkeit nicht inerhalb der hwCaps.lCaps2 vorhanden ist, dann erscheint eine Fehlermeldung, und das Programm wird beendet.

Jetzt, da der Computer den Test bestanden hat, können wir die Primary Surface und eine "GammaControl" erstellen.Beachtet, dass die "GammaControl" NUR auf eine Primary Surface angewendet werden kann. Der folgende Code setzt voraus, das eine Primary Surface bereit korrekt eingerichtet wurde:

Dim GammaControler As DirectDrawGammaControl

    Set GammaControler = Primary.GetDirectDrawGammaControl

Es gibt zwei Dinge, die ihr mit der "GammaControl" anstellen könnt, sobald sie erstellt wurde: "GetGammaRamp" und "SetGammaRamp". Benutzt "GetGammaRamp" um den derzeitigen Status des Bildschirms festzustellen. Benutzt "SetGammaRamp" um den derzeitigen Status des Bildschirms zu verändern. Einfach genug... also lasst uns erstmal zwei DDGAMMARAMP-Objekte erstellen. Eines werden wir dazu verwenden, um die ursprünglichen Bildschirmeinstellungen zu sichern, und mit dem anderen werden wir den Bildschirm so anpassen wie es uns gefällt:

Dim GammaRamp As DDGAMMARAMP
Dim OriginalRamp As DDGAMMARAMP

    GammaControler.GetGammaRamp DDSGR_DEFAULT, OriginalRamp

Jetzt haben wir die derzeitigen Bildschirm-GammaRamp-Daten in unsere "OriginalRamp"-Variable geschrieben. Es ist wichtig, diese Kopie der Originalbildschirmdaten zu erhalten, da das Anwenden einer nicht linearen GammaRamp zu unerwarteten Ergebnissen führen kann, falls das System keine GammaCalibration-Unterstützung aufweist (die lCaps2 DDCAPS2_CANCALIBRATEGAMMA flag). Der Code oben verwendet die DDSGR_DEFAULT flag anstatt der DDSGR_CALIBRATE flag, da einige Computer keine Unterstützung für die Kalibration aufweisen (natürlich könnten wir diese Fähigkeiten, wie oben gezeigt abfragen und nutzen, falls vorhanden). Für unsere Zwecke werden einfache lineare GammaRamps ausreichen. Der einfachste Weg um diese zu erstellen ist, dass man einfach einen prozentualen Anteil der original GammaRamp-Werte verwendet. Die folgende Routine wird die GammaRamp-Werte des Bildschirms um einen steigenden Prozentsatz ändern:

Public Sub SetGamma(bytRed As Byte, bytGreen As Byte, bytBlue As Byte)

Dim i as Integer

    For i = 0 To 255
        GammaRamp.red(i) = ConvToSignedValue(ConvToUnSignedValue(OriginalRamp.red(i)) * bytRed / 100)
        GammaRamp.green(i) = ConvToSignedValue(ConvToUnSignedValue(OriginalRamp.green(i)) * bytGreen / 100)
        GammaRamp.blue(i) = ConvToSignedValue(ConvToUnSignedValue(OriginalRamp.blue(i)) * bytBlue / 100)
    Next
    GammaControler.SetGammaRamp DDSGR_DEFAULT, GammaRamp

End Sub

Das DDGAMMARAMP-Objekt besteht aus drei Datenfeldern, einer für jeden Farbkanal. Diese Arrays enthalten "unsigned" Integer, die einer bestimmten Ausgabe entsprechen, welche erstellt wird, wenn ein Wert übergeben wird. Durch das Verändern dieser Werte um einen prozentualen Anteil erhalten wir die Linearität, die für konstante, gleichbleibende Ergebnisse unerlässlich ist. Zum Beispiel bewirkt das Aufrufen von "SetGamma 50, 50, 50" die Verringerung der Intensität aller Farben um die Hälfte (halb abgeblendet). Durch das Aufrufen von "SetGamma 100, 0, 0" würden wir alle Farben außer den Rotfarbtönen entfernen, eine Überblendung auf Rot.

Der technische Aspekt der mit der Benutzung der "GammaControl" verbunden ist, könnte jetzt zwar etwas entmutigent klingen, aber ich versichere euch, es ist wirklich einfach. Schaut euch einfach das Beispielprojekt an, und ihr werdet erkennen wie leicht es ist.