1. Dashboard
  2. Mitglieder
    1. Letzte Aktivitäten
    2. Benutzer online
    3. Team
    4. Mitgliedersuche
  3. Forenregeln
  4. Forum
    1. Unerledigte Themen
  • Anmelden
  • Registrieren
  • Suche
Alles
  • Alles
  • Artikel
  • Seiten
  • Forum
  • Erweiterte Suche
  1. AutoIt.de - Das deutschsprachige Forum.
  2. Mitglieder
  3. UEZ

Beiträge von UEZ

  • JIT.au3 - C-Code direkt aus AutoIt kompilieren und ausführen

    • UEZ
    • 9. März 2026 um 22:27
    Zitat von AspirinJunkie

    Was meint ihr dazu?

    Why not. Können wir gerne testen.


    Apropos testen:

    AutoIt
    #AutoIt3Wrapper_UseX64=y
    #include <GDIPlus.au3>
    #include <GUIConstantsEx.au3>
    #include "..\JIT.au3"
    
    AutoItSetOption("GUIOnEventMode", 1)
    
    Global $hCRT = DllCall("kernel32.dll", "handle", "LoadLibraryW", "wstr", "ucrtbase.dll")[0]
    Global $pSin = DllCall("kernel32.dll", "ptr", "GetProcAddress", "handle", $hCRT, "str", "sin")[0]
    Global $pCos = DllCall("kernel32.dll", "ptr", "GetProcAddress", "handle", $hCRT, "str", "cos")[0]
    Global $pPow = DllCall("kernel32.dll", "ptr", "GetProcAddress", "handle", $hCRT, "str", "pow")[0]
    If Not $pSin Or Not $pCos Or Not $pPow Then Exit MsgBox(16, "Fehler", "Math-Pointer nicht gefunden!")
    
    Global $sCode = _
    'typedef double (*MathFn1)(double);'                                               								& @LF & _
    'typedef double (*MathFn2)(double, double);'                                       								& @LF & _
    'CALLCONV void RenderDwitter(unsigned int* ptr, int iW, int iH,'                   								& @LF & _
    '    MathFn1 fsin, MathFn1 fcos, MathFn2 fpow, double t) {'                      								& @LF & _
    '    int i, px, py;'                                                               								& @LF & _
    '    double y, k, e, d, q, P;'                                                    								& @LF & _
    '    int l = 840, l1 = (l >> 1), l2 = (l >> 2);'                                   								& @LF & _
    '    for (i = iW * iH - 1; i--;) ptr[i] = 0xF0202020;'                	     									& @LF & _
    '    for (i = 20000; i-- > 0; ) {'                                                 								& @LF & _
    '        y = (double)i / l;'                                                       								& @LF & _
    '        k = (4.0 + fsin(y * 2.0 - t) * 3.0) * fcos((double)i / 29.0);'		       								& @LF & _
    '        e = y / 8.0 - 11.0;'                                                      								& @LF & _
    '        d = fpow(k * k + e * e, 0.66);'                                           								& @LF & _
    '        q = fsin(k * 2.0) + 0.3 / k + fsin(y / 25.0) * k * (9.0 + 4.0 * fsin(e * 9.0 - d * 3.0 + t * 2.0));' 	& @LF & _
    '        P = d - t;'                                                        									& @LF & _
    '        px = (int)(q * fsin(P) + d * 39.0 - l1);'		                  										& @LF & _
    '        py = (int)(q + 30.0 * fcos(P) + l2);'            														& @LF & _
    '        if (px >=0 && px < iW && py >=0 && py <iH)'                        									& @LF & _
    '            ptr[py * iW + px] = 0xB0FFFFFF;'                               									& @LF & _
    '    }'                                                                     									& @LF & _
    '}'
    
    Global $mCode = _JIT_Compile($sCode, (@AutoItX64 ? "-O3 -ffloat-store" : "-Ofast"))
    If @error Then Exit MsgBox(16, "Fehler", "Kompilierung fehlgeschlagen")
    
    _GDIPlus_Startup()
    Global $iW = 840, $iH = Int($iW * 9 / 16)
    Global $pScan0 = DllStructCreate("ulong rgba[" & $iW * $iH & "]")
    Global $hBitmap = _GDIPlus_BitmapCreateFromScan0($iW, $iH, $GDIP_PXF32ARGB, $iW * 4, $pScan0)
    
    Global $hGUI = GUICreate("JIT Render https://dwitter.net/d/33997", $iW, $iH)
    GUISetState(@SW_SHOW)
    GUISetOnEvent($GUI_EVENT_CLOSE, "_Exit")
    
    Global $hGfx = _GDIPlus_GraphicsCreateFromHWND($hGUI)
    
    Global $fT = 0.0, $bExit
    
    Do
        DllCallAddress("none", $mCode.ptr + $mCode.Funcs["RenderDwitter"],  "ptr",    DllStructGetPtr($pScan0), _
    																		"int",    $iW, _
    																		"int",    $iH, _
    																		"ptr",    $pSin, _
    																		"ptr",    $pCos, _
    																		"ptr",    $pPow, _
    																		"double", $fT)
        _GDIPlus_GraphicsDrawImageRect($hGfx, $hBitmap, 0, 0, $iW, $iH)
        $fT += 0.05
    	If $bExit Then ExitLoop
    Until Not Sleep(10)
    
    _GDIPlus_GraphicsDispose($hGfx)
    _GDIPlus_BitmapDispose($hBitmap)
    _GDIPlus_Shutdown()
    _JIT_Free($mCode)
    
    Func _Exit()
    	$bExit = True
    EndFunc   ;==>_Exit_About
    Alles anzeigen


    Das sollte unter x86 und x64 laufen. Bitte mal testen.

    Original JS Code:

    Java
    l = c.width = 840;
    for (i = 2e4; i--; )
      	y = i / l,
        k = (4 + S(y * 2 - t) * 3) * C(i / 29),
        e = y / 8 - 11,
        d = (k * k + e * e)**0.66,
        q = S(k * 2) + 0.3 / k + S(y / 25) * k * (9 + 4 * S(e * 9 - d * 3 + t * 2)),
        P = d - t,
        px = q * S(P) + d * 39 - l / 2,
        py = q + 30 * C(P) + l / 4,
        x.fillRect(px, py, 1, 1)
    Alles anzeigen
  • JIT.au3 - C-Code direkt aus AutoIt kompilieren und ausführen

    • UEZ
    • 9. März 2026 um 19:09

    Zuhause funzt es bei mir auch. Code oben aktualisiert.

  • JIT.au3 - C-Code direkt aus AutoIt kompilieren und ausführen

    • UEZ
    • 9. März 2026 um 15:43

    ;)


    Btw, wie bekomme ich den Binärstring Online?

  • JIT.au3 - C-Code direkt aus AutoIt kompilieren und ausführen

    • UEZ
    • 9. März 2026 um 15:11

    $__g_JIT_oHTTP ist Global, aber nicht $oHTTP - wird immer local in der Funktionen definiert.


    Meinst du vielleicht?:


    $__g_JIT_sProxy = "localhost:3128"

  • JIT.au3 - C-Code direkt aus AutoIt kompilieren und ausführen

    • UEZ
    • 9. März 2026 um 14:44

    Bekomme mit den Binärstrings:
    !>14:41:06 AutoIt3 ended. rc:-1073741819 -> Speicherschutzfehler.

    Ist der Aufruf so korrekt? -> Global $aDll = DllCallAddress("none", $mCode.ptr + $mCode.Funcs["XorTexture"], "ptr", DllStructGetPtr($pScan0), "int", $iW, "int", $iH)


    $oHTTP.SetProxy(2, "localhost:3128")

    kann doch nicht funktionieren, da $oHTTP doch lokal in den Funktionen definiert wird, oder?

  • JIT.au3 - C-Code direkt aus AutoIt kompilieren und ausführen

    • UEZ
    • 9. März 2026 um 14:02

    Nette Idee :thumbup:

    Kann jemand mal testen?

    AutoIt
    #AutoIt3Wrapper_UseX64=y
    #include <GDIPlus.au3>
    #include "..\JIT.au3"
    
    Global $sSourceCode = _
    ' CALLCONV void XorTexture(unsigned int* ptr, int iW, int iH) {					' & @LF & _
    '        for (int y = 0; y < iH; y++) {                                         ' & @LF & _
    '            unsigned int yy = y * iW;	                                        ' & @LF & _
    '            for (int x = 0; x < iW; x++) {                                     ' & @LF & _
    '                unsigned int r = ( x       ^ y      ) & 0xFF;                  ' & @LF & _
    '                unsigned int g = ((x >> 1) ^ (y >> 1)) & 0xFF;                 ' & @LF & _
    '                unsigned int b = ((x * 1)  ^ (y * 3) ) & 0xFF;                 ' & @LF & _
    '                ptr[yy + x] 	= (0xFF << 24) | (r << 16) | (g << 8) | b;      ' & @LF & _
    '            }                                                                  ' & @LF & _
    '        }                                                                      ' & @LF & _
    '    }'                                                                          
    
    Global $mCode = _JIT_Compile($sSourceCode, @AutoItX64 ? "-Ofast" : "-O2")
    If @error Then Exit MsgBox(16, "Error", "Compilation failed")
    ConsoleWrite($mCode.ReusableString & @CRLF)
    
    _GDIPlus_Startup()
    Global $iW = Int(@DesktopWidth * 0.85), $iH = Int(@DesktopHeight * 0.85)
    Global $pScan0 = DllStructCreate("ulong rgba[" & $iW * $iH & "]")
    Global $hBitmap = _GDIPlus_BitmapCreateFromScan0($iW, $iH, $GDIP_PXF32ARGB, $iW * 4, $pScan0)
    
    Global $fTimer = TimerInit()
    Global $aDll = DllCallAddress("none", $mCode.ptr + $mCode.Funcs["XorTexture"], "ptr", DllStructGetPtr($pScan0), "int", $iW, "int", $iH)
    ConsoleWrite("Xor erstellt in " & TimerDiff($fTimer) & " ms." & @CRLF)
    
    Global $hGUI = GUICreate("JIT GDI+ XOR GFX Test", $iW, $iH)
    GUISetState()
    
    Global $hGfx = _GDIPlus_GraphicsCreateFromHWND($hGUI)
    _GDIPlus_GraphicsDrawImageRect($hGfx, $hBitmap, 0, 0, $iW, $iH)
    Do
    Until GUIGetMsg() = -3
    _GDIPlus_GraphicsDispose($hGfx)
    _GDIPlus_BitmapDispose($hBitmap)
    _GDIPlus_Shutdown()
    _JIT_Free($mCode)
    Alles anzeigen
  • Rollende Kugel mit Textur

    • UEZ
    • 28. November 2025 um 20:54

    Douky

    Ich muss die OpenGL DLL (ältere Version v5.1) in ScriptDir kopieren und folgendes Skript wandelt die Texturen korrekt um, sodass jetzt alles so aussieht, wie in deinem Screenshot oben.

    AutoIt
    #AutoIt3Wrapper_UseX64=n
    #include <GUIConstantsEx.au3>
    #include <WindowsConstants.au3>
    #include <Misc.au3>
    #include <Math.au3>
    #include <GDIPlus.au3> ; Wird benoetigt, um Bilder fuer Texturen zu laden
    
    ; --- OPENGL KONSTANTEN ---
    Global Const $PFD_DOUBLEBUFFER = 0x00000001
    Global Const $PFD_DRAW_TO_WINDOW = 0x00000004
    Global Const $PFD_SUPPORT_OPENGL = 0x00000020
    Global Const $PFD_TYPE_RGBA = 0
    Global Const $PFD_MAIN_PLANE = 0
    
    Global Const $GL_COLOR_BUFFER_BIT = 0x00004000
    Global Const $GL_QUADS = 0x0007
    Global Const $GL_TRIANGLE_FAN = 0x0006
    Global Const $GL_TEXTURE_2D = 0x0DE1
    Global Const $GL_TEXTURE_MAG_FILTER = 0x2800
    Global Const $GL_TEXTURE_MIN_FILTER = 0x2801
    Global Const $GL_LINEAR = 0x2601
    Global Const $GL_RGBA = 0x1908
    Global Const $GL_UNSIGNED_BYTE = 0x1401
    Global Const $GL_MODELVIEW = 0x1700
    Global Const $GL_PROJECTION = 0x1701
    Global Const $GL_TEXTURE = 0x1702
    Global Const $GL_BLEND = 0x0BE2
    Global Const $GL_SRC_ALPHA = 0x0302
    Global Const $GL_ONE_MINUS_SRC_ALPHA = 0x0303
    Global Const $GL_COMPILE = 0x1300
    Global Const $GL_POLYGON_SMOOTH = 0x0B42
    Global Const $GL_POLYGON_SMOOTH_HINT = 0x0C53
    Global Const $GL_NICEST = 0x1102
    Global Const $GL_MODELVIEW_MATRIX = 0x0BA6
    Global Const $GL_DEPTH_TEST = 0x0B71
    Global Const $GL_DEPTH_BUFFER_BIT = 0x00000100
    Global Const $GL_TEXTURE_WRAP_S = 0x2802
    Global Const $GL_TEXTURE_WRAP_T = 0x2803
    Global Const $GL_REPEAT = 0x2901
    Global Const $GL_MIRRORED_REPEAT = 0x8370
    
    ; --- KONFIGURATION ---
    Global $iWidth = 1000
    Global $iHeight = 600
    Global $fFriction = 0.98
    Global $fBallRadius = 18
    Global $iBorder = 40
    Global $sFolder = @ScriptDir
    
    ; Globale Arrays fuer die Kugeln
    Global $iMaxBalls = 16
    Global $aBalls[$iMaxBalls][8]
    Global $aTextures[$iMaxBalls] ; OpenGL Textur-IDs
    Global $aBallMatrices[$iMaxBalls] ; Strukturen fuer 4x4 Rotations-Matrizen
    
    ; Display Listen (Optimierung: Speichert Zeichenbefehle auf der Grafikkarte)
    Global $g_iListTable = 0
    Global $g_iListSphere = 0
    Global $g_bMSAA = False ; Status fuer Multisampling Anti-Aliasing
    
    ; DLL Handles
    Global $hOpenGL32 = DllOpen(@ScriptDir & "\opengl32.dll")
    Global $hGDI32 = DllOpen("gdi32.dll")
    Global $hUser32 = DllOpen("user32.dll")
    
    _Main()
    
    Func _Main()
        _GDIPlus_Startup()
    
        Local $hGui = GUICreate("AutoIt Billard Simulation (OpenGL)", $iWidth, $iHeight)
    
        ; --- OPENGL EINRICHTUNG ---
        Local $hDC = _WinAPI_GetDC($hGui)
        Local $hRC = _SetupOpenGL($hGui, $hDC)
    
        GUISetState(@SW_SHOW)
    
        ; OpenGL Status initialisieren
        _glEnable($GL_TEXTURE_2D) ; Texturierung aktivieren
        _glEnable($GL_BLEND) ; Transparenz aktivieren
        _glBlendFunc($GL_SRC_ALPHA, $GL_ONE_MINUS_SRC_ALPHA)
        _glEnable($GL_POLYGON_SMOOTH) ; Kantenglättung für Polygone
        _glHint($GL_POLYGON_SMOOTH_HINT, $GL_NICEST) ; Beste Qualität anfordern
    
        _glClearColor(0.0, 0.25, 0.0, 1.0) ; Dunkelgrüner Hintergrund (Clear Color)
    
        ; Ansichtsbereich & Orthogonale Projektion (2D-Koordinatensystem für 3D-Welt)
        _glViewport(0, 0, $iWidth, $iHeight)
        _glMatrixMode($GL_PROJECTION)
        _glLoadIdentity()
        ; Wir setzen den Z-Bereich auf -100 bis 100, damit die Kugeln (Radius 18) nicht abgeschnitten werden.
        _glOrtho(0, $iWidth, $iHeight, 0, -100, 100) ; Ursprung oben-links
        _glMatrixMode($GL_MODELVIEW)
    
        ; Texturen laden
        _LoadBallTextures()
    
        ; Rotations-Matrizen initialisieren
        _InitBallMatrices()
    
        ; Display Listen erstellen (Vorkompilierte Geometrie für Performance)
        _InitDisplayLists()
    
        ; Simulation starten (Kugeln aufbauen)
        _ResetTable()
    
        Local $hTimer = TimerInit()
        Local $hFpsTimer = TimerInit()
        Local $iFrames = 0
        Local $iFPS = 0
        Local $iIdleCounter = 0
    
        While 1
            Local $iMsg = GUIGetMsg()
            If $iMsg = $GUI_EVENT_CLOSE Then ExitLoop
    
            ; Framerate Begrenzung entfernt für maximale Flüssigkeit
            $hTimer = TimerInit()
    
            ; FPS Berechnung (Anzeige im Fenstertitel)
            $iFrames += 1
            If TimerDiff($hFpsTimer) >= 1000 Then
                $iFPS = $iFrames
                Local $sStatus = " [MSAA: " & ($g_bMSAA ? "An" : "Aus") & " | Smooth: An]"
                WinSetTitle($hGui, "", "AutoIt Billard Simulation (OpenGL)" & $sStatus & " - FPS: " & $iFPS)
                $iFrames = 0
                $hFpsTimer = TimerInit()
            EndIf
    
            ; --- 1. PHYSIK BERECHNUNG ---
            Local $bMovement = _UpdatePhysics()
    
            ; --- 1b. 3D ROTATION BERECHNUNG ---
            _UpdateRotations()
    
            ; --- 2. AUTO-RESET (Wenn alles stillsteht) ---
            If Not $bMovement Then
                $iIdleCounter += 1
                If $iIdleCounter > 120 Then
                    _ResetTable()
                    $iIdleCounter = 0
                EndIf
            Else
                $iIdleCounter = 0
            EndIf
    
            ; --- 3. ZEICHNEN (RENDERING) ---
            _Render()
            _SwapBuffers($hDC) ; Puffer tauschen (Double Buffering)
        WEnd
    
        ; Aufräumen
        _wglMakeCurrent(0, 0)
        _wglDeleteContext($hRC)
        _WinAPI_ReleaseDC($hGui, $hDC)
        DllClose($hOpenGL32)
        DllClose($hGDI32)
        DllClose($hUser32)
        _GDIPlus_Shutdown()
    EndFunc
    
    Func _Render()
        ; Bildschirm und Tiefenpuffer loeschen
        _glClear(BitOR($GL_COLOR_BUFFER_BIT, $GL_DEPTH_BUFFER_BIT))
        _glLoadIdentity()
    
        ; --- TISCH ZEICHNEN (Display List) ---
        ; Wir schalten den Tiefentest fuer den Hintergrund aus,
        ; damit er immer "ganz hinten" ist und nicht mit den Kugeln z-fightet.
        _glDisable($GL_DEPTH_TEST)
        _glDisable($GL_TEXTURE_2D)
        _glCallList($g_iListTable)
        _glEnable($GL_DEPTH_TEST)
    
        ; --- KUGELN ZEICHNEN ---
        _glEnable($GL_TEXTURE_2D)
        _glColor3f(1.0, 1.0, 1.0) ; Farbe zuruecksetzen (Weiss = Originaltextur)
    
        For $i = 0 To $iMaxBalls - 1
            If Not $aBalls[$i][5] Then ContinueLoop
    
            Local $fX = $aBalls[$i][0]
            Local $fY = $aBalls[$i][1]
            Local $iTexID = $aTextures[$i]
    
            _glPushMatrix()
            ; Kugel an ihre 2D-Position verschieben
            _glTranslatef($fX, $fY, 0.0)
    
            If $iTexID <> 0 Then
                _glBindTexture($GL_TEXTURE_2D, $iTexID)
    
                ; 3D ROTATION ANWENDEN
                ; Wir laden die gespeicherte Rotationsmatrix der Kugel.
                ; Diese Matrix enthaelt die akkumulierte Rotation aller vergangenen Frames.
                Local $pMatrix = DllStructGetPtr($aBallMatrices[$i])
                _glMultMatrixf($pMatrix)
    
                ; Kugel zeichnen (3D Sphaere aus der Display List)
                _glCallList($g_iListSphere)
            Else
                ; Fallback fuer fehlende Textur (Weisse Kugel ohne Bild)
                _glDisable($GL_TEXTURE_2D)
                _glColor3f(1.0, 1.0, 1.0)
                _glCallList($g_iListSphere)
                _glEnable($GL_TEXTURE_2D)
            EndIf
    
            _glPopMatrix()
        Next
    EndFunc
    
    Func _InitDisplayLists()
        ; --- LISTE 1: TISCH ---
        $g_iListTable = _glGenLists(1)
        _glNewList($g_iListTable, $GL_COMPILE)
            _glColor3f(0.545, 0.27, 0.075)
            _DrawRect(0, 0, $iWidth, $iHeight)
            _glColor3f(0.0, 0.39, 0.0)
            _DrawRect($iBorder, $iBorder, $iWidth - 2*$iBorder, $iHeight - 2*$iBorder)
            _glColor3f(0.0, 0.0, 0.0)
            Local $iHoleR = 22
            _DrawCircle($iBorder - $iHoleR, $iBorder - $iHoleR, $iHoleR)
            _DrawCircle($iWidth - $iBorder - $iHoleR, $iBorder - $iHoleR, $iHoleR)
            _DrawCircle($iBorder - $iHoleR, $iHeight - $iBorder - $iHoleR, $iHoleR)
            _DrawCircle($iWidth - $iBorder - $iHoleR, $iHeight - $iBorder - $iHoleR, $iHoleR)
            _DrawCircle($iWidth/2 - $iHoleR, $iBorder - $iHoleR, $iHoleR)
            _DrawCircle($iWidth/2 - $iHoleR, $iHeight - $iBorder - $iHoleR, $iHoleR)
        _glEndList()
    
        ; --- LISTE 2: KUGEL (3D Sphäre) ---
    $g_iListSphere = _glGenLists(1)
    _glNewList($g_iListSphere, $GL_COMPILE)
        Local $iStacks = 48
        Local $iSlices = 48
        Local $r = $fBallRadius
        Local $PI = 3.1415926535897932
    
        For $i = 0 To $iStacks - 1
            Local $lat0 = $PI * (-0.5 + $i / $iStacks)
            Local $z0 = Sin($lat0) * $r
            Local $zr0 = Cos($lat0) * $r
    
            Local $lat1 = $PI * (-0.5 + ($i + 1) / $iStacks)
            Local $z1 = Sin($lat1) * $r
            Local $zr1 = Cos($lat1) * $r
    
            ; Zeichne jeden Ring als separate Quads (nicht als Strip)
            For $j = 0 To $iSlices - 1  ; WICHTIG: Bis iSlices-1, nicht iSlices!
                Local $lng0 = 2 * $PI * $j / $iSlices
                Local $lng1 = 2 * $PI * ($j + 1) / $iSlices
    
                Local $x0 = Cos($lng0)
                Local $y0 = Sin($lng0)
                Local $x1 = Cos($lng1)
                Local $y1 = Sin($lng1)
    
                Local $s0 = $j / $iSlices
                Local $s1 = ($j + 1) / $iSlices
                Local $t0 = $i / $iStacks
                Local $t1 = ($i + 1) / $iStacks
    
                ; Zeichne ein Quad (4 Vertices)
                _glBegin($GL_QUADS)
                    _glTexCoord2f($s0, $t0)
                    _glVertex3f($x0 * $zr0, $y0 * $zr0, $z0)
    
                    _glTexCoord2f($s1, $t0)
                    _glVertex3f($x1 * $zr0, $y1 * $zr0, $z0)
    
                    _glTexCoord2f($s1, $t1)
                    _glVertex3f($x1 * $zr1, $y1 * $zr1, $z1)
    
                    _glTexCoord2f($s0, $t1)
                    _glVertex3f($x0 * $zr1, $y0 * $zr1, $z1)
                _glEnd()
            Next
        Next
    _glEndList()
    EndFunc
    
    Func _DrawRect($x, $y, $w, $h)
        _glBegin($GL_QUADS)
        _glVertex2f($x, $y)
        _glVertex2f($x + $w, $y)
        _glVertex2f($x + $w, $y + $h)
        _glVertex2f($x, $y + $h)
        _glEnd()
    EndFunc
    
    Func _DrawCircle($x, $y, $r)
        Local $iSegments = 32
        _glBegin($GL_TRIANGLE_FAN)
        _glVertex2f($x + $r, $y + $r) ; Center
        For $i = 0 To $iSegments
            Local $fAngle = $i * 2.0 * 3.14159 / $iSegments
            _glVertex2f($x + $r + Cos($fAngle) * $r, $y + $r + Sin($fAngle) * $r)
        Next
        _glEnd()
    EndFunc
    
    Func _DrawCircleTextured($x, $y, $r)
        Local $iSegments = 32
        _glBegin($GL_TRIANGLE_FAN)
        _glTexCoord2f(0.5, 0.5)
        _glVertex2f($x + $r, $y + $r) ; Center
    
        For $i = 0 To $iSegments
            Local $fAngle = $i * 2.0 * 3.14159 / $iSegments
            Local $tx = 0.5 + 0.5 * Cos($fAngle)
            Local $ty = 0.5 + 0.5 * Sin($fAngle)
            _glTexCoord2f($tx, $ty)
            _glVertex2f($x + $r + Cos($fAngle) * $r, $y + $r + Sin($fAngle) * $r)
        Next
        _glEnd()
    EndFunc
    
    Func _LoadBallTextures()
        For $i = 0 To 15
            Local $sPath = $sFolder & "\" & $i & ".png"
    
            If FileExists($sPath) Then
                $aTextures[$i] = _LoadTexture($sPath)
            Else
                $aTextures[$i] = 0
            EndIf
        Next
    EndFunc
    
    Func _MakeSeamlessTexture($hBitmap, $iW, $iH)
        ; Erstelle eine Graphics-Oberfläche
        Local $hGraphics = _GDIPlus_ImageGetGraphicsContext($hBitmap)
        _GDIPlus_GraphicsSetInterpolationMode($hGraphics, 7)
    
        ; Kopiere die linken 5% der Textur an den rechten Rand (verwischt)
        Local $iEdgeWidth = Int($iW * 0.05)
    
        ; Zeichne die linke Kante an die rechte Position (überlappend)
        _GDIPlus_GraphicsDrawImageRectRect($hGraphics, $hBitmap, _
            0, 0, $iEdgeWidth, $iH, _  ; Source: linke Kante
            $iW - $iEdgeWidth, 0, $iEdgeWidth, $iH) ; Dest: rechte Kante
    
        _GDIPlus_GraphicsDispose($hGraphics)
    EndFunc
    
    Func _LoadTexture($sFile)
        Local $hImage = _GDIPlus_ImageLoadFromFile($sFile)
        If $hImage = 0 Then
            Return 0
        EndIf
    
        Local $iW = _GDIPlus_ImageGetWidth($hImage)
        Local $iH = _GDIPlus_ImageGetHeight($hImage)
        ConsoleWrite("  Original: " & $iW & "x" & $iH & @CRLF)
    
        Local $iTexW = _NextPowerOfTwo($iW)
        Local $iTexH = _NextPowerOfTwo($iH)
    
        ; SCHRITT 1: Erstelle temporäre Bitmap in Original-Größe
        Local $hTempBitmap = _GDIPlus_BitmapCreateFromScan0($iW, $iH, $GDIP_PXF32ARGB)
        Local $hTempGraphics = _GDIPlus_ImageGetGraphicsContext($hTempBitmap)
        _GDIPlus_GraphicsDrawImageRect($hTempGraphics, $hImage, 0, 0, $iW, $iH)
        _GDIPlus_GraphicsDispose($hTempGraphics)
        _GDIPlus_ImageDispose($hImage)
    
        ; SCHRITT 2: Mache die Textur nahtlos (Wrap die linke Kante zur rechten)
        Local $hGraphics2 = _GDIPlus_ImageGetGraphicsContext($hTempBitmap)
        Local $iWrapWidth = Int($iW * 0.1) ; 10% der Breite
    
        ; Verwende einen Brush mit Transparenz-Verlauf wäre ideal, aber wir machen es einfacher:
        ; Kopiere die linke Kante zur rechten Seite
        _GDIPlus_GraphicsDrawImageRectRect($hGraphics2, $hTempBitmap, 0, 0, $iWrapWidth, $iH, $iW - $iWrapWidth, 0, $iWrapWidth, $iH)
        _GDIPlus_GraphicsDispose($hGraphics2)
    
        ; SCHRITT 3: Skaliere auf Zweierpotenz-Größe
        Local $hBitmap = _GDIPlus_BitmapCreateFromScan0($iTexW, $iTexH, $GDIP_PXF32ARGB)
        Local $hGraphics = _GDIPlus_ImageGetGraphicsContext($hBitmap)
        _GDIPlus_GraphicsSetInterpolationMode($hGraphics, 7)
    
        ; Skaliere die jetzt nahtlose Textur
        _GDIPlus_GraphicsDrawImageRect($hGraphics, $hTempBitmap, 0, 0, $iTexW, $iTexH)
        _GDIPlus_GraphicsDispose($hGraphics)
        _GDIPlus_ImageDispose($hTempBitmap)
    
        Local $tBitmapData = _GDIPlus_BitmapLockBits($hBitmap, 0, 0, $iTexW, $iTexH, $GDIP_ILMREAD, $GDIP_PXF32ARGB)
        Local $pScan0 = DllStructGetData($tBitmapData, "Scan0")
        Local $iStride = DllStructGetData($tBitmapData, "Stride")
    
        Local $iDataSize = Abs($iStride) * $iTexH
        Local $tPixelData = DllStructCreate("byte[" & $iDataSize & "]")
        DllCall("msvcrt.dll", "ptr:cdecl", "memcpy", "ptr", DllStructGetPtr($tPixelData), "ptr", $pScan0, "ulong_ptr", $iDataSize)
    
        _GDIPlus_BitmapUnlockBits($hBitmap, $tBitmapData)
        _GDIPlus_ImageDispose($hBitmap)
    
        Local $tTexID = DllStructCreate("uint")
        DllCall($hOpenGL32, "none", "glGenTextures", "int", 1, "struct*", $tTexID)
        Local $iTexID = DllStructGetData($tTexID, 1)
    
        DllCall($hOpenGL32, "none", "glBindTexture", "uint", $GL_TEXTURE_2D, "uint", $iTexID)
        DllCall($hOpenGL32, "none", "glTexParameteri", "uint", $GL_TEXTURE_2D, "uint", $GL_TEXTURE_WRAP_S, "int", $GL_REPEAT)
        DllCall($hOpenGL32, "none", "glTexParameteri", "uint", $GL_TEXTURE_2D, "uint", $GL_TEXTURE_WRAP_T, "int", $GL_REPEAT)
        DllCall($hOpenGL32, "none", "glTexParameteri", "uint", $GL_TEXTURE_2D, "uint", $GL_TEXTURE_MAG_FILTER, "int", $GL_LINEAR)
        DllCall($hOpenGL32, "none", "glTexParameteri", "uint", $GL_TEXTURE_2D, "uint", $GL_TEXTURE_MIN_FILTER, "int", $GL_LINEAR)
    
        DllCall($hOpenGL32, "none", "glTexImage2D", "uint", $GL_TEXTURE_2D, "int", 0, "int", 4, "int", $iTexW, "int", $iTexH, "int", 0, "uint", 0x80E1, "uint", $GL_UNSIGNED_BYTE, "ptr", DllStructGetPtr($tPixelData))
    
        Local $iError = DllCall($hOpenGL32, "uint", "glGetError")[0]
        If $iError <> 0 Then
            ConsoleWrite("  OpenGL ERROR: " & $iError & @CRLF)
            Return 0
        Else
            ConsoleWrite("  Erfolgreich! Textur-ID: " & $iTexID & @CRLF)
        EndIf
    
        Return $iTexID
    EndFunc
    
    Func _NextPowerOfTwo($n)
        Local $power = 1
        While $power < $n
            $power *= 2
        WEnd
        Return $power
    EndFunc
    
    ; --- OPENGL WRAPPERS ---
    
    Func _SetupOpenGL($hWnd, $hDC)
        ; 1. Versuchen, MSAA (Multisampling Anti-Aliasing) zu aktivieren
        ; Dies sorgt fuer glatte Kanten an den Kugeln.
        Local $iPixelFormat = 0 ;_GetMultisamplePixelFormat()
    
        If $iPixelFormat <> 0 Then
            $g_bMSAA = True
        EndIf
    
        Local $tPFD = DllStructCreate("ushort Size;ushort Version;dword Flags;byte PixelType;byte ColorBits;byte RedBits;byte RedShift;byte GreenBits;byte GreenShift;byte BlueBits;byte BlueShift;byte AlphaBits;byte AlphaShift;byte AccumBits;byte AccumRedBits;byte AccumGreenBits;byte AccumBlueBits;byte AccumAlphaBits;byte DepthBits;byte StencilBits;byte AuxBuffers;byte LayerType;byte Reserved;dword LayerMask;dword VisibleMask;dword DamageMask")
        DllStructSetData($tPFD, "Size", DllStructGetSize($tPFD))
        DllStructSetData($tPFD, "Version", 1)
        DllStructSetData($tPFD, "Flags", BitOR($PFD_DRAW_TO_WINDOW, $PFD_SUPPORT_OPENGL, $PFD_DOUBLEBUFFER))
        DllStructSetData($tPFD, "PixelType", $PFD_TYPE_RGBA)
        DllStructSetData($tPFD, "ColorBits", 32)
        DllStructSetData($tPFD, "DepthBits", 24)
        DllStructSetData($tPFD, "LayerType", $PFD_MAIN_PLANE)
    
        If $iPixelFormat = 0 Then
            ; Fallback auf Standard-Format, falls MSAA nicht verfuegbar ist
            $iPixelFormat = DllCall($hGDI32, "int", "ChoosePixelFormat", "handle", $hDC, "struct*", $tPFD)[0]
        EndIf
    
        DllCall($hGDI32, "int", "SetPixelFormat", "handle", $hDC, "int", $iPixelFormat, "struct*", $tPFD)
    
        Local $hRC = DllCall($hOpenGL32, "handle", "wglCreateContext", "handle", $hDC)[0]
        _wglMakeCurrent($hDC, $hRC)
    
        Return $hRC
    EndFunc
    
    Func _GetMultisamplePixelFormat()
        ; Erstellt ein Dummy-Fenster & Kontext, um Zugriff auf erweiterte OpenGL-Funktionen (Extensions) zu erhalten.
        ; Dies ist notwendig, da wglChoosePixelFormatARB eine Extension-Funktion ist.
        Local $hDummyGui = GUICreate("Dummy", 10, 10, -1000, -1000)
        Local $hDummyDC = _WinAPI_GetDC($hDummyGui)
    
        Local $tPFD = DllStructCreate("ushort Size;ushort Version;dword Flags;byte PixelType;byte ColorBits;byte RedBits;byte RedShift;byte GreenBits;byte GreenShift;byte BlueBits;byte BlueShift;byte AlphaBits;byte AlphaShift;byte AccumBits;byte AccumRedBits;byte AccumGreenBits;byte AccumBlueBits;byte AccumAlphaBits;byte DepthBits;byte StencilBits;byte AuxBuffers;byte LayerType;byte Reserved;dword LayerMask;dword VisibleMask;dword DamageMask")
        DllStructSetData($tPFD, "Size", DllStructGetSize($tPFD))
        DllStructSetData($tPFD, "Version", 1)
        DllStructSetData($tPFD, "Flags", BitOR($PFD_DRAW_TO_WINDOW, $PFD_SUPPORT_OPENGL, $PFD_DOUBLEBUFFER))
        DllStructSetData($tPFD, "PixelType", $PFD_TYPE_RGBA)
        DllStructSetData($tPFD, "ColorBits", 32)
        DllStructSetData($tPFD, "DepthBits", 24)
        DllStructSetData($tPFD, "LayerType", $PFD_MAIN_PLANE)
    
        Local $iPF = DllCall($hGDI32, "int", "ChoosePixelFormat", "handle", $hDummyDC, "struct*", $tPFD)[0]
        DllCall($hGDI32, "int", "SetPixelFormat", "handle", $hDummyDC, "int", $iPF, "struct*", $tPFD)
        Local $hDummyRC = DllCall($hOpenGL32, "handle", "wglCreateContext", "handle", $hDummyDC)[0]
        _wglMakeCurrent($hDummyDC, $hDummyRC)
    
        ; Pruefen, ob wglChoosePixelFormatARB verfuegbar ist
        Local $pChoosePixelFormatARB = _wglGetProcAddress("wglChoosePixelFormatARB")
    
        Local $iRetFormat = 0
    
        If $pChoosePixelFormatARB Then
            ; Attribute fuer 4x MSAA definieren
            Local $tIntAttribs = DllStructCreate("int[20]")
            Local $pIntAttribs = DllStructGetPtr($tIntAttribs)
    
            ; Attribute fuellen
            Local $i = 1
            DllStructSetData($tIntAttribs, 1, 0x2001, $i) ; WGL_DRAW_TO_WINDOW_ARB
            DllStructSetData($tIntAttribs, 1, 1, $i+1)      ; GL_TRUE
            $i+=2
            DllStructSetData($tIntAttribs, 1, 0x2010, $i) ; WGL_SUPPORT_OPENGL_ARB
            DllStructSetData($tIntAttribs, 1, 1, $i+1)
            $i+=2
            DllStructSetData($tIntAttribs, 1, 0x2011, $i) ; WGL_DOUBLE_BUFFER_ARB
            DllStructSetData($tIntAttribs, 1, 1, $i+1)
            $i+=2
            DllStructSetData($tIntAttribs, 1, 0x2013, $i) ; WGL_PIXEL_TYPE_ARB
            DllStructSetData($tIntAttribs, 1, 0x202B, $i+1) ; WGL_TYPE_RGBA_ARB
            $i+=2
            DllStructSetData($tIntAttribs, 1, 0x2014, $i) ; WGL_COLOR_BITS_ARB
            DllStructSetData($tIntAttribs, 1, 32, $i+1)
            $i+=2
            DllStructSetData($tIntAttribs, 1, 0x2022, $i) ; WGL_DEPTH_BITS_ARB
            DllStructSetData($tIntAttribs, 1, 24, $i+1)
            $i+=2
            DllStructSetData($tIntAttribs, 1, 0x2041, $i) ; WGL_SAMPLE_BUFFERS_ARB
            DllStructSetData($tIntAttribs, 1, 1, $i+1)
            $i+=2
            DllStructSetData($tIntAttribs, 1, 0x2042, $i) ; WGL_SAMPLES_ARB
            DllStructSetData($tIntAttribs, 1, 4, $i+1)    ; 4x MSAA (4 Samples pro Pixel)
            $i+=2
            DllStructSetData($tIntAttribs, 1, 0, $i)      ; Ende
    
            Local $tFloatAttribs = DllStructCreate("float[2]") ; Leer
            DllStructSetData($tFloatAttribs, 1, 0, 1)
            DllStructSetData($tFloatAttribs, 1, 0, 2)
    
            Local $tPixelFormats = DllStructCreate("int[1]")
            Local $tNumFormats = DllStructCreate("uint")
    
            ; wglChoosePixelFormatARB aufrufen
            Local $aRet = DllCallAddress("int", $pChoosePixelFormatARB, "handle", $hDummyDC, "ptr", $pIntAttribs, "ptr", DllStructGetPtr($tFloatAttribs), "uint", 1, "ptr", DllStructGetPtr($tPixelFormats), "ptr", DllStructGetPtr($tNumFormats))
    
            If $aRet[0] And DllStructGetData($tNumFormats, 1) > 0 Then
                $iRetFormat = DllStructGetData($tPixelFormats, 1)
            EndIf
        EndIf
    
        ; Dummy aufraeumen
        _wglMakeCurrent(0, 0)
        _wglDeleteContext($hDummyRC)
        _WinAPI_ReleaseDC($hDummyGui, $hDummyDC)
        GUIDelete($hDummyGui)
    
        Return $iRetFormat
    EndFunc
    
    Func _wglGetProcAddress($proc)
        Local $aRet = DllCall($hOpenGL32, "ptr", "wglGetProcAddress", "str", $proc)
        Return $aRet[0]
    EndFunc
    
    Func _wglMakeCurrent($hDC, $hRC)
        DllCall($hOpenGL32, "int", "wglMakeCurrent", "handle", $hDC, "handle", $hRC)
    EndFunc
    
    Func _wglDeleteContext($hRC)
        DllCall($hOpenGL32, "int", "wglDeleteContext", "handle", $hRC)
    EndFunc
    
    Func _SwapBuffers($hDC)
        DllCall($hGDI32, "int", "SwapBuffers", "handle", $hDC)
    EndFunc
    
    Func _glClearColor($r, $g, $b, $a)
        DllCall($hOpenGL32, "none", "glClearColor", "float", $r, "float", $g, "float", $b, "float", $a)
    EndFunc
    
    Func _glClear($mask)
        DllCall($hOpenGL32, "none", "glClear", "uint", $mask)
    EndFunc
    
    Func _glViewport($x, $y, $w, $h)
        DllCall($hOpenGL32, "none", "glViewport", "int", $x, "int", $y, "int", $w, "int", $h)
    EndFunc
    
    Func _glMatrixMode($mode)
        DllCall($hOpenGL32, "none", "glMatrixMode", "uint", $mode)
    EndFunc
    
    Func _glLoadIdentity()
        DllCall($hOpenGL32, "none", "glLoadIdentity")
    EndFunc
    
    Func _glOrtho($l, $r, $b, $t, $n, $f)
        DllCall($hOpenGL32, "none", "glOrtho", "double", $l, "double", $r, "double", $b, "double", $t, "double", $n, "double", $f)
    EndFunc
    
    Func _glEnable($cap)
        DllCall($hOpenGL32, "none", "glEnable", "uint", $cap)
    EndFunc
    
    Func _glDisable($cap)
        DllCall($hOpenGL32, "none", "glDisable", "uint", $cap)
    EndFunc
    
    Func _glBlendFunc($s, $d)
        DllCall($hOpenGL32, "none", "glBlendFunc", "uint", $s, "uint", $d)
    EndFunc
    
    Func _glColor3f($r, $g, $b)
        DllCall($hOpenGL32, "none", "glColor3f", "float", $r, "float", $g, "float", $b)
    EndFunc
    
    Func _glBegin($mode)
        DllCall($hOpenGL32, "none", "glBegin", "uint", $mode)
    EndFunc
    
    Func _glEnd()
        DllCall($hOpenGL32, "none", "glEnd")
    EndFunc
    
    Func _glVertex2f($x, $y)
        DllCall($hOpenGL32, "none", "glVertex2f", "float", $x, "float", $y)
    EndFunc
    
    Func _glTexCoord2f($s, $t)
        DllCall($hOpenGL32, "none", "glTexCoord2f", "float", $s, "float", $t)
    EndFunc
    
    Func _glGenTextures()
        Local $tTextures = DllStructCreate("uint")
        DllCall($hOpenGL32, "none", "glGenTextures", "int", 1, "struct*", $tTextures)
        Return DllStructGetData($tTextures, 1)
    EndFunc
    
    Func _glBindTexture($target, $texture)
        DllCall($hOpenGL32, "none", "glBindTexture", "uint", $target, "uint", $texture)
    EndFunc
    
    Func _glTexParameteri($target, $pname, $param)
        DllCall($hOpenGL32, "none", "glTexParameteri", "uint", $target, "uint", $pname, "int", $param)
    EndFunc
    
    Func _glTexImage2D($target, $level, $internalformat, $width, $height, $border, $format, $type, $pixels)
        DllCall($hOpenGL32, "none", "glTexImage2D", "uint", $target, "int", $level, "int", $internalformat, "int", $width, "int", $height, "int", $border, "uint", $format, "uint", $type, "ptr", $pixels)
    EndFunc
    
    Func _glTranslatef($x, $y, $z)
        DllCall($hOpenGL32, "none", "glTranslatef", "float", $x, "float", $y, "float", $z)
    EndFunc
    
    Func _glScalef($x, $y, $z)
        DllCall($hOpenGL32, "none", "glScalef", "float", $x, "float", $y, "float", $z)
    EndFunc
    
    Func _glMultMatrixf($m)
        DllCall($hOpenGL32, "none", "glMultMatrixf", "ptr", $m)
    EndFunc
    
    Func _glVertex3f($x, $y, $z)
        DllCall($hOpenGL32, "none", "glVertex3f", "float", $x, "float", $y, "float", $z)
    EndFunc
    
    Func _glGetFloatv($pname, $params)
        DllCall($hOpenGL32, "none", "glGetFloatv", "uint", $pname, "ptr", $params)
    EndFunc
    
    Func _glLoadMatrixf($m)
        DllCall($hOpenGL32, "none", "glLoadMatrixf", "ptr", $m)
    EndFunc
    
    Func _glRotatef($angle, $x, $y, $z)
        DllCall($hOpenGL32, "none", "glRotatef", "float", $angle, "float", $x, "float", $y, "float", $z)
    EndFunc
    
    Func _glGenLists($range)
        Local $aRet = DllCall($hOpenGL32, "uint", "glGenLists", "int", $range)
        Return $aRet[0]
    EndFunc
    
    Func _glNewList($list, $mode)
        DllCall($hOpenGL32, "none", "glNewList", "uint", $list, "uint", $mode)
    EndFunc
    
    Func _glEndList()
        DllCall($hOpenGL32, "none", "glEndList")
    EndFunc
    
    Func _glCallList($list)
        DllCall($hOpenGL32, "none", "glCallList", "uint", $list)
    EndFunc
    
    Func _glPushMatrix()
        DllCall($hOpenGL32, "none", "glPushMatrix")
    EndFunc
    
    Func _glPopMatrix()
        DllCall($hOpenGL32, "none", "glPopMatrix")
    EndFunc
    
    Func _glHint($target, $mode)
        DllCall($hOpenGL32, "none", "glHint", "uint", $target, "uint", $mode)
    EndFunc
    
    ; --- PHYSIK  ---
    Func _ResetTable()
        $aBalls[0][0] = $iWidth * 0.25
        $aBalls[0][1] = $iHeight / 2
        Local $fChaos = Random(-0.5, 0.5)
        $aBalls[0][2] = 35
        $aBalls[0][3] = $fChaos
        $aBalls[0][5] = True
        $aBalls[0][6] = 0
        $aBalls[0][7] = 0
    
        Local $fStartX = $iWidth * 0.75
        Local $fStartY = $iHeight / 2
        Local $fD = $fBallRadius * 2 + 1
    
        Local $iBallIdx = 1
        For $col = 0 To 4
            For $row = 0 To $col
                If $iBallIdx >= $iMaxBalls Then ExitLoop
                Local $fX = $fStartX + ($col * ($fD * 0.866))
                Local $fY = ($fStartY - ($col * $fD / 2)) + ($row * $fD)
                $aBalls[$iBallIdx][0] = $fX
                $aBalls[$iBallIdx][1] = $fY
                $aBalls[$iBallIdx][2] = 0
                $aBalls[$iBallIdx][3] = 0
                $aBalls[$iBallIdx][5] = True
                $aBalls[$iBallIdx][6] = 0
                $aBalls[$iBallIdx][7] = 0
                $iBallIdx += 1
            Next
        Next
    EndFunc
    
    Func _InitBallMatrices()
        For $i = 0 To $iMaxBalls - 1
            $aBallMatrices[$i] = DllStructCreate("float[16]")
            ; Identitaetsmatrix setzen (Keine Rotation)
            Local $pMatrix = DllStructGetPtr($aBallMatrices[$i])
            _glLoadIdentity()
            _glGetFloatv($GL_MODELVIEW_MATRIX, $pMatrix)
        Next
    EndFunc
    
    Func _UpdateRotations()
        For $i = 0 To $iMaxBalls - 1
            If Not $aBalls[$i][5] Then ContinueLoop
    
            Local $vx = $aBalls[$i][2]
            Local $vy = $aBalls[$i][3]
            Local $fSpeed = Sqrt($vx*$vx + $vy*$vy)
    
            If $fSpeed > 0.01 Then
                ; Rotationsachse berechnen:
                ; Die Achse steht senkrecht zur Bewegungsrichtung.
                ; Bei Bewegung (vx, vy) ist die Senkrechte (-vy, vx).
                Local $rx = -$vy
                Local $ry = $vx
    
                ; Rotationswinkel berechnen:
                ; Winkel = Zurueckgelegter Weg / Radius (in Radiant)
                ; Weg pro Frame entspricht der Geschwindigkeit ($fSpeed).
                ; Umrechnung in Grad: * (180 / PI)
                Local $fAngle = ($fSpeed / $fBallRadius) * (180.0 / 3.1415926)
    
                ; Matrix Update (Die Magie der 3D-Rotation)
                _glMatrixMode($GL_MODELVIEW)
                _glLoadIdentity()
    
                ; 1. Neue Rotation anwenden (um die Welt-Achsen)
                ; Wir rotieren zuerst um die berechnete Achse.
                _glRotatef($fAngle, $rx, $ry, 0.0)
    
                ; 2. Alte Rotation anwenden
                ; Dann multiplizieren wir die bestehende Rotation der Kugel dazu.
                ; Dies akkumuliert die Drehungen korrekt, sodass die Kugel "weiterrollt"
                ; anstatt sich nur lokal zu drehen.
                Local $pMatrix = DllStructGetPtr($aBallMatrices[$i])
                _glMultMatrixf($pMatrix)
    
                ; 3. Ergebnis speichern
                ; Die kombinierte Matrix wird fuer den naechsten Frame gespeichert.
                _glGetFloatv($GL_MODELVIEW_MATRIX, $pMatrix)
            EndIf
        Next
    EndFunc
    
    Func _UpdatePhysics()
        Local $bAnyMovement = False
        Local $fSpeedThreshold = 0.08
    
        For $i = 0 To $iMaxBalls - 1
            If Not $aBalls[$i][5] Then ContinueLoop
            Local $vx = $aBalls[$i][2]
            Local $vy = $aBalls[$i][3]
            $aBalls[$i][0] += $vx
            $aBalls[$i][1] += $vy
            $vx *= $fFriction
            $vy *= $fFriction
            Local $fSpeed = Sqrt($vx*$vx + $vy*$vy)
            If $fSpeed > $fSpeedThreshold Then
                $bAnyMovement = True
                $aBalls[$i][6] += $vx
                $aBalls[$i][7] += $vy
            Else
                $vx = 0
                $vy = 0
            EndIf
            $aBalls[$i][2] = $vx
            $aBalls[$i][3] = $vy
    
            If $aBalls[$i][0] - $fBallRadius < $iBorder Then
                $aBalls[$i][0] = $iBorder + $fBallRadius
                $aBalls[$i][2] *= -1
            ElseIf $aBalls[$i][0] + $fBallRadius > $iWidth - $iBorder Then
                $aBalls[$i][0] = $iWidth - $iBorder - $fBallRadius
                $aBalls[$i][2] *= -1
            EndIf
            If $aBalls[$i][1] - $fBallRadius < $iBorder Then
                $aBalls[$i][1] = $iBorder + $fBallRadius
                $aBalls[$i][3] *= -1
            ElseIf $aBalls[$i][1] + $fBallRadius > $iHeight - $iBorder Then
                $aBalls[$i][1] = $iHeight - $iBorder - $fBallRadius
                $aBalls[$i][3] *= -1
            EndIf
    
            For $j = $i + 1 To $iMaxBalls - 1
                 If $aBalls[$j][5] Then _CheckCollision($i, $j)
            Next
        Next
        Return $bAnyMovement
    EndFunc
    
    Func _CheckCollision($i1, $i2)
        Local $dx = $aBalls[$i2][0] - $aBalls[$i1][0]
        Local $dy = $aBalls[$i2][1] - $aBalls[$i1][1]
        Local $distSq = $dx*$dx + $dy*$dy
        Local $minDist = $fBallRadius * 2
        If $distSq < ($minDist * $minDist) Then
            Local $dist = Sqrt($distSq)
            If $dist = 0 Then $dist = 0.01
            Local $overlap = ($minDist - $dist) / 2
            Local $nx = $dx / $dist
            Local $ny = $dy / $dist
            $aBalls[$i1][0] -= $nx * $overlap
            $aBalls[$i1][1] -= $ny * $overlap
            $aBalls[$i2][0] += $nx * $overlap
            $aBalls[$i2][1] += $ny * $overlap
            Local $tx = -$ny
            Local $ty = $nx
            Local $dpTan1 = $aBalls[$i1][2] * $tx + $aBalls[$i1][3] * $ty
            Local $dpTan2 = $aBalls[$i2][2] * $tx + $aBalls[$i2][3] * $ty
            Local $dpNorm1 = $aBalls[$i1][2] * $nx + $aBalls[$i1][3] * $ny
            Local $dpNorm2 = $aBalls[$i2][2] * $nx + $aBalls[$i2][3] * $ny
            Local $v1n = $dpNorm2
            Local $v2n = $dpNorm1
            $aBalls[$i1][2] = $tx * $dpTan1 + $nx * $v1n
            $aBalls[$i1][3] = $ty * $dpTan1 + $ny * $v1n
            $aBalls[$i2][2] = $tx * $dpTan2 + $nx * $v2n
            $aBalls[$i2][3] = $ty * $dpTan2 + $ny * $v2n
        EndIf
    EndFunc
    Alles anzeigen

    Ohne die DLL in ScriptDir sehe ich nur ein grünes Rechteck, wie oben gezeigt. Scheint an der OpenGL32.dll v10 (Win11) zu liegen...

  • Rollende Kugel mit Textur

    • UEZ
    • 23. November 2025 um 13:06

    Gleiches Resultat:

    Code
    > _SetupOpenGL: Start
    > MSAA Enabled (Format Index: 39)
    > Selected PixelFormat: 39
    > SetPixelFormat Result: 1
    > wglCreateContext Result: 0x00020000
    > wglMakeCurrent Result: 1
    --- OpenGL Info ---
    Version:  4.6.0 - Build 32.0.101.6881
    Vendor:   Intel
    Renderer: Intel(R) Graphics

    Vielleicht hängt's an den Treibern...

  • Rollende Kugel mit Textur

    • UEZ
    • 22. November 2025 um 23:15

    So sieht's bei mir aus:


    Keine Kugeln.

    OS: Win11 24H2

    Deine Version sieht gut aus. :thumbup:. Ich habe mit WebP Anim die Animationsdatei erstellt.

    Bilder

    • image.webp
      • 3,84 kB
      • 995 × 625
  • Rollende Kugel mit Textur

    • UEZ
    • 22. November 2025 um 19:32

    Douky leider sehe ich keine Kugeln, nur den "Tisch". Die Texturen werden geladen und eine ID zurück gegeben.

    Idee?

  • _GDIPlus_ImageCalcDif

    • UEZ
    • 5. November 2025 um 16:38

    Ich habe den Code oben aktualisiert. Mode 4 sollte auch so ähnliche Resultate liefern.

    Um diesen Thread nicht weiter zu missbrauchen, kann jemand einen neue Thread eröffnen, um den Code weiter zu behandeln, falls erwünscht, ansonsten mache ich jetzt einen Punkt zu meinem Code.

  • _GDIPlus_ImageCalcDif

    • UEZ
    • 4. November 2025 um 22:24

    Kannst du mal ein Beispiel posten, wie es mit Farbe aussieht?

  • _GDIPlus_ImageCalcDif

    • UEZ
    • 4. November 2025 um 00:06

    Passt gut hier rein - Differenz als Graustufe, wobei weiß = keine Differenz, je dunkler, desto größer die Differenz:

    AutoIt
    ;Coded by UEZ build 2025-11-05
    #include <Array.au3>
    #include <GDIPlus.au3>
    #include <MsgBoxConstants.au3>
    
    _GDIPlus_Startup()
    Global $hImage1, $hImage2
    Global $sImages = FileOpenDialog("Select 2 images", "", "Image (*.bmp;*.jpg;*.png;*.gif)", $FD_MULTISELECT)
    If @error Then _Exit("Nothing selected")
    Global $aFiles = StringSplit($sImages, "|", 2)
    If (UBound($aFiles) < 3) Then _Exit("Select at least 2 images")
    $hImage1 = _GDIPlus_ImageLoadFromFile($aFiles[1])
    If @error Then _Exit("Unable to load " & $aFiles[1])
    $hImage2 = _GDIPlus_ImageLoadFromFile($aFiles[2])
    If @error Then _Exit("Unable to load " & $aFiles[2])
    If (_GDIPlus_ImageGetWidth($hImage1) <> _GDIPlus_ImageGetWidth($hImage2)) Then _Exit("Width of both images are different")
    If (_GDIPlus_ImageGetHeight($hImage1) <> _GDIPlus_ImageGetHeight($hImage2)) Then _Exit("Height of both images are different")
    
    Global $iMode = 4
    Global $aDiff = _GDIPlus_ImageCompare($hImage1, $hImage2, $iMode)
    
    If $iMode = 1 Then Exit MsgBox($MB_SYSTEMMODAL, "Compared", "Equal: " & $aDiff & " / " & @extended & " ms")
    
    If $iMode = 2 Then
    	Global $iChk = MsgBox(BitOR($MB_SYSTEMMODAL, $MB_YESNO), "Information", "Found " & Round((UBound($aDiff) - 1) / ($aDiff[0][1] * $aDiff[0][2]) * 100, 2) & " % differences in " & Round($aDiff[0][0], 2) & " ms." & _
    							@CRLF & @CRLF & _
    							"Display the array with information")
    	If ($iChk = 6) Then _ArrayDisplay($aDiff, "Differences", Default, Default, Default, "Runtime / Coordinate (x,y)|Image1 Color|Image2 Color")
    	_Exit()
    	Exit
    EndIf
    ConsoleWrite($aDiff & " ms" & @CRLF)
    _Exit()
    
    Func _GDIPlus_ImageCompare($hImage1, $hImage2, $iMode = 1)
    	Local Const $iW = _GDIPlus_ImageGetWidth($hImage1), $iH = _GDIPlus_ImageGetHeight($hImage1)
    	If ($iW <> _GDIPlus_ImageGetWidth($hImage2)) Then Return SetError(1, 0, 0)
    	If ($iH <> _GDIPlus_ImageGetHeight($hImage2)) Then Return SetError(2, 0, 0)
    	Local $t = TimerInit()
    	Local $tBitmapData1 = _GDIPlus_BitmapLockBits($hImage1, 0, 0, $iW, $iH, $GDIP_ILMREAD, $GDIP_PXF32ARGB)
    	Local $tBitmapData2 = _GDIPlus_BitmapLockBits($hImage2, 0, 0, $iW, $iH, $GDIP_ILMREAD, $GDIP_PXF32ARGB)
    
        Local $pScan1 = DllStructGetData($tBitmapData1, "Scan0")
        Local $tPixel1 = DllStructCreate("uint[" & $iW * $iH & "];", $pScan1)
    	Local $iStride = Abs(DllStructGetData($tBitmapData1, "Stride"))
    
        Local $pScan2 = DllStructGetData($tBitmapData2, "Scan0")
        Local $tPixel2 = DllStructCreate("uint[" & $iW * $iH & "];", $pScan2)
    
    	Switch $iMode
    		Case 1
    			$iResult = DllCall("msvcrt.dll", "int:cdecl", "memcmp", "ptr", $pScan1, "ptr", $pScan2, "uint", DllStructGetSize($tPixel1))[0]
    			_GDIPlus_BitmapUnlockBits($hImage1, $tBitmapData1)
    			_GDIPlus_BitmapUnlockBits($hImage2, $tBitmapData2)
    			Return SetError(0, Int(TimerDiff($t)), $iResult = 0)
    		Case 2
    			If ($iW * $iH + 1) * 3 > 16 * 1024 ^ 2 Then Return SetError(3, 0, 0)
    			Local $iX, $iY, $iRowOffset, $iPixel1, $iPixel2, $c = 1, $aDiff[$iW * $iH + 1][3]
    			For $iY = 0 To $iH - 1
    				$iRowOffset = $iY * $iW + 1
    				For $iX = 0 To $iW - 1
    					$iPixel1 = DllStructGetData($tPixel1, 1, $iRowOffset + $iX) ;get pixel color
    					$iPixel2 = DllStructGetData($tPixel2, 1, $iRowOffset + $iX) ;get pixel color
    					If $iPixel1 <> $iPixel2 Then
    						$aDiff[$c][0] = $iX & ", " & $iY
    						$aDiff[$c][1] = "0x" & Hex($iPixel1, 8)
    						$aDiff[$c][2] = "0x" & Hex($iPixel2, 8)
    						$c += 1
    					EndIf
    				Next
    			Next
    			_GDIPlus_BitmapUnlockBits($hImage1, $tBitmapData1)
    			_GDIPlus_BitmapUnlockBits($hImage2, $tBitmapData2)
    			$aDiff[0][0] = TimerDiff($t)
    			$aDiff[0][1] = $iW
    			$aDiff[0][2] = $iH
    			ReDim $aDiff[$c][3]
    			Return $aDiff
    		Case 3 ;Graustufen
    			If ($iW * $iH + 1) * 3 > 16 * 1024 ^ 2 Then Return SetError(4, 0, 0)
    			Local $stride = $iW * 4
    			Local $tDestBmp = DllStructCreate("uint color[" & $stride * $iH & "];")
    			Local $hBitmapDiff = _GDIPlus_BitmapCreateFromScan0($iW, $iH, $GDIP_PXF32ARGB, $stride, DllStructGetPtr($tDestBmp))
    			If @error Or Not $hBitmapDiff Then
    				_GDIPlus_BitmapUnlockBits($hImage1, $tBitmapData1)
    				_GDIPlus_BitmapUnlockBits($hImage2, $tBitmapData2)
    				Return SetError(5, @error, 0)
    			EndIf
    			Local $iX, $iY, $iRowOffset, $iPixel1, $iPixel2, $c = 1, $aDiff[$iW * $iH + 1][3], $a1, $a2, $r1, $r2, $g1, $g2, $b1, $b2, $dist3D, $dist4D, $alpha, $gamma = 0.1
    			For $iY = 0 To $iH - 1
    				$iRowOffset = $iY * $iW + 1
    				For $iX = 0 To $iW - 1
    					$iPixel1 = DllStructGetData($tPixel1, 1, $iRowOffset + $iX) ;get pixel color
    					$iPixel2 = DllStructGetData($tPixel2, 1, $iRowOffset + $iX) ;get pixel color
    					$a1 = BitShift(BitAND($iPixel1, 0xFF000000), 24)
    					$a2 = BitShift(BitAND($iPixel2, 0xFF000000), 24)
    					$r1 = BitShift(BitAND($iPixel1, 0x00FF0000), 16)
    					$r2 = BitShift(BitAND($iPixel2, 0x00FF0000), 16)
    					$g1 = BitShift(BitAND($iPixel1, 0x0000FF00), 8)
    					$g2 = BitShift(BitAND($iPixel2, 0x0000FF00), 8)
    					$b1 = BitAND($iPixel1, 0x000000FF)
    					$b2 = BitAND($iPixel2, 0x000000FF)
    
    					;euklidische Distanz in 4D
    ;~ 					$dist4D = Sqrt(($a1 - $a2) * ($a1 - $a2) + ($r1 - $r2) * ($r1 - $r2) + ($g1 - $g2) * ($g1 - $g2) + ($b1 - $b2) * ($b1 - $b2))
    ;~ 					$tDestBmp.color($iRowOffset + $iX) = BitOR(0xFF000000, BitXOR(BitShift($dist4D, -16), BitShift($dist4D, -8), $dist4D, 0xFFFFFF))
    
    					;Alpha als Gewichtung der RGB-Distanz
    					$dist3D = Sqrt(($r1 - $r2) * ($r1 - $r2) + ($g1 - $g2) * ($g1 - $g2) + ($b1 - $b2) * ($b1 - $b2))
    
    					$alpha = Int(($a1 + $a2) / 2)
    					$dist3D = 255 - Int($dist3D / 441.67295593 * 255) ;Sqr(3 * 255^2) = 441.67295593
    
    					$tDestBmp.color($iRowOffset + $iX) = BitOR(BitShift($alpha, -24), BitShift($dist3D, -16), BitShift($dist3D, -8), $dist3D)
    
    ;~ 					$alpha = ($a1 + $a2) / 510 ;
    ;~ 					$dist3D = Int(($dist3D / 441.67295593) * 255 * $alpha)
    ;~ 					$tDestBmp.color($iRowOffset + $iX) = BitOR(0xFF000000, BitShift($dist3D, -16), BitShift($dist3D, -8), $dist3D)
    
    				Next
    			Next
    			_GDIPlus_ImageSaveToFile($hBitmapDiff, @ScriptDir & "\ImageDiff.png")
    			_GDIPlus_BitmapUnlockBits($hImage1, $tBitmapData1)
    			_GDIPlus_BitmapUnlockBits($hImage2, $tBitmapData2)
    			_GDIPlus_ImageDispose($hBitmapDiff)
    			Return TimerDiff($t)
    		Case 4 ;Graustufen mit Auto-Kontrast
    			If ($iW * $iH + 1) * 3 > 16 * 1024 ^ 2 Then Return SetError(6, 0, 0)
    			Local $stride = $iW * 4
    			Local $tDestBmp = DllStructCreate("uint color[" & $stride * $iH & "];")
    			Local $hBitmapDiff = _GDIPlus_BitmapCreateFromScan0($iW, $iH, $GDIP_PXF32ARGB, $stride, DllStructGetPtr($tDestBmp))
    			If @error Or Not $hBitmapDiff Then
    				_GDIPlus_BitmapUnlockBits($hImage1, $tBitmapData1)
    				_GDIPlus_BitmapUnlockBits($hImage2, $tBitmapData2)
    				Return SetError(6, @error, 0)
    			EndIf
    
    			Local $iX, $iY, $iRowOffset, $iPixel1, $iPixel2, $r1, $r2, $g1, $g2, $b1, $b2, $dist3D
    			Local $minDist = 999999, $maxDist = 0
    			Local $aDist[$iW * $iH + 1]
    
    			;Distanzen berechnen und Min/Max finden
    			For $iY = 0 To $iH - 1
    				$iRowOffset = $iY * $iW + 1
    				For $iX = 0 To $iW - 1
    					$iPixel1 = DllStructGetData($tPixel1, 1, $iRowOffset + $iX)
    					$iPixel2 = DllStructGetData($tPixel2, 1, $iRowOffset + $iX)
    					$r1 = BitShift(BitAND($iPixel1, 0x00FF0000), 16)
    					$r2 = BitShift(BitAND($iPixel2, 0x00FF0000), 16)
    					$g1 = BitShift(BitAND($iPixel1, 0x0000FF00), 8)
    					$g2 = BitShift(BitAND($iPixel2, 0x0000FF00), 8)
    					$b1 = BitAND($iPixel1, 0x000000FF)
    					$b2 = BitAND($iPixel2, 0x000000FF)
    
    					$dist3D = Sqrt(($r1 - $r2) * ($r1 - $r2) + ($g1 - $g2) * ($g1 - $g2) + ($b1 - $b2) * ($b1 - $b2))
    					$aDist[$iRowOffset + $iX] = $dist3D
    
    					If $dist3D < $minDist Then $minDist = $dist3D
    					If $dist3D > $maxDist Then $maxDist = $dist3D
    				Next
    			Next
    
    			Local $range = $maxDist - $minDist
    			If $range < 0.001 Then $range = 1  ;Division durch 0 verhindern (Bilder identisch)
    
    			;Normalisieren
    			Local $a1, $a2, $alpha
    			For $iY = 0 To $iH - 1
    				$iRowOffset = $iY * $iW + 1
    				For $iX = 0 To $iW - 1
    					$iPixel1 = DllStructGetData($tPixel1, 1, $iRowOffset + $iX)
    					$iPixel2 = DllStructGetData($tPixel2, 1, $iRowOffset + $iX)
    					$a1 = BitShift(BitAND($iPixel1, 0xFF000000), 24)
    					$a2 = BitShift(BitAND($iPixel2, 0xFF000000), 24)
    					$alpha = Int(($a1 + $a2) / 2)
    
    					; Kontrast-Stretch: voller Bereich 0-255
    					$dist3D = 255 - Int((($aDist[$iRowOffset + $iX] - $minDist) / $range) * 255)
    
    					$tDestBmp.color($iRowOffset + $iX) = BitOR(BitShift($alpha, -24), BitShift($dist3D, -16), BitShift($dist3D, -8), $dist3D)
    				Next
    			Next
    
    			_GDIPlus_ImageSaveToFile($hBitmapDiff, @ScriptDir & "\ImageDiff.png")
    			_GDIPlus_BitmapUnlockBits($hImage1, $tBitmapData1)
    			_GDIPlus_BitmapUnlockBits($hImage2, $tBitmapData2)
    			_GDIPlus_ImageDispose($hBitmapDiff)
    			Return TimerDiff($t)
    
    		Case 5 ;direkte Differenz RGBA
    			If ($iW * $iH + 1) * 3 > 16 * 1024 ^ 2 Then Return SetError(7, 0, 0)
    			Local $stride = $iW * 4
    			Local $tDestBmp = DllStructCreate("uint color[" & $stride * $iH & "];")
    			Local $hBitmapDiff = _GDIPlus_BitmapCreateFromScan0($iW, $iH, $GDIP_PXF32ARGB, $stride, DllStructGetPtr($tDestBmp))
    			If @error Or Not $hBitmapDiff Then
    				_GDIPlus_BitmapUnlockBits($hImage1, $tBitmapData1)
    				_GDIPlus_BitmapUnlockBits($hImage2, $tBitmapData2)
    				Return SetError(8, @error, 0)
    			EndIf
    			Local $iX, $iY, $iRowOffset, $iPixel1, $iPixel2, $c = 1, $aDiff[$iW * $iH + 1][3], $a1, $a2, $r1, $r2, $g1, $g2, $b1, $b2, $dr, $dg, $db, $rDiff, $gDiff, $bDiff, $alpha
    			For $iY = 0 To $iH - 1
    				$iRowOffset = $iY * $iW + 1
    				For $iX = 0 To $iW - 1
    					$iPixel1 = DllStructGetData($tPixel1, 1, $iRowOffset + $iX) ;get pixel color
    					$iPixel2 = DllStructGetData($tPixel2, 1, $iRowOffset + $iX) ;get pixel color
    					$a1 = BitShift(BitAND($iPixel1, 0xFF000000), 24)
    					$a2 = BitShift(BitAND($iPixel2, 0xFF000000), 24)
    					$r1 = BitShift(BitAND($iPixel1, 0x00FF0000), 16)
    					$r2 = BitShift(BitAND($iPixel2, 0x00FF0000), 16)
    					$g1 = BitShift(BitAND($iPixel1, 0x0000FF00), 8)
    					$g2 = BitShift(BitAND($iPixel2, 0x0000FF00), 8)
    					$b1 = BitAND($iPixel1, 0x000000FF)
    					$b2 = BitAND($iPixel2, 0x000000FF)
    
    					$dr = Abs($r1 - $r2)
    					$dg = Abs($g1 - $g2)
    					$db = Abs($b1 - $b2)
    					$alpha = Int(($a1 + $a2) / 2)
    					$tDestBmp.color($iRowOffset + $iX) = BitOR(BitShift($alpha, -24), BitShift($dr, -16), BitShift($dg, -8), $db)
    				Next
    			Next
    			_GDIPlus_ImageSaveToFile($hBitmapDiff, @ScriptDir & "\ImageDiff.png")
    			_GDIPlus_BitmapUnlockBits($hImage1, $tBitmapData1)
    			_GDIPlus_BitmapUnlockBits($hImage2, $tBitmapData2)
    			_GDIPlus_ImageDispose($hBitmapDiff)
    			Return TimerDiff($t)
    
    		Case 6 ;Heatmap
    			If ($iW * $iH + 1) * 3 > 16 * 1024 ^ 2 Then Return SetError(9, 0, 0)
    			Local $stride = $iW * 4
    			Local $tDestBmp = DllStructCreate("uint color[" & $stride * $iH & "];")
    			Local $hBitmapDiff = _GDIPlus_BitmapCreateFromScan0($iW, $iH, $GDIP_PXF32ARGB, $stride, DllStructGetPtr($tDestBmp))
    			If @error Or Not $hBitmapDiff Then
    				_GDIPlus_BitmapUnlockBits($hImage1, $tBitmapData1)
    				_GDIPlus_BitmapUnlockBits($hImage2, $tBitmapData2)
    				Return SetError(10, @error, 0)
    			EndIf
    			Local $iX, $iY, $iRowOffset, $iPixel1, $iPixel2, $a1, $a2, $r1, $r2, $g1, $g2, $b1, $b2, $dr, $dg, $db, $alpha, $totalDiff, $heatR, $heatG, $heatB
    			For $iY = 0 To $iH - 1
    				$iRowOffset = $iY * $iW + 1
    				For $iX = 0 To $iW - 1
    					$iPixel1 = DllStructGetData($tPixel1, 1, $iRowOffset + $iX)
    					$iPixel2 = DllStructGetData($tPixel2, 1, $iRowOffset + $iX)
    					$a1 = BitShift(BitAND($iPixel1, 0xFF000000), 24)
    					$a2 = BitShift(BitAND($iPixel2, 0xFF000000), 24)
    					$r1 = BitShift(BitAND($iPixel1, 0x00FF0000), 16)
    					$r2 = BitShift(BitAND($iPixel2, 0x00FF0000), 16)
    					$g1 = BitShift(BitAND($iPixel1, 0x0000FF00), 8)
    					$g2 = BitShift(BitAND($iPixel2, 0x0000FF00), 8)
    					$b1 = BitAND($iPixel1, 0x000000FF)
    					$b2 = BitAND($iPixel2, 0x000000FF)
    
    					$dr = Abs($r1 - $r2)
    					$dg = Abs($g1 - $g2)
    					$db = Abs($b1 - $b2)
    					$alpha = Int(($a1 + $a2) / 2)
    
    					$totalDiff = ($dr + $dg + $db) / 3
    					If $totalDiff < 64 Then ;Blau -> Cyan (0-63)
    						$heatR = 0
    						$heatG = Int($totalDiff * 4)
    						$heatB = 255
    					ElseIf $totalDiff < 128 Then ;Cyan -> Grün (64-127)
    						$heatR = 0
    						$heatG = 255
    						$heatB = Int(255 - ($totalDiff - 64) * 4)
    					ElseIf $totalDiff < 192 Then ;Grün -> Gelb (128-191)
    						$heatR = Int(($totalDiff - 128) * 4)
    						$heatG = 255
    						$heatB = 0
    					Else ;Gelb -> Rot (192-255)
    						$heatR = 255
    						$heatG = Int(255 - ($totalDiff - 192) * 4)
    						$heatB = 0
    					EndIf
    
    					$tDestBmp.color($iRowOffset + $iX) = BitOR(BitShift($alpha, -24), BitShift($heatR, -16), BitShift($heatG, -8), $heatB)
    				Next
    			Next
    			_GDIPlus_ImageSaveToFile($hBitmapDiff, @ScriptDir & "\ImageDiff.png")
    			_GDIPlus_BitmapUnlockBits($hImage1, $tBitmapData1)
    			_GDIPlus_BitmapUnlockBits($hImage2, $tBitmapData2)
    			_GDIPlus_ImageDispose($hBitmapDiff)
    			Return TimerDiff($t)
    
    	EndSwitch
    EndFunc
    
    
    Func _Exit($sError = "")
    	If $sError <> "" Then MsgBox($MB_ICONERROR, "ERROR", $sError)
    	If ($hImage1 <> 0) Then _GDIPlus_ImageDispose($hImage1)
    	If ($hImage2 <> 0) Then _GDIPlus_ImageDispose($hImage2)
    	_GDIPlus_Shutdown()
    	Exit
    EndFunc
    Alles anzeigen


    Sorry fürs Hijacken...:whistling:

  • Windows Graphics Capture API (WinRT) Fullscreen Capturing Test

    • UEZ
    • 29. August 2025 um 10:54

    Andy

    Danke fürs Testen. Ja genau, nur wenn sich was verändert, wird aufgenommen. Je höher die Qualität, umso länger dauert das Encoden in WebP. Daher sind die Settings auf "Speed" eingestellt.

    Ich habe mal die Zeit für das Capturen und Encoden gemessen und bei mir sind es ca. 70 ms. Bei 30 FPS sollte es nicht mehr als 33.33 ms sein. Für Fullscreen Aufnahmen ist WebP einfach zu schwach.

    Wie gesagt, reicht das für rudimentäre Zwecke. Moderne Browser unterstützen WebP und du kannst das WebP File im Browser darstellen. MS Edge kann das zum Beispiel...


    Ich habe die Exe aktualisiert (siehe Post#1)!

    Meine Ergebnis:

    Code
    Target fps: 30
    Recording time: 30 seconds
    Recording screen dim: 1920 x 1200
    
    Starting fullscreen capturing in 3 seconds...
    ellapsed: 30.12809640000342 seconds
    frames captured: 452        15.0026073336631 fps
    frame index: 460            15.26814020682528 fps
    delta : 8     0.9826086956521739 %
    total frames: 900           target fps 30 delta: 0.5022222222222222 %
    average frame encoding speed: 66.34842522186845 ms, max encoding delay: 33 ms -> -33.34842522186845
    Return: 1
    File size: 33939266 bytes
    
    Done
    Alles anzeigen
  • Windows Graphics Capture API (WinRT) Fullscreen Capturing Test

    • UEZ
    • 27. August 2025 um 23:16

    Danke argumentum .

    Hast einen schneller PC, denn 21 FPS sind ordentlich, falls du Bewegung auf dem Schirm hattest.

    WebP Anim ist kein Codec für Realtime Aufnahmen, da zu langsam. WebP Anim spielt in der gleichen Liga wie GIF und PNG Anim, d.h. WebP Anim ist eher für Animationen geeignet, wo man die Frames parat hat und nicht Realtime generierte Frames encodieren muss.

    Ich denke, das reicht, um mal schnell den Desktop aufzunehmen, um z.B. was mit anderen zu teilen.

  • Windows Graphics Capture API (WinRT) Fullscreen Capturing Test

    • UEZ
    • 27. August 2025 um 16:21

    Komisch, der Code sucht die Monitore mit EnumDisplayMonitors() und gibt den Wert für den primären Monitor zurück.

  • Windows Graphics Capture API (WinRT) Fullscreen Capturing Test

    • UEZ
    • 27. August 2025 um 15:21

    Vielen Dank.

    Was ich sagen kann, ist, dass die Aufnahmegeschwindigkeit anscheinend WebP bei großen Auflösungen überfordert und anscheinend nicht mit dem Encodieren der Frames in Echtzeit nachkommt.

    GetCapturedFrame() aus der DLL scheint nicht der Flaschenhals zu sein. Die Aufnahme im Speicher erst aufzunehmen und dann zu encoden könnte funktionieren, aber könnte der Speicheroverkill werden.

    Muss mal überlegen, welche Alternativen noch WebP bietet...


    Kanashius ist denn 2560 x 1440 nicht die tatsächliche Auflösung deines primären Monitors?


    Bei 3440x1440 -> das sind ~5 Mio. Pixel pro Frame -> bei 30 FPS ≈ 150 Mio. Pixel/s, die kodiert werden müssen!

  • Windows Graphics Capture API (WinRT) Fullscreen Capturing Test

    • UEZ
    • 27. August 2025 um 12:59
    Zitat von AspirinJunkie

    Ja klappt super! :love:

    30s 1920x1080@30FPS ergibt .webp-Datei mit 1,3 MB Dateigröße!

    Danke fürs Testen! 30s? Sollten eigentlich 20s sein. ;)


    Zitat von BananaJoe

    Screencapture hat funktioniert, aber die Animation besteht nur aus einem kurzen Flackern

    Hmm, benötige mehr Infos. Welches OS? Hast du was mit DRM aufgenommen? Ist die Aufnahme komplett durchgelaufen? Hast du nur dein Desktop aufgenommen? Wie viele Monitore?


    Ich habe zum Testen YouTube im Fullscreen Modus genommen -> z.B. https://youtu.be/9E0NQ2_aPfY?si=AoH69ZZzPLRRgySx

    Das gibt einen guten Eindruck, ob das Capturing gut funktioniert.


    Könnt ihr bitte den Output in der CMD Box posten?

  • Windows Graphics Capture API (WinRT) Fullscreen Capturing Test

    • UEZ
    • 27. August 2025 um 11:04

    Könnt ihr bitte testen, ob das Fullscreen Capturing auf dem primären Monitor funktioniert? Das Ergebnis sollte ein WebP Animation sein, die im gleichen Verzeichnis angelegt wird. Die Frames von der WGC API werden an die WebP API übergeben, da dann die Animation erstellt.

    In der CMD Console gibt es ein paar Infos. Könnt ihr bitte den Output in der CMD Box auch posten?

    Aus welchen Gründen auch immer kann ich diese Funktion nicht aus Autoit aufrufen!

    Läuft nur ab Win10+, da die Windows Graphics Capture API (WinRT) genutzt wird.

    Danke.

    Parameter:

    Code
    config.lossless = 0
    config.quality = 50
    config.method = 0
    config.thread_level = 1
    config.segments = 1
    config.sns_strength = 1
    config.filter_strength = 0
    config.pass = 1

    Dateien

    Fullscreen Capturing.7z 354,93 kB – 172 Downloads
  • Duplication API -> schnelle Screenshots

    • UEZ
    • 27. August 2025 um 10:25

    Immer noch schwarz.

Spenden

Jeder Euro hilft uns, Euch zu helfen.

Download

AutoIt Tutorial
AutoIt Buch
Onlinehilfe
AutoIt Entwickler
  1. Datenschutzerklärung
  2. Impressum
  3. Shoutbox-Archiv
Community-Software: WoltLab Suite™