  Um Eigenschaften und Positionierung von Licht in OpenGL zu verstehen, musste ich es mir erst visualisieren. Das Ergebnis teile ich gerne mit euch.
  Es sind ein paar API Aufrufe dabei, es ist aber alles sehr überschaubar gehalten.
  Meine Top 3 Learnings waren: - Glanzlichter sind doch gar nicht so schwer - Platzierung von Licht ist unbeeindruckt von Pushs und Pops - Die Lichtgenauigkeit ist direkt von der Dreiecksanzahl abhängig
 
  
  $H OpenGL.ph
declare time&, frames%
declare rtri!, light#
declare white#,red#, green#,blue#, zero#, list&,loop&
dim light#,16
dim white#,16
dim red#,16
dim green#,16
dim blue#,16
dim zero#,16
FloatArray(white#,1,1,1,1)
FloatArray(red#,1,0,0,1)
FloatArray(green#,0,1,0,1)
FloatArray(blue#,0,0,1,1)
FloatArray(zero#,0,0,0,1)
FloatArray(light#,-0.05,-0.05,-0.05, 1.0)
PROC GRID
    'Es gibt bessere Möglichkeiten, Gitter zu erstellen aber für dieses Beispiel reicht es, ein einzelner Quad würde
    'nicht vernünftig beleuchtet werden (siehe Würfel) "per-vertex lighting"
    parameters size!, resolution!
    if list& = 0
        list& = ogl("StartList")
        oGL("Move", -(size! * 0.5)-(size! / resolution! * 0.5),(size! * 0.5)-(size! / resolution! * 0.5), 0)
        whileloop 1, int(resolution!)
            oGL("Move", (size! / resolution!),-size!, 0)
            loop& = &loop
            whileloop 1, int(resolution!)
                if ((&loop + loop&) MOD 2) = 0
                    oGL("Color", 0.2,0.2,0.2,1.0)
                else
                    oGL("Color", 1.0,1.0,1.0,1.0)
                endif
                oGL("Move", 0.0, (size! / resolution!), 0)
                oGL("Quad", (size! / resolution!),(size! / resolution!))
            endwhile
        endwhile
        ogl("EndList")
    endif
    ogl("Drawlist", list&)
ENDPROC
Proc Light
    'Zur besseren Veranschaulichung in Proc gekapselt, wenn es um Performance geht nimmt man einen fertigen Bereich,
    'Definition von allem aus Position würde auch einmal bei Initialisierung reichen, das Objekt dient der Visualisierung
    'der Lichtposition. Das Grundlicht (Ambient) ist leicht negativ gesetzt da es aus irgendeinem Grund bei "0" noch etwas
    'Licht gibt
    parameters no&, r!, g!, b!
    declare color#
    dim color#, 16
    FloatArray(color#,r!, g!, b!, 1.0)
    oGL("glMaterialfv", ~GL_FRONT_AND_BACK, ~GL_EMISSION, color#)
    oGL("Color", r!, g!, b!, 1.0)
    oGL("Cuboid", 0.15, 0.15, 0.15)
    oGL("glMaterialfv", ~GL_FRONT_AND_BACK, ~GL_EMISSION, zero#)
    oGL("glLightfv",~GL_LIGHT0 + no&,~GL_AMBIENT,light#)'GL_AMBIENT
    oGL("glLightfv",~GL_LIGHT0 + no&,~GL_DIFFUSE, color#)' GL_DIFFUSE
    oGL("glLightfv",~GL_LIGHT0 + no&,~GL_POSITION,zero#)' GL_POSITION
    oGL("glLightfv",~GL_LIGHT0 + no&,~GL_SPECULAR, white#)' GL_SPECULAR
    oGL("glEnable",~GL_LIGHT0 + no&)
    dispose color#
Endproc
proc DrawGLScene
    oGL("Clear")
    oGL("Move", 0, 0.75, -5.0)
    oGL("glMaterialfv",~GL_FRONT_AND_BACK, ~GL_SPECULAR, white#)' Glanzlichtfarbe
    oGL("glMaterialf", ~GL_FRONT_AND_BACK, ~GL_SHININESS,128.0)' Glanzlichtgröße (große Zahl ist kleiner, max 128.0)
    oGL("glDisable",~GL_LIGHT0)'Default Licht aus
    '-------
    'Lichtpositionen lassen sich nicht durch Push/Pop kapseln!
    'Jegliche Positionierung muss also danach wieder negiert werden, bei Rotationen achsenweise
    'und alles immer in umgekehrter Reihenfolge - eine Aufnahme davon in der Light()-Funktion wäre denkbar
    'LICHTER
    oGL("Rotate",0,0, rtri!)
    oGL("Move", 2.0, 0,0)
    'Light(Lichtnummer, Rot, Grün, Blau)
    Light(1,1,0,0)' rot
    oGL("Move", -2.0, 0,0)
    oGL("Rotate", 0,0,-rtri!)
    oGL("Rotate",0,90,0)
    oGL("Rotate",0,0, rtri!)
    oGL("Move", 2.0, 0,0)
    Light(2,0,1,0)' grün
    oGL("Move", -2.0, 0,0)
    oGL("Rotate", 0,0,-rtri!)
    oGL("Rotate", 0,-90,0)
    oGL("Rotate", 0, rtri!,0)
    oGL("Move", 2.5, 0,0)
    Light(3,0,0,1)' blau
    oGL("Move", -2.5, 0,0)
    oGL("Rotate", 0, -rtri!,0)
    'OBJEKTE
    oGL("Color", 1, 1, 1, 1)
    'etwas in der gegen herumschauen:
    oGL("Rotate",sin(rtri!*0.01) * 10.0, sin(rtri!*0.01) * 20.0, sin(rtri!*0.01) * 5.0)
    oGL("Push")'Boden
    oGL("Move", 0, -2.2, -4)
    oGL("Rotate",270, 0,0)
    GRID(20,40)
    oGL("Pop")
    oGL("Push")'Würfel, nur sehr eingeschränktes Lighting
    oGL("Move", -0.65, 0.5, 0)
    oGL("Rotate", -45, 45, 0)
    oGL("Cuboid", 0.75, 0.75,0.75)
    oGL("Pop")
    oGL("Push")'Kugel, mit vielen Dreiecken siehts richtig gut aus
    oGL("Move", 1, 0, 0)
    oGL("Sphere", 0.65, 192,192)
    oGL("Pop")
    oGL("Push")'Kegel / Cone
    oGL("Move", 2.5, -1.5, -1.0)
    oGL("Cylinder", 1.0, 0,2.0,192)
    oGL("Pop")
    oGL("Push")'Cylinder, sieht auch mit wenigen Unterteilungen schon gut aus
    oGL("Move", -2.0, -0.5, -1.5)
    oGL("Rotate", -15, -30, 30)
    oGL("Cylinder", 0.20, 0.20,4,30)
    oGL("Pop")
    oGL("Show")
    rtri! = rtri! + 1
endproc
Proc FloatArray
    parameters x&,a!,b!,c!,d!
    long x&,0  = single(a!)
    long x&,4  = single(b!)
    long x&,8  = single(c!)
    long x&,12 = single(d!)
Endproc
' Hauptprogramm
' -------------
declare ende%
CLS 0
oGL("Init", %hWnd, 0,0,0,1)
oGL("PosMode", 1)
oGL("glEnable",~GL_CULL_FACE)
oGL("glEnable",~GL_DEPTH_TEST)
oGL("BlendMode", 1)
oGL("Fog", 3, 6, 14)
time&   = &GetTickCount
frames% = 0
ende%   = 0
WhileNot ende%
    'WaitInput sollte in 3D-Anwendungen und Spielen in jedem Fall vermieden werden,
    'da dort auch ohne timer ca. 8 ms unkontrollierbar verschwinden
    if isKey(27)
        ende% = 1
    endif
    DrawGLScene()
    inc frames%
    if &GetTickCount - time& >= 1000' 1 Sekunde ist 'rum
        setText %hWnd, str$(frames%) + " Frames/sek"
        time&   = &GetTickCount
        frames% = 0
    endif
EndWhile
end
 |