Objekte in einer 3D Darstellung werden aus Polygonen erzeugt. Damit man die Kanten der Polygone nicht so sehr sieht und damit Lichteffekte (Shading) sichtbar wird, wird eine Technik namens Gouraud Shading (<> Flat Shading) eingesetzt.
Ich hab das Ganze aus Spaß mal gan von vorn angefangen. Und so wird nur aus einer Funktion die einen einzigen Pixel färbt ein Polygon mit Smooth-Shading erzeugt. Dabei ist eine DllStruct das Canvas und muss nur bearbeitet werden. Nach dem Bearbeiten wird sie einfach auf die GUI beblittet ohne dabei auf Zeichenfunktionen aus GDI o.ä. zuzugreifen ^^.
Spoiler anzeigen
#include <WindowsConstants.au3>
#include <WinAPI.au3>
#include <StaticConstants.au3>
Local $w = 500, $h = 500
Local $xOrigin = $w/2;
Local $yOrigin = $h-30;
$hgui = GUICreate("Gouraud Shaded Polys", $w, $h + 20)
$hTime = GUICtrlCreateLabel("", 0, $h, $w, 20, $SS_CENTER)
$DC_gui = _WinAPI_GetDC($hgui)
GUISetState()
Global $ptr, $hbmp
$DC_bitmap = _CreateNewBmp32($w, $h, $ptr, $hbmp)
Global $struct = DllStructCreate("dword["& $w * $h& "]", $ptr)
$Timer = TimerInit()
[/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]Do
gpoly(Random(0,$w/2,1),Random(0,$h/2,1),Random($w/2,$w,1),Random(0,$h/2,1),Random(0,$w,1),Random($h/2,$h,1),Random(0,255,1),Random(0,255,1),Random(0,255,1))
GUICtrlSetData($hTime, timerdiff($Timer))
_WinAPI_BitBlt($DC_gui, 0, 0, $w, $h, $DC_bitmap, 0, 0, $srccopy)
$Timer = TimerInit()
Until GUIGetMsg() = -3
_DeleteBitmap32($DC_bitmap, $ptr, $hbmp)
Func gpoly ($x1, $y1, $x2, $y2, $x3, $y3, $c1, $c2, $c3)
DIM $poly[$h][2]
DIM $colr[$h][2]
Local $m = 0, $x = 0, $c = 0, $cm = 0
IF $x1 + $x2 <> 0 AND $y1 + $y2 <> 0 THEN $m = ($x1 - $x2) / ($y1 - $y2)
IF $c1 + $c2 <> 0 AND $y1 + $y2 <> 0 THEN $cm = ($c1 - $c2) / ($y1 - $y2)
FOR $y = $y1 TO $y2
$poly[$y][0] = $x + $x1
$colr[$y][0] = $c + $c1
$x = $x + $m
$c = $c + $cm
NEXT
Local $m = 0, $x = 0, $c = 0, $cm = 0
IF $x2 + $x3 <> 0 AND $y2 + $y3 <> 0 THEN $m = ($x2 - $x3) / ($y2 - $y3)
IF $c2 + $c3 <> 0 AND $y2 + $y3 <> 0 THEN $cm = ($c2 - $c3) / ($y2 - $y3)
FOR $y = $y2 TO $y3
$poly[$y][0] = $x + $x2
$colr[$y][0] = $c + $c2
$x = $x + $m
$c = $c + $cm
NEXT
Local $m = 0, $x = 0, $c = 0, $cm = 0
IF $x1 + $x3 <> 0 AND $y1 + $y3 <> 0 THEN $m = ($x1 - $x3) / ($y1 - $y3)
IF $c1 + $c3 <> 0 AND $y1 + $y3 <> 0 THEN $cm = ($c1 - $c3) / ($y1 - $y3)
FOR $y = $y1 TO $y3
$poly[$y][1] = $x + $x1
$colr[$y][1] = $c + $c1
$x = $x + $m
$c = $c + $cm
NEXT
FOR $y = $y1 TO $y3
gLINE($poly[$y][0], $poly[$y][1], $y, $colr[$y][0], $colr[$y][1])
NEXT
EndFunc
Func gLINE($x1, $x2, $y, $c1, $c2)
If $x1 > $x2 Then
SWAP ($x1, $x2)
SWAP ($c1, $c2)
EndIf
Local $cm = 0, $c = 0
IF $c2 - $c1 <> 0 AND $x2 - $x1 <> 0 THEN $cm = ($c2 - $c1) / ($x2 - $x1)
FOR $x = $x1 TO $x2
DllStructSetData($struct, 1, ($c+$c1), $y*$w + $x + 1)
$c += $cm
NEXT
EndFunc
Func Swap(ByRef $a, ByRef $b)
$t = $b
$b = $a
$a = $t
EndFunc
Func _CreateNewBmp32($iwidth, $iheight, ByRef $ptr, ByRef $hbmp) ;erstellt leere 32-bit-Bitmap; Rückgabe $HDC und $ptr und handle auf die Bitmapdaten
$hcdc = _WinAPI_CreateCompatibleDC(0) ;Desktop-Kompatiblen DeviceContext erstellen lassen
$tBMI = DllStructCreate($tagBITMAPINFO) ;Struktur der Bitmapinfo erstellen und Daten eintragen
DllStructSetData($tBMI, "Size", DllStructGetSize($tBMI) - 4);Structgröße abzüglich der Daten für die Palette
DllStructSetData($tBMI, "Width", $iwidth)
DllStructSetData($tBMI, "Height", -$iheight) ;minus =standard = bottomup
DllStructSetData($tBMI, "Planes", 1)
DllStructSetData($tBMI, "BitCount", 32) ;32 Bit = 4 Bytes => AABBGGRR
$adib = DllCall('gdi32.dll', 'ptr', 'CreateDIBSection', 'hwnd', 0, 'ptr', DllStructGetPtr($tBMI), 'uint', 0, 'ptr*', 0, 'ptr', 0, 'uint', 0)
$hbmp = $adib[0] ;hbitmap handle auf die Bitmap, auch per GDI+ zu verwenden
$ptr = $adib[4] ;pointer auf den Anfang der Bitmapdaten, vom Assembler verwendet
_WinAPI_SelectObject($hcdc, $hbmp) ;objekt hbitmap in DC
Return $hcdc ;DC der Bitmap zurückgeben
EndFunc ;==>_CreateNewBmp32
Func _DeleteBitmap32($DC, $ptr, $hbmp)
_WinAPI_DeleteDC($DC)
_WinAPI_DeleteObject($hbmp)
$ptr = 0
EndFunc ;==>_DeleteBitmap32