Page 1 sur 1
Plasma
Publié : dim. 28/août/2005 16:17
par bombseb
Salut, voici un plasma que je viens de faire...
je pense qu'on doit pouvoir l'optimiser en précalculant les cosinus et les sinus mais c'est chiant à faire
Code : Tout sélectionner
InitSprite()
InitKeyboard()
If (InitSprite() And InitKeyboard() And OpenScreen(640,480,32,"Plasma")) = 1
EndIf
xres = 640
yres = 480
;Récupère l'adresse du buffer invisible
StartDrawing(ScreenOutput())
*AdresseEcran=DrawingBuffer()
Pitch=DrawingBufferPitch()/SizeOf(long)
#PI = 3.14159
; ------ Definition de la palette --------------
Dim mapal.l(300)
For i = 0 To 300
angle.f = angle + ((2 * #pi) / 300)
mapal(i) = RGB (Abs (Cos (angle + (4*#pi/3))* 255),Abs (Cos (angle + #pi/2)* 255), Abs (Cos (angle)* 255))
Next
; ----------------------------------------------
; ------------------- PLASMA -------------------
Repeat
a2 + 5
a3 + 5
StartDrawing (ScreenOutput ())
*AdresseEcran=DrawingBuffer()
For x = 0 To xres
A = Sin ((x + a2)/(300 + Sin (x/100)*100)) * 75 + 75
For y = 0 To yres
*ptr.Long = *AdresseEcran + (x+y*pitch) * SizeOf(Long)
A2 = Cos ((y + a3)/(300 + Cos (y/100)*100)) * 75 + 75
coul = a + a2
If coul > 300
coul = coul-300
EndIf
coul = mapal (coul)
;Plot (x,y, coul)
*ptr\l = coul
Next
Next
StopDrawing ()
FlipBuffers()
ExamineKeyboard()
Until KeyboardPushed(#PB_Key_Escape)
; ----------------------------------------------
dites moi ce que vous en pensez, c'est mon premier prog en purebasic
Publié : dim. 28/août/2005 17:18
par Dr. Dri
Voila les modifs pour que ca fonctionne chez moi...
Code : Tout sélectionner
If (InitSprite() And InitKeyboard() And OpenScreen(640,480,32,"Plasma")) = 1
EndIf
xres = 640
yres = 480
;Récupère l'adresse du buffer invisible
StartDrawing(ScreenOutput())
*AdresseEcran=DrawingBuffer()
Pitch=DrawingBufferPitch()/SizeOf(long)
#PI = 3.14159
; ------ Definition de la palette --------------
Dim mapal.l(300)
For i = 0 To 300
angle.f = angle + ((2 * #pi) / 300)
mapal(i) = RGB (Abs (Cos (angle + (4*#pi/3))* 255),Abs (Cos (angle + #pi/2)* 255), Abs (Cos (angle)* 255))
Next
; ----------------------------------------------
; ------------------- PLASMA -------------------
Repeat
a2 + 5
a3 + 5
If StartDrawing( ScreenOutput() )
*AdresseEcran=DrawingBuffer()
For x = 0 To xres
A = Sin ((x + a2)/(300 + Sin (x/100)*100)) * 75 + 75
For y = 0 To yres
*ptr.Long = *AdresseEcran + (x+y*pitch) * SizeOf(Long)
A2 = Cos ((y + a3)/(300 + Cos (y/100)*100)) * 75 + 75
coul = a + a2
If coul > 300
coul = coul-300
EndIf
coul = mapal (coul)
;Plot (x,y, coul)
*ptr\l = coul
Next
Next
StopDrawing ()
EndIf
FlipBuffers()
ExamineKeyboard()
Until KeyboardPushed(#PB_Key_Escape)
sympa comme tout en tou cas ^^
Dri

Publié : dim. 28/août/2005 21:09
par fweil
Pour l'optimisation des calculs de Sin() / Cos(), il y a un truc intéressant et pas trop lourd à intégrer :
- créer des tableaux pré-calculés pour les valeurs y des fonctions Sin() et Cos() variant de 0 à 2 * Pi par pas de 0.001 et travailler sur les angles * 1000 ramenés à des indices entiers.
Code : Tout sélectionner
Dim fSin.f(8191)
Dim fCos.f(8191)
For i = 0 To 8191
fSin(i) = Sin(i / 1000)
fCos(i) = Cos(i / 1000)
Next
OpenConsole()
NTimes = 10000000
tz = ElapsedMilliseconds()
For i = 1 To NTimes
f.f = Sin(i / 12345)
Next
PrintN(Str(ElapsedMilliseconds() - tz))
tz = ElapsedMilliseconds()
For i = 1 To NTimes
angle.f = i / 12345
iangle * 1000
iangle & $1FFF
f.f = fSin(iangle)
Next
PrintN(Str(ElapsedMilliseconds() - tz))
While Inkey() = ""
Wend
CloseConsole()
End
Les écarts entre les valeurs réelles et les valeurs pré-calculées sont ainsi assez faibles pour ne pas perturber le dessin en général (on a une précision ramenée à moins de un pixel près).
L'avantage de la méthode est, comme le fait ressortir le code ci-dessus, une vitesse 4 à 5 fois plus grande pour obtenir la valeur approchée.
Attention à vérifier ce code de test sans Debugger pour voir les perfs en exécutable.
Publié : dim. 28/août/2005 22:18
par bombseb
Dr dri : tu as juste rajouté le "if startdrawing ()" ? cane marchait pas chez toi sans ca ?
- créer des tableaux pré-calculés pour les valeurs y des fonctions Sin() et Cos() variant de 0 à 2 * Pi par pas de 0.001 et travailler sur les angles * 1000 ramenés à des indices entiers.

olala ca l'air plutot compliqué tout ca

Publié : dim. 28/août/2005 23:03
par Dr. Dri
c'est très simple, un startdrawing peut échouer... donc il faut toujours vérifier qu'il a fonctionné...
Regarde aussi le début de ton code, il contient des InitTruc() en trop...
Ton code se lance sans le debugger, ma version corrigée se lance aussi avec

(enfin bon j'ai pas regardé tout le code ^^)
Dri
Publié : dim. 28/août/2005 23:04
par bombseb
les initsprite et initkeyboard ?
et pourquoi ca échouerais un startdrawing ?
Publié : dim. 28/août/2005 23:15
par Dr. Dri
Oui ce sont ces deux initialisations... on initialise qu'une fois...
Pourquoi un StartDrawing() échourai ? parce qu'il est censé bloqué l'accès à la mémoire vidéo de l'output concernée et que ce genre d'opération peut échouer...
Dri

Publié : dim. 28/août/2005 23:17
par bombseb
mais si le startdrawing échoue le programme plante dans cas non ?
dans le cas de ton teste, si le startdrawing échoue le programme se termine sans rien faire non ?
Publié : dim. 28/août/2005 23:21
par Dr. Dri
dans ton exemple plasma, si le start échoue, rien ne s'affiche à l'écran et la boucle continue juska ce que l'utilisateur quitte... si tu ne fais pas de test sur le start et que tu dessines, là tu auras un plantage séverre...
autre chose, lorsque tu dessines, n'utilise pas le debugger (Debug valeur) parce que là aussi j'ai des plantages séverres...
Dri
Publié : dim. 28/août/2005 23:25
par bombseb
ah bon ok je prend note merci...
bon sinon j'ai optimisé mon plasma en precalculant les sinus et cosinus mais j'ai pas l'impression que ce soit plus rapide :
Code : Tout sélectionner
; InitSprite()
; InitKeyboard()
If (InitSprite() And InitKeyboard() And OpenScreen(640,480,32,"Plasma")) = 0
MessageRequester("Erreur", "Erreur à l'ouverture de l'écran", #PB_MessageRequester_Ok)
End
EndIf
xres = 640
yres = 480
;Récupère l'adresse du buffer invisible
If StartDrawing(ScreenOutput()) = 0
MessageRequester("Erreur", "Erreur à l'ouverture de l'écran", #PB_MessageRequester_Ok)
End
EndIf
*AdresseEcran=DrawingBuffer()
Pitch=DrawingBufferPitch()/SizeOf(long)
StopDrawing()
#PI = 3.14159
; ------ Definition de la palette --------------
Dim mapal.l(300)
For i = 0 To 300
angle.f = angle + ((2 * #pi) / 300)
mapal(i) = RGB (Abs (Cos (angle + (4*#pi/3))* 255),Abs (Cos (angle + #pi/2)* 255), Abs (Cos (angle)* 255))
Next
; ----------------------------------------------
;------------ Precalculation ------------
angle.f = 0
Global nb
nb = 2 * #pi * 1000
Dim costab.f(nb)
Dim sintab.f(nb)
For i = 1 To nb
angle.f = angle + ((2 * #pi) / nb)
costab(i) = Cos (angle)
sintab(i) = Sin (angle)
Next
Procedure.f Getcos(angle.f)
If angle.f > 2*#pi
angle = angle / (angle/(2*#pi))
EndIf
index = Int (angle * 1000)
ProcedureReturn costab(index)
EndProcedure
Procedure.f Getsin(angle.f)
If angle.f > 2*#pi
angle = angle / (angle/(2*#pi))
EndIf
index = Int (angle * 1000)
ProcedureReturn sintab(index)
EndProcedure
; ----------------------------------------------
; ------------------- PLASMA -------------------
Repeat
a2 + 5
a3 + 5
If StartDrawing (ScreenOutput ())
*AdresseEcran=DrawingBuffer()
For x = 0 To xres-1
A = getSin ((x + a2)/(300 + getSin (x/100)*100)) * 75 + 75
For y = 0 To yres-1
*ptr.Long = *AdresseEcran + (x+y*pitch) * SizeOf(Long)
A2 = getCos ((y + a3)/(300 + getCos (y/100)*100)) * 75 + 75
coul = a + a2
If coul > 300
coul = coul-300
EndIf
coul = mapal (coul)
;Plot (x,y, coul)
*ptr\l = coul
Next
Next
StopDrawing ()
FlipBuffers()
EndIf
ExamineKeyboard()
Until KeyboardPushed(#PB_Key_Escape)
; ----------------------------------------------
Publié : lun. 29/août/2005 17:35
par bombseb
je viens de m'apercevoir que mon plasma "optimisé" est carrément plus lent que l'original.... comment ce fesse ?