Farben mischen

Übersicht BlitzBasic Allgemein

Neue Antwort erstellen

Travis

Betreff: Farben mischen

BeitragDo, Jun 10, 2004 16:01
Antworten mit Zitat
Benutzer-Profile anzeigen
Im Codearchiv gibt's ja jetzt so schöne Lichtspielchen, wo sich verschiedene Lichtquellen überlagern und vermischen. Jetzt habe ich es selbst mal probiert, aber das mischen klappt nicht so richtig.

Ich bin dabei so vorgegangen, dass ich die Lichter als Kreise dargestellt habe. Diese Kreise bestehen aus einzelnen Bildpunkten. Je weiter jetzt der Bildpunkt vom Zentrum der Lichtquelle weg ist, desto dunkler wird er.

Um jetzt die Farben zu mischen bin ich so vorgegangen, dass ich zunächst an der Position wo der neue Bildpunkt gezeichnet werden soll, den alten Wert ausgelesen habe. Diesen Wert habe ich dann mit dem neuen Wert addiert.

Leider vermischt es sich aber nicht so schön, wie bei dem Beispiel von Vincent. Manchmal werden zwei Lichtquellen einfach wie Bilder aufeinandergepackt und man sieht sogar schwarze Ränder an den Übergängen. Manchmal schneidet sich ein anderes Licht mitten in ein anderes (sieht ja ein bisschen wie eine Kugel aus das Ganze). Bei einigen Farbtönen wirkt es schon ganz ordentlich, aber guckt es euch am besten mal selbst an.

Wie muss ich denn da vorgehen, wenn ich solche Lichtquellen verschmelzen lassen will? Ich bin leider aus dem Beispiel im Codearchiv nicht ganz schlau geworden.


Code: [AUSKLAPPEN]

Graphics 640,480,16,2
SetBuffer BackBuffer()

Type Light
 Field PosX#,PosY#,sx#,sy#,winkel,Radius,r,g,b
End Type

SeedRnd MilliSecs()

For i = 1 To 4
 l.light = New light
 l\PosX = Rnd(640-76)
 l\PosY = Rnd(480-76)
 l\radius = Rnd(50,90)
 l\r = Rnd(200)
 l\g = Rnd(200)
 l\b = Rnd(200)
 l\winkel = Rnd(360)
 l\sx# = Cos(l\winkel) * Rnd(8)
 l\sy# = Sin(l\winkel) * Rnd(8)
Next


Repeat
Cls

DrawLight()
MoveLight()

Flip
Until KeyHit(1)
End



Function MoveLight()
 For l.light = Each light
  l\PosX# = l\PosX# + l\sx#
  l\PosY# = l\PosY# + l\sy#
  If l\posx < 0 Then l\posx = 640
  If l\posx > 640 Then l\posx = 0
  If l\posy < 0 Then l\posy = 480
  If l\posy > 480 Then l\posy = 0
 Next 
End Function


Function DrawLight()

 LockBuffer BackBuffer()

 For l.light = Each light

  For rad = l\radius To 0 Step -1
   For grad# = 0 To 360 Step .5
   
    ; Position des Biltpunktes berrechnen
    x = ((Sin (grad#) * rad) + l\PosX)
    y = ((Cos (grad#) * rad) + l\PosY)

    ; alten Farbwert erfassen   
    If x > 0 And x < 640 Then
     If y > 0 And y < 480 Then
      OldRGB = ReadPixelFast(x,y)
      OldR = (OldRGB And $FF0000)/$10000
      OldG = (OldRGB And $FF00)/$100
      OldB = (OldRGB And $FF)
     EndIf   
    EndIf

    ; alte Farbe mit einberechnen
    r = r + oldr : If r>255 Then r = 255
    g = g + oldg : If g>255 Then g = 255
    b = b + oldb : If b>255 Then b = 255

    ; neue Farbe berechnen
    r = l\r - rad*2 : If r<0 Then r = oldr
    g = l\g - rad*2 : If g<0 Then g = oldg
    b = l\b - rad*2 : If b<0 Then b = oldb

    col = a*$1000000 + r*$10000 + g*$100 + b

    If x > 0 And x < 640 Then
     If y > 0 And y < 480 Then
      WritePixelFast x, y, col
     EndIf
    EndIf

    Next
   Next

 Next

 UnlockBuffer BackBuffer()

End Function
www.funforge.org

Ich hasse WASD-Steuerung.

Man kann alles sagen, man muss es nur vernünftig begründen können.

sbrog

BeitragDo, Jun 10, 2004 20:26
Antworten mit Zitat
Benutzer-Profile anzeigen
Also ich würde aus den farben den mittelwertbilden
150,250,10 und 20,100,220 wäre der mittelwert 85,175,105

a,b,c und a2,b2,c2 entspricht (a+a2)/2,(b+b2)/2,(c+c2)/2
 

Ensign Joe

BeitragFr, Jun 11, 2004 17:45
Antworten mit Zitat
Benutzer-Profile anzeigen
Das würde wohl nicht so ganz klappen:
0,0,0 (schwarz)
+
255,255,255 (weiß)
------------------ Mittelwert:
128,128,128

Das wäre GRAU, müsste aber WEIß SeIN!!!

Michi1988

BeitragFr, Jun 11, 2004 18:41
Antworten mit Zitat
Benutzer-Profile anzeigen
Man bräuchte evt. eine
Hintergrundfarbe. Schwarz wird dann z.B.
nicht mitgerechnet. Alle anderen Farben schon.

Michi

Holzchopf

Meisterpacker

BeitragFr, Jun 11, 2004 19:43
Antworten mit Zitat
Benutzer-Profile anzeigen
Travis, der Ansatz mit dem Farben addieren ist korrekt, der einzige Fehler den du machst, ist bei der Berechnung der neuen Farbe.
Ich hab mal den Code abgeändert:
Code: [AUSKLAPPEN]

Graphics 640,480,16,2
SetBuffer BackBuffer()

Type Light
 Field PosX#,PosY#,sx#,sy#,winkel,Radius,r,g,b
End Type

SeedRnd MilliSecs()

For i = 1 To 4
 l.light = New light
 l\PosX = Rnd(640-76)
 l\PosY = Rnd(480-76)
 l\radius = Rnd(50,90)
 l\r = Rnd(255)
 l\g = Rnd(255)
 l\b = Rnd(255)
 l\winkel = Rnd(360)
 l\sx# = Cos(l\winkel) * Rnd(8)
 l\sy# = Sin(l\winkel) * Rnd(8)
Next


Repeat
Cls

DrawLight()
MoveLight()

Flip
Until KeyHit(1)
End



Function MoveLight()
 For l.light = Each light
  l\PosX# = l\PosX# + l\sx#
  l\PosY# = l\PosY# + l\sy#
  If l\posx < 0 Then l\posx = 640
  If l\posx > 640 Then l\posx = 0
  If l\posy < 0 Then l\posy = 480
  If l\posy > 480 Then l\posy = 0
 Next 
End Function


Function DrawLight()

 LockBuffer BackBuffer()

 For l.light = Each light

  For x = l\posx - l\radius To l\posx + l\radius
   For y = l\posy - l\radius To l\posy + l\radius
   
    ; Radius ermiteln
    rad = Sqr( (x-l\posx)^2 + (y-l\posy)^2 )
    If rad < l\radius Then
   
     ; alten Farbwert erfassen   
     If x > 0 And x < 640 Then
      If y > 0 And y < 480 Then
       OldRGB = ReadPixelFast(x,y)
       OldR = (OldRGB And $FF0000)/$10000
       OldG = (OldRGB And $FF00)/$100
       OldB = (OldRGB And $FF)

      ; Farbintensität errechnen
       r = l\r * Float((l\radius - rad) / Float(l\radius))
       g = l\g * Float((l\radius - rad) / Float(l\radius))
       b = l\b * Float((l\radius - rad) / Float(l\radius))
       If r<0 Then r = 0
       If g<0 Then g = 0
       If b<0 Then b = 0
   
       ; alte Farbe mit einberechnen
       r = r + oldr : If r>255 Then r = 255
       g = g + oldg : If g>255 Then g = 255
       b = b + oldb : If b>255 Then b = 255
 

       col = r*$10000 + g*$100 + b

       WritePixelFast x, y, col
      EndIf
     EndIf

   EndIf

   Next
  Next

 Next

 UnlockBuffer BackBuffer()

End Function


Zur Berechnung der Farbintensität:

Die Differenz zwischen rad und l\radius wird ermittelt, diese wird dann durch l\radius geteit, damit sie zwischen 0 und 1 liegt - mit diesem Wert wird dann die Lichtfarbe multipliziert.

Zudem habe ich dein Prinzip vom einzeichnen geändert, wenn du alle 0.5 bei jedem ganzen Radiusschritt ein Pixel malst, malst du bei einem Kreis mit dem Radius 50 ganze 50*360*2 = 36000 Pixel, wovon sich einige natürlich überschneiden (diese würden sich dann gegenseitig aufhellen). Mit "meiner" Methode werden beim selben Radius allerdings nur 100*100 = 10000 Pixel gemalt, jene die Ausserhalb des Radius liegen werden sogar ausgelassen, ergo werden nurnoch 7854 Pixel berechnet und gemalt...

Die unschönen schwarzen Lichtkanten kann ich mir auch nicht erklären...
Erledige alles Schritt um Schritt - erledige alles. - Holzchopf
CC BYBinaryBorn - Yogurt ♫ (31.10.2018)
Im Kopf da knackt's und knistert's sturm - 's ist kein Gedanke, nur ein Wurm

Neue Antwort erstellen


Übersicht BlitzBasic Allgemein

Gehe zu:

Powered by phpBB © 2001 - 2006, phpBB Group