[B3D] Schattenberechnung in 2D
Übersicht

![]() |
NoobodyBetreff: [B3D] Schattenberechnung in 2D |
![]() Antworten mit Zitat ![]() |
---|---|---|
Nach Lektüre eines äusserst interessanten Artikels auf Gamedev habe ich ein kleines Programm geschrieben, welches den Schattenwurf für 2D - Objekte korrekt berechnet.
Der Algorithmus ist im Moment limitiert auf konvexe Objekte, ausserdem müssen die Eckpunkte jedes Objekts im Gegenuhrzeigersinn angegeben werden. Immerhin tut er seinen Dienst, und das relativ flott dank simpler Vektorrechnung und 3D - Beschleunigung durch die Grafikkarte. Der Code (ich habe mich sogar dazu durchgerungen, ihn ein wenig zu kommentieren ![]() Const GWIDTH = 800
Const GHEIGHT = 600 Graphics3D GWIDTH, GHEIGHT, 0, 2 SetBuffer BackBuffer() Global PolygonSurf, ShadowSurf Type TPolygon ;Ein Schattenwerfendes Polygon Field VertexCount ;Anzahl Vertices Field Vertex.TVertex[ 128 ] ;Die Vertices an sich Field CenterX# ;Koordinaten des Mittelpunkts Field CenterY# End Type Type TVertex ;Ein Eckpunkt eines Polygons Field Polygon.TPolygon ;Zugehöriges Polygon Field X# ;Position Field Y# Field Prev.TVertex ;Vorgänger und Nachfolger Field Succ.TVertex Field VertIndex ;Index des 3D - Vertex' auf der Surface End Type Init() ;Ein paar kleine Polygone zur Demonstration erstellen CreatePolygon( 100, 100, 50, 50, 45 ) CreatePolygon( 250, 100, 50, 80, 90 ) CreatePolygon( 400, 500, 200, 50, 45 ) CreatePolygon( 400, 300, 10, 10, 36 ) Local Timer = CreateTimer( 60 ) ;Gebt 100% Auslastung keine Chance >:O While Not KeyHit( 1 ) LightX# = 400 + Cos( ( MilliSecs() Mod 3600 )/10. )*100 ;Das Licht ein wenig kreisen lassen LightY# = 300 - Sin( ( MilliSecs() Mod 3600 )/10. )*100 CalculateShadows( LightX#, LightY# ) ;Schatten berechnen Wireframe MouseDown( 1 ) ;Wireframe je nach Wunsch RenderWorld ;Rendern Color 255, 255, 0 ;Licht einzeichnen Oval LightX# - 10, LightY# - 10, 20, 20 ClearSurface ShadowSurf ;Und die Schattensurface aufräumen Flip 0 ;Versichtbaren und so WaitTimer Timer Wend End Function Init() DrawCam = CreateCamera() CameraProjMode DrawCam, 2 ;Kameraprojektion auf Orthogonal stellen CameraZoom DrawCam, 2.0/Float( GWIDTH ) ;Zoom für 2D richtig einstellen CameraClsColor DrawCam, 64, 64, 64 ;Hintergrundfarbe auf dunkles Grau einstellen - sonst sieht man die Schatten nicht DrawPivot = CreatePivot( DrawCam ) ;Pivot für Schatten und Polygone erstellen TurnEntity DrawPivot, 180, 0, 0 ;Pivot so drehen und positionieren, dass wir das normale 2D - Koordinatensystem haben PositionEntity DrawPivot, -GWIDTH/2., GHEIGHT/2., 100, True PolygonMesh = CreateMesh( DrawPivot ) ;Mesh und Surface für die Polygone erstellen PolygonSurf = CreateSurface( PolygonMesh ) EntityFX PolygonMesh, 1 + 2 ShadowMesh = CreateMesh( DrawPivot ) ;Mesh und Surface für die Schatten erstellen ShadowSurf = CreateSurface( ShadowMesh ) EntityFX ShadowMesh, 1 + 2 End Function Function CalculateShadows( LightX#, LightY# ) For Polygon.TPolygon = Each TPolygon For i = 0 To Polygon\VertexCount*2 ;Alle Vertices durchgehen Local Vertex.TVertex = Polygon\Vertex[ i Mod Polygon\VertexCount ] ;Momentan zu bearbeitenden Vertex rauslesen ;Skalarprodukt zwischen dem Vektor zum Licht und der Normale der Seite zwischen dem aktuellen Vertex und dem folgenden Vertex berechnen EdgeDP# = ( Vertex\Y# - Vertex\Succ\Y# )*( Vertex\X# - LightX# ) + ( Vertex\Succ\X# - Vertex\X# )*( Vertex\Y# - LightY# ) If Triangulate Then ;Falls trianguliert werden soll, dann... V1 = AddVertex( ShadowSurf, Vertex\X#, Vertex\Y#, 0, 0.6, 0.9 ) ;...benötigte Vertices erstellen.. V2 = AddVertex( ShadowSurf, Vertex\X# + ( Vertex\X# - LightX# )*100, Vertex\Y# + ( Vertex\Y# - LightY# )*100, 0, 0.6, 0.9 ) VertexColor ShadowSurf, V1, 0, 0, 0 ;...einfärben... VertexColor ShadowSurf, V2, 0, 0, 0 AddTriangle ShadowSurf, OldV1, V1, OldV2 ;...und triangulieren AddTriangle ShadowSurf, V1, V2, OldV2 EndIf If i > 0 Then ;Wenn die aktuelle Seite auf der Schattenseite und die vorherige Seite auf der Lichtseite ist, dann fängt hier der Schatten an If EdgeDP# > 0 And OldEdgeDP# < 0 Then V1 = AddVertex( ShadowSurf, Vertex\X#, Vertex\Y#, 0, 0.6, 0.9 ) ;Die ersten beiden Vertices erstellen und einfärben V2 = AddVertex( ShadowSurf, Vertex\X# + ( Vertex\X# - LightX# )*100, Vertex\Y# + ( Vertex\Y# - LightY# )*100, 0, 0.6, 0.9 ) VertexColor ShadowSurf, V1, 0, 0, 0 VertexColor ShadowSurf, V2, 0, 0, 0 Triangulate = True ;Wenn die aktuelle Seite auf der Lichtseite und die vorherige Seite auf der Schattenseite ist, hört hier der Schatten auf ElseIf EdgeDP# < 0 And OldEdgeDP# > 0 And Triangulate Then Triangulate = False ;Nix wie raus hier! Exit EndIf EndIf OldEdgeDP# = EdgeDP# OldV1 = V1 OldV2 = V2 Next Next End Function ;Erstellt ein Polygon mit dem Zentrum X#, Y#, der Breit Width#, der Höhe#, der Genauigkeit Stepsize und der Farbe R G B Function CreatePolygon( X#, Y#, Width#, Height#, StepSize = 10, R = 255, G = 255, B = 255 ) Polygon.TPolygon = New TPolygon Polygon\CenterX# = X# Polygon\CenterY# = Y# For i = 0 To 360 - StepSize CreateVertex( Polygon, X# + Cos( i )*Width#, Y# - Sin( i )*Height# ) i = i + StepSize - 1 Next Polygon\Vertex[ Polygon\VertexCount - 1 ]\Succ = Polygon\Vertex[ 0 ] For i = 0 To Polygon\VertexCount - 1 Polygon\Vertex[ i ]\VertIndex = AddVertex( PolygonSurf, Polygon\Vertex[ i ]\X#, Polygon\Vertex[ i ]\Y#, 0 ) VertexColor PolygonSurf, Polygon\Vertex[ i ]\VertIndex, R, G, B If i >= 2 Then AddTriangle PolygonSurf, Polygon\Vertex[ i ]\VertIndex, Polygon\Vertex[ i - 1 ]\VertIndex, Polygon\Vertex[ 0 ]\VertIndex Next End Function Function CreateVertex( Polygon.TPolygon, X#, Y# ) ;Erstellt einen Eckpunkt an einem Polygon Polygon\Vertex[ Polygon\VertexCount ] = New TVertex Polygon\Vertex[ Polygon\VertexCount ]\X# = X# Polygon\Vertex[ Polygon\VertexCount ]\Y# = Y# If Polygon\VertexCount > 0 Then Polygon\Vertex[ Polygon\VertexCount ]\Prev = Polygon\Vertex[ Polygon\VertexCount - 1 ] Polygon\Vertex[ Polygon\VertexCount - 1 ]\Succ = Polygon\Vertex[ Polygon\VertexCount ] EndIf Polygon\VertexCount = Polygon\VertexCount + 1 End Function Mit linker Maustaste kann man Wireframe ein- und ausschalten. Ein kleiner Screenshot: ![]() Die im Artikel beschriebene Methode zur Berechnung der weichen Übergänge am Rand der Schatten hat bei mir längst nicht so gut ausgesehen, weswegen ich die Funktion wieder rausgenommen habe. Ebenfalls ist die Lichtberechnung in Blitz nicht so gut hinzubekommen, da man dort leider keinen Alpha - Buffer zur Verfügung hat (ich habe noch ein wenig damit herumprobiert, den Z - Buffer zum eigenen Nutzen zu verwenden, allerdings hat es nicht wirklich funktioniert ![]() |
||
Man is the best computer we can put aboard a spacecraft ... and the only one that can be mass produced with unskilled labor. -- Wernher von Braun |
aletes |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
hmm, das sieht eigentlich ganz gut aus, kann man bestimmt noch gebrauchen ![]() |
||
![]() |
ozzi789 |
![]() Antworten mit Zitat ![]() |
---|---|---|
Mensch Noobody du bist zu gut!
Wieder mal ein sehr interessanter & nützlicher Code deinerseits, kurz thnx ![]() |
||
0x2B || ! 0x2B
C# | C++13 | Java 7 | PHP 5 |
![]() |
ToeB |
![]() Antworten mit Zitat ![]() |
---|---|---|
Fast genau so geht mein Vetex2D vor ^_^'
Aber trotzdem sehr gut gemacht... vielleicht wäre es besser wenn du sowieso nur "Polygones" erstellst (die ja an sich symetrisch sind) das du statt 30 Schatten nur einen schatten zeichnest... mfg ToeB |
||
Religiöse Kriege sind Streitigkeiten erwachsener Männer darum, wer den besten imaginären Freund hat.
Race-Project - Das Rennspiel der etwas anderen Art SimpleUDP3.0 - Neuste Version der Netzwerk-Bibliothek Vielen Dank an dieser Stelle nochmal an Pummelie, welcher mir einen Teil seines VServers für das Betreiben meines Masterservers zur verfügung stellt! |
![]() |
Dottakopf |
![]() Antworten mit Zitat ![]() |
---|---|---|
Geiles Teil!
Genau sowas habe ich gerade gesucht ! Danke Gruß Dottakopf |
||
Rechtschreibfehler gelten der allgemeinen Belustigung! |
Übersicht


Powered by phpBB © 2001 - 2006, phpBB Group