Verzerrungseffekte

Übersicht BlitzMax, BlitzMax NG Allgemein

Neue Antwort erstellen

s_m_w

Betreff: Verzerrungseffekte

BeitragDi, Dez 22, 2009 13:23
Antworten mit Zitat
Benutzer-Profile anzeigen
Hallo,
Ich habe mich in den letzten paar Tagen viel mit dem Thema ausseinander gesetzt, jedoch es nicht hinbekommen. Um zu zeigen, was ich denn versuche: Erstbestes Javaapplet, das ich gefunden habe
Mein erster Ansatz war ganz naiv einfach eine Heightmap zu generieren und je nachdem die Pixel zu verschieben, so dass eben der gewünschte Effekt auftaucht, aber das hat alles andere als gut geklappt. Gibt es einen besseren Ansatz, oder vielleicht ein Codeschnippsel, was mir helfen könnte?

edit:
Ich finde es interessant, wie schnell man die Lösung selbst findet, wenn man gerade nach Hilfe fragt. Ich habe das Ausgangsbild über die Heightmap auf das Endbild projeziert, ich muss es aber genau andersrum machen!

edit2:
Es gibt also Fortschritt. Mein jetziger Code ist folgender:
Code: [AUSKLAPPEN]
SuperStrict

Global Background:TImage = LoadImage("bild2.png")
Global H:TPixmap = LoadPixmap("bild.png")
Global Heightmap:Float[,] = ProcessHeightMap(H, 0, 0)

Graphics 800,600

While Not KeyHit(KEY_Escape)
  DrawImageHeightmap(Background,0,0,Heightmap)
  DrawPixmap H, 300, 0
  If (MouseDown(1))
     Heightmap = ProcessHeightmap(H, MouseX() - 400, MouseY() - 300)
  End If
  Flip
  Cls
Wend

Function DrawImageHeightmap(Image:TImage,x:Int,y:Int,Heightmap:Float[,])
  Local Xoffset:Int,Yoffset:Int,Shading:Int,c:Int,r:Float,g:Float,b:Float,newc:Int,rfactor:Float,gfactor:Float,bfactor:Float
  Local lockedImage:TPixmap = LockImage(Image)
  Local newImage:TPixmap = CopyPixmap(lockedImage)
  For Local x:Int=1 To lockedImage.width-2
    For Local y:Int=1 To lockedImage.height-2
      Xoffset = (Heightmap[x-1,y] - Heightmap[x+1,y])*10
      Yoffset = (Heightmap[x,y-1] - Heightmap[x,y+1])*10

      Shading = Xoffset * 2
     If (x - Xoffset < 0 Or x - Xoffset > lockedImage.width - 1)
       Xoffset = 0
      EndIf
      If (y - Yoffset < 0 Or y - Yoffset > lockedImage.height - 1)
        Yoffset = 0
      EndIf
      c = ReadPixel(lockedImage, x - Xoffset, y - Yoffset)
      WritePixel(newImage, x, y, c)
    Next
  Next
  DrawPixmap newImage,x,y
  UnlockImage Image
End Function

Function ProcessHeightmap:Float[,] (Pixmap:TPixmap, XOffset:Int, YOffset:Int)
  Local Color:Float,Map:Float[Pixmap.width,Pixmap.height]
  For Local x:Int=0 To Pixmap.width-1
    For Local y:Int=0 To Pixmap.height-1
      Color = (ReadPixel(Pixmap, x, y) Shr 16) & $ff
     If (x + XOffset > 0 And x + XOffset < Pixmap.width - 1 And y + YOffset > 0 And y + YOffset < pixmap.height - 1)
        Map[x + XOffset, y + YOffset] = (Color / 255) * 20 - 0.5
      EndIf
    Next
  Next
  Return Map
End Function

Jedoch ist das ganze ein wenig Langsam. Geht es schneller, wenn man davon ausgeht, dass sich die "Heightmap" jeden Frame ändern soll?
Sheep Happens

BlitzMoritz

BeitragDi, Dez 22, 2009 23:45
Antworten mit Zitat
Benutzer-Profile anzeigen
'hab mir den Code noch nicht so ganz bis ins Detail angeschaut, aber generell ist es nicht realistisch, DrawPixmap-, ReadPixel- und WritePixel-Befehle zu verwenden und interaktive Echtzeit in der Umsetzung zu erwarten. Da deine (im übrigen sehr interessante) Verfremdungsidee Pixel für Pixel berechnen muss, gibt es letztlich wohl keinen echt schnellen Weg ohne Kompromisse.
Schau doch mal in mein Programm für Verzerrungseffekte hinein: BlitzFoto 1.2
Mein Weg dabei ist folgender:
- Pixelfarbwerte nur singulär (also z.B. beim Laden) in Arrays einlesen
- Bei der interaktiven Bearbeitung nur noch diese fertigen Arrays nutzen (d.h. neue Position berechnen und per 'plot' zeichnen)
- Nur ein Ausschnitt des Bildes (also ein Teil der Arrays) in einer Vorschau wiedergeben, deren Größe selbst gewählt werden kann. Der Ausschnitt ist darüberhinaus beweglich und zoombar.

Ich nehme an, auch gimp o.a. arbeiten so ähnlich und können interaktiv nur einen Vorschauteil der Verfremdung in mehr oder weniger ruckelnder Echtzeit wiedergeben.

DaysShadow

BeitragDi, Dez 22, 2009 23:57
Antworten mit Zitat
Benutzer-Profile anzeigen
Ist zwar jetzt nur vermutet, aber ich denke mit einem Shader würde das ganze wahrscheinlich recht einfach zu machen sein, das blöde ist halt nur das BMax von sich aus das nicht drin hat, müsstest dir also etwas über OpenGL oder so basteln...

MfG DaysShadow
Blessed is the mind too small for doubt

s_m_w

BeitragMi, Dez 23, 2009 0:02
Antworten mit Zitat
Benutzer-Profile anzeigen
Erstmal danke für eure antworten, es stellen sich nur einige Probleme:
- Der Zweck, den ich hoffe zu erfüllen ist hauptsächlich Eyecandy in Spielen: Druckwellen, Kraftfeldeffekte und ähnliches die das Spiel grafisch aufpeppen, das heißt eine teilweise Vorschau kommt nicht in Frage. Ich habe solche Effekte schon öfters gesehen und bewundert.
- Was sind Shader?

edit:
Gerade etwas sehr beeindruckendes gefunden, was mir weiterhelfen könnte. Jedoch verstehe ich absolut garnicht, was da gemacht wird. Blickt da jemand durch und kann mir das erklären? ("Bild2.png" muss ein 256² Bild sein)

Code: [AUSKLAPPEN]
' Last iteration's tick value
'trancelation from C using SDL to bmax
'original code found at: http://sol.gfxile.net/gp/ch17.html
' by Jari Komppa AKA Sol. Translated by Jesse.

SuperStrict
' Screen surface
Global gScreen:TPixmap
Global GscreenPtr:Int Ptr
Global PITCH:Int
' Texture surface
Global gTexture:TPixmap
Global gTexturePtr:Int Ptr

' Look-up table
Global  gLut:Short[]

' Distance mask
Global gMask:Int[]

' Screen width
Const WIDTH:Int = 480
' Screen height
Const HEIGHT:Int = 320

' Physics iterations per second
Const PHYSICSFPS:Int = 100

' Last iteration's tick value
Global gLastTick:Int


Function init()

  Local temp:TPixmap = LoadPixmap("bild2.png")
  gTexture = ConvertPixmap(temp,PF_RGBA8888)
  gTexturePtr = Int Ptr(gTexture.pixels)

  gLut = New Short[WIDTH * HEIGHT * 4]
  gMask = New Int[WIDTH * HEIGHT * 4]

  Local i:Int, j:Int
  Local distance:Int
    For i = 0 Until HEIGHT * 2
 
    For j = 0 Until WIDTH * 2
   
      Local xdist:Int = j - WIDTH
      Local ydist:Int = i - HEIGHT
     
      ' round
      distance:Int = Sqr(xdist * xdist + ydist * ydist)
 
      ' square
 
    'If (Abs(xdist) > Abs(ydist)) distance = Abs(xdist) Else distance = Abs(ydist)
   
      ' diamond
      'distance = (Abs(xdist) + Abs(ydist)) / 2
     
      ' flower
      'distance :+ (Sin(ATan2(xdist,ydist) * 5)*8)*57.2957795
     
      If (distance <= 0) distance = 1
 
      Local d:Int = distance
      If (d > 255) d = 255
      gMask[i * WIDTH * 2 + j] = d * $010101
     
      distance = (64 * 256 / distance) & $ff
 
      Local angle:Int = (((ATan2(Float(xdist), Float(ydist)) / Pi*2) + 1.0) * 128)*0.0174532925
 
      gLut[i * WIDTH * 2 + j] = (distance Shl 8) + angle
    Next
  Next
End Function


Function blend_mul:Int(source:Int, target:Int)

  Local sourcer:Int = (source Shr  0) & $ff
  Local sourceg:Int = (source Shr  8) & $ff
  Local sourceb:Int = (source Shr 16) & $ff
  Local targetr:Int = (target Shr  0) & $ff
  Local targetg:Int = (target Shr  8) & $ff
  Local targetb:Int = (target Shr 16) & $ff

  targetr = (sourcer * targetr) Shr 8
  targetg = (sourceg * targetg) Shr 8
  targetb = (sourceb * targetb) Shr 8

  Return (targetr Shl  0) | (targetg Shl  8) | (targetb Shl 16)
End Function


Function render()
   
  ' Ask For the time in milliseconds
  Local tick:Int = MilliSecs()

  If (tick <= gLastTick)
 
    Delay(1)
    Return
  EndIf

  While (gLastTick < tick)
 
    ' 'physics' here

    gLastTick :+ 100 / PHYSICSFPS
  Wend

  Local posx:Int = (Sin((tick * 0.000645234)*57.2957795) + 1) * WIDTH / 2
  Local posy:Int = (Sin(tick * 0.000445234*57.2957795) + 1) * HEIGHT / 2
  Local posx2:Int =(Sin(-tick * 0.000645234*57.2957795) + 1) * WIDTH / 2
  Local posy2:Int =(Sin(-tick * 0.000445234*57.2957795) + 1) * HEIGHT / 2

  Local i:Int, j:Int
  For i = 0 Until HEIGHT
 
    For j = 0 Until WIDTH
   
      Local lut:Int = gLut[(i + posy) * WIDTH * 2 + j + posx] - gLut[(i + posy2) * WIDTH * 2 + j + posx2]
      Local mask:Int = gMask[(i + posy) * WIDTH * 2 + j + posx]
      Local mask2:Int = gMask[(i + posy2) * WIDTH * 2 + j + posx2]

      gScreenPtr[(j) + (i) * PITCH] =..
        blend_mul(..
        blend_mul(..
        gTexturePtr[((lut + tick / 32) & $ff) +..
                                         (((lut Shr 8) + tick / 8) & $ff) *..
                                         (gTexture.pitch/4)],..
         mask),..
         mask2)
    Next
  Next

End Function


 
' Attempt To Create a WIDTHxHEIGHT window with 32bit pixels.

Graphics width,height
gScreen = CreatePixmap(WIDTH, HEIGHT ,PF_RGBA8888)
gScreenPtr = Int Ptr(gScreen.pixels)
PITCH = gScreen.pitch/4
init()

' Main loop: loop Forever.

Repeat
  Cls
  render()
  DrawPixmap gScreen,0,0
  Flip(0)
Until KeyDown(KEY_ESCAPE)
Sheep Happens

DaysShadow

BeitragMi, Dez 23, 2009 0:15
Antworten mit Zitat
Benutzer-Profile anzeigen
Shader: http://de.wikipedia.org/wiki/Shader
Sofern ich es richtig verstanden habe sind Shader kleine Programme die von der Grafikkarte ausgeführt werden und ein Frame(also das derzeitige Bild) verändern können bevor das Bild auf den Bildschirm kommt, dadurch sind sie recht schnell und ermöglichen Echtzeiteffekte.

Zu dem Code: Sieht schön aus, habe keine Ahnung wie das funktioniert, aber er zieht zuviel Leistung.

Edit: Naja, der Code verzerrt das Bild indem er halt die Pixelkoordinaten durch Berechnungen verändert, das macht er über eine Pixmap, das ist aber in der Regel zu langsam und Leistungsfordernd für einen brauchbaren Echtzeiteinsatz.

MfG DaysShadow
Blessed is the mind too small for doubt
  • Zuletzt bearbeitet von DaysShadow am Mi, Dez 23, 2009 0:19, insgesamt einmal bearbeitet

s_m_w

BeitragMi, Dez 23, 2009 0:24
Antworten mit Zitat
Benutzer-Profile anzeigen
Hm, also interpretiere ich es richtig, dass es unmöglich ist, das zu machen, was ich vorhatte?
Sheep Happens

DaysShadow

BeitragMi, Dez 23, 2009 0:30
Antworten mit Zitat
Benutzer-Profile anzeigen
Nur mit den von BlitzMax gegebenen Mitteln würde ich es behaupten, ja.

MfG DaysShadow
Blessed is the mind too small for doubt

Noobody

BeitragMi, Dez 23, 2009 0:55
Antworten mit Zitat
Benutzer-Profile anzeigen
Mit BRL.GLGraphics liefert BMax die komplette OGL-API mit - du könntest dir also ohne zusätzliche Module einen Verzerr-Shader basteln.

Der Shader an sich ist meistens in kurzer Zeit geschrieben. Mit GLSL hat man ja eine High Level Shadersprache zur Hand, mit der man sehr effizient Shader programmieren kann. Andererseits ist das Initialisieren und Aktualisieren, das man zum Verwenden und Anzeigen des Shaders benötigt, nicht ganz einfach. Du müsstest dich daher stark mit OGL auseinandersetzen, falls du dich für diesen Weg entscheidest; du müsstest dann auch damit leben, dass je nach dem, wie du sie umsetzt, diese Effekte nicht bei jedem laufen werden.
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
 

Ava

Gast

BeitragMi, Dez 23, 2009 4:27
Antworten mit Zitat
Zitat:
ich denke mit einem Shader würde das ganze wahrscheinlich recht einfach zu machen sein


Im Programmablauf um ein Vielfaches schneller auf alle Fälle ... aber einfacher auf keinen Fall. Wink

Und das bezieht sich nicht einmal so sehr auf die Einarbeitung in OpenGL und GLSL. Ein Shaderprogramm ist ne ziemlich enge Zwangsjacke. Das mag etwas paradox klingen, da man Shader ansich direkt mit tollen Grafikmöglichkeiten in super Geschwindigkeit assoziiert - was ja auch richtig ist. ABER vieles was sich mit gewöhnlichem Programmcode recht einfach lösen lässt (wenn auch nicht unbedingt Echtzeit tauglich Rolling Eyes), kann einen in einem Shaderprogramm an den Rande des Wahnsinns treiben, da dort immer nur sehr wenige Informationen zur Verfügung stehen und keinerlei Gesamtüberblick vorhanden ist ("nimm dir deinen Pixel - und mach was draus!" Wink).

@ s_m_w
Meine Grafikengine hat einen sehr einfachen, benutzerfreundlichen Shadersupport. Wenn Du magst kann ich Dir die Module hochladen. Mit GLSL müsstest Du Dich aber auch dann vertraut machen (um den eigentlichen Shadercode zu schreiben).

s_m_w

BeitragMi, Dez 23, 2009 14:57
Antworten mit Zitat
Benutzer-Profile anzeigen
Noobody hat Folgendes geschrieben:
Du müsstest dich daher stark mit OGL auseinandersetzen, falls du dich für diesen Weg entscheidest; du müsstest dann auch damit leben, dass je nach dem, wie du sie umsetzt, diese Effekte nicht bei jedem laufen werden.

Das würde mich nicht unbedingt stören, solange es denn bei mir selbst läuft.
Ava hat Folgendes geschrieben:
@ s_m_w
Meine Grafikengine hat einen sehr einfachen, benutzerfreundlichen Shadersupport. Wenn Du magst kann ich Dir die Module hochladen. Mit GLSL müsstest Du Dich aber auch dann vertraut machen (um den eigentlichen Shadercode zu schreiben).

Das ist ein Angebot, das ich gerne annehmen würde
Sheep Happens
 

Ava

Gast

BeitragDi, Dez 29, 2009 2:11
Antworten mit Zitat
Schau mal hier: https://www.blitzforum.de/foru...hp?t=33529

Es ist bisher leider noch kein Shader-Beispiel dabei. Ich werde mich bemühen, noch eines anzufertigen.

Jan_

Ehemaliger Admin

BeitragDi, Dez 29, 2009 10:37
Antworten mit Zitat
Benutzer-Profile anzeigen
Ach, dieser Effekt ist garnicht so schwer.

Das mit der Highmap ist schon richtig.
Du brauchst eine Highmap + Cubemapping.
Das gibts bestimmt in Minib3d und ein Beispiel in der Blitzhilfe für Cubemapping.
Im Buch Gameprogramming Gems gibt es dann auch noch den Algorhythmus für das Wasser.

Lg. Jan_
between angels and insects

AnniXa

BeitragDi, Dez 29, 2009 12:50
Antworten mit Zitat
Benutzer-Profile anzeigen
soweit ich weis handelt es sich um blitzmax
|moonForge|
Ich bin Pokémon Meisterin seit 1998!

DaysShadow

BeitragDi, Dez 29, 2009 12:53
Antworten mit Zitat
Benutzer-Profile anzeigen
Und miniB3D ist ein Modul für eben dieses, nicht wahr? Wink

MfG DaysShadow
Blessed is the mind too small for doubt

AnniXa

BeitragDi, Dez 29, 2009 13:39
Antworten mit Zitat
Benutzer-Profile anzeigen
ja, das stimmt schon, aber er möchte es doch als spielerei für seine spiele machen :O
|moonForge|
Ich bin Pokémon Meisterin seit 1998!

Jan_

Ehemaliger Admin

BeitragMi, Dez 30, 2009 14:22
Antworten mit Zitat
Benutzer-Profile anzeigen
Ja, und annixa, da kann er dochj trotzdem Minib3d verwenden...

Das was er zeigt in dem Java dings, ist ein Wasser Effekt der mit Cubemapping und minib3d einfach zu machen geht. und das Kann er in seinem Programm doch nutzen!
between angels and insects

Neue Antwort erstellen


Übersicht BlitzMax, BlitzMax NG Allgemein

Gehe zu:

Powered by phpBB © 2001 - 2006, phpBB Group