Page 1 sur 1

Dessiner pixel par pixel

Publié : sam. 29/sept./2007 17:56
par Buckethead
Bonjour,

J'ai parcouru le petit tuto "l'adresse d'un pixel" ci contre
http://www.purebasic.fr/french/viewtopi ... highlight=

J'essaye depuis cet exemple d'incorporer l'instruction PokeL() plutôt que Plot() mais il y a quelque chose que je n'ai pas compris.

DrawingBufferPitch() (=4096) qui ne vaut pas "TAILLE_ECRAN_EN_X" (=800 dans mon exemple)

J'ai laissé les codes de control volontairement ;) En REM les PokeL() qui ont échoués. (note qu'ils affichent quand même quelquechose, qu'une mauvaise valeur résulte en un crash)

Code : Tout sélectionner

InitSprite()
InitKeyboard()

OpenScreen(800,600,32,"keftales")
 
 Repeat
 
StartDrawing (ScreenOutput ())
 
  DB  = DrawingBuffer() 
  DBP = DrawingBufferPixelFormat()  
  
  ;DBP = 7 -> PF = 4
  Select DBP 
    Case #PB_PixelFormat_8Bits         : PF=1 
    Case #PB_PixelFormat_15Bits        : PF=2 
    Case #PB_PixelFormat_16Bits        : PF=2 
    Case #PB_PixelFormat_24Bits_RGB    : PF=3 
    Case #PB_PixelFormat_24Bits_BGR    : PF=3 
    Case #PB_PixelFormat_32Bits_RGB    : PF=4 
    Case #PB_PixelFormat_32Bits_BGR    : PF=4 
  EndSelect 
 
  t = t + 1

For y = 0 To 599
For x = 0 To 799


color = 155 + 100 * Sin(t + ( x*(x+t) + y*(y+t) ) / 100)



Plot (x,y,color)
 
;PokeL(DB + (X * PF) +DrawingBufferPitch() * ( Y * PF ) , Color ) 
;PokeL(DB + (X * PF) + TAILLE_ECRAN_EN_X * ( Y * PF ) , Color ) 
;PokeL(DB + (X * 4) + 800 * ( Y * 4 ) , Color ) 
;PokeL(DB + (X * 4) + 4096 * ( Y * 4 ) , Color ) 



  Next x
  Next y        
    
 
    DrawText(0,0,"DrawingBuffer() = DB:" + Str(DB))
    DrawText(0,16,"DBP:" + Str(DBP))
    DrawText(0,32,"PF:" + Str(PF))
    DrawText(0,48,"DrawingBufferPitch():" + Str(DrawingBufferPitch()))
     
   
     StopDrawing () 
    FlipBuffers () 
  ExamineKeyboard()
Until KeyboardPushed(#PB_Key_Escape)

Publié : sam. 29/sept./2007 18:14
par Backup
Cpl Bator ??

je dois avouer qu'en dehors d'un ecran

en 32 bits de profondeur, j'ai aussi eu des problemes avec cette procedure !!
notament sur un ecran en 16 bits de profondeur ... :?

peut etre un bug de purebasic ??

rappel des deux procedures :

Code : Tout sélectionner

Procedure rapide_Point(x,Y)   
    Select DrawingBufferPixelFormat()
        Case #PB_PixelFormat_8Bits         : PF=1:t=0
        Case #PB_PixelFormat_15Bits        : PF=2:t=0
        Case #PB_PixelFormat_16Bits        : PF=2:t=0
        Case #PB_PixelFormat_24Bits_RGB    : PF=3:t=0
        Case #PB_PixelFormat_24Bits_BGR    : PF=3:t=1
        Case #PB_PixelFormat_32Bits_RGB    : PF=4:t=0
        Case #PB_PixelFormat_32Bits_BGR    : PF=4:t=1
    EndSelect   
    color= PeekL(DrawingBuffer() + (x * PF) +DrawingBufferPitch()* ( Y )  ) 
    If t=1
        Rouge=Red(color)
        Vert=Green(color)
        Bleu=Blue(color)
       color=RGB(Bleu,Vert,Rouge) 
    EndIf 
    ProcedureReturn color 
EndProcedure



Procedure rapide_Plot(x,Y,Couleur) 
    Select DrawingBufferPixelFormat()
        Case #PB_PixelFormat_8Bits         : PF=1:t=0
        Case #PB_PixelFormat_15Bits        : PF=2:t=0
        Case #PB_PixelFormat_16Bits        : PF=2:t=0
        Case #PB_PixelFormat_24Bits_RGB    : PF=3:t=0
        Case #PB_PixelFormat_24Bits_BGR    : PF=3:t=1
        Case #PB_PixelFormat_32Bits_RGB    : PF=4:t=0
        Case #PB_PixelFormat_32Bits_BGR    : PF=4:t=1
    EndSelect  
    If t=1
        Rouge=Red(Couleur)
        Vert=Green(Couleur)
        Bleu=Blue(Couleur)
        Couleur=RGB(Bleu,Vert,Rouge) 
    EndIf 
    PokeL( DrawingBuffer()  + (x * PF) +DrawingBufferPitch()* ( Y ) , Couleur ) 
EndProcedure


Publié : sam. 29/sept./2007 18:42
par Buckethead
Je viens de trouver le problème, grace à un post de Mytic:

Au lieu de
PokeL(DB + (X * PF) +DrawingBufferPitch() * ( Y * PF ) , Color )

mettre
PokeL(DB + (X * PF) + DrawingBufferPitch() * Y , Color )

note: il faut convertir les couleurs, le rouge devient bleu ! (comme en Coolbasic :D)

http://www.purebasic.fr/french/viewtopi ... ight=pokel

Publié : sam. 29/sept./2007 18:46
par Backup
Buckethead a écrit : note: il faut convertir les couleurs, le rouge devient bleu ! (comme en Coolbasic :D)
si tu as bien essayé les procedures que je viens de poster ! tu aurai vu qu'elles intègrent le changement de couleur deja ainsi que ta découverte :lol: !! :)

Publié : sam. 29/sept./2007 19:46
par Buckethead
Dobro a écrit :
Buckethead a écrit : note: il faut convertir les couleurs, le rouge devient bleu ! (comme en Coolbasic :D)
si tu as bien essayé les procedures que je viens de poster ! tu aurai vu qu'elles intègrent le changement de couleur deja ainsi que ta découverte :lol: !! :)
Désolé, sur le coup j'ai pensé que tu t'en remettais à Cpl Bator (si c'est bien un nickname) que tu avais eu des problèmes avec cette routine. Je n'ai pas pris la peine de lire ton code, qui m'a paru être le même avec la partie "Select". Il m'a semblé être un copier coller, un rappel du tuto et non une solution.

Sur ce le tuto est resté tel quel, erroné. :wink:

Publié : sam. 29/sept./2007 22:45
par djes
Désolé d'être direct, mais je ne vois pas en quoi vos procédures sont "rapides".

Publié : sam. 29/sept./2007 23:05
par case
djes a écrit :Désolé d'être direct, mais je ne vois pas en quoi vos procédures sont "rapides".
je n'ai pas testé mais normalement d'apres mon experience (en blitz basic notement) utiliser ce genre de routines est plus rapide que d'utiliser une commande telle que plot .
sur quelques points dessiné la difference ne se verra peut etre pas mais sur la totalité d'un ecran il y a des chances d'avoir de meilleures performances

ceci dit tout depend aussi de la maniere dont pure gere ses ecrans

Publié : sam. 29/sept./2007 23:23
par djes
Pour être rapide, il faudrait déjà éviter d'utiliser une procédure, mais incorporer le code (à l'aide d'une macro par exemple). Ensuite il faudrait éviter toutes ces multiplications, l'utilisation de plusieurs variables, l'appel à plusieurs fonctions (red(), green()...). Là, on commencerait à être rapide.

Publié : sam. 29/sept./2007 23:36
par Backup
djes a écrit :Désolé d'être direct, mais je ne vois pas en quoi vos procédures sont "rapides".
ben c'est simple , je vais te le montrer :D


dans ce prg le but est de dessiner des barrières avec le bouton gauche , et avec le bouton droite tu te met en haut de l'écran et tu balance de "l'eau" et regarde bien le résultat , balance beaucoup d'eau hein :D

observe la vitesse des particules d'eau lorsque tu utilise l'instruction Point()

tu aura meme du mal a dessiner des barrieres sans trous pendant la chutes des particules !!

ensuite remplace "point" actuel par "rapide_point" avec l'editeur

relance le programe et test !! :D

la fluidité, est evidente, et on peu dessiner des barriere rouges, sans probleme !!
ceci prouve que Point() est tres lent !!

j'en avait deja fait la demonstration lors du prog Terre lune avec Huitbit !! :D
(c'etait mem encore plus flagrant !!)


Code : Tout sélectionner


;-------------
;-By Dobro sur une idée de Mytic ---
;-------------



InitSprite()
InitMouse()
InitKeyboard()
Declare rapide_Point(x,Y)
Declare  nouvel_goute(x.l,Y.l)
Declare gravite_collision()

Global taille=5 ; testez un autre chiffre<------------ zoom sur le phenomene



Structure goute
  x.l
  Y.l 
  pasy.l
  pasx.l 
EndStructure

Global NewList goute.goute()
Global largeur,hauteur

Enumeration 
  #crayon
  #goute
  #fond
  #Window
EndEnumeration

OpenWindow(#Window,1,1,1024,768,"ecran",#PB_Window_BorderLess  )
OpenWindowedScreen(WindowID(#Window),1,1,1024,768,1,0,0)
;OpenScreen(1024,768,32,"Eau")
largeur = GetSystemMetrics_ ( #SM_CXSCREEN ): ;=largeur de l'ecran
hauteur = GetSystemMetrics_ ( #SM_CYSCREEN ): ;=hauteur de l'ecran
  
  ; ********** Fond  ****************
  CreateSprite( #fond,1024,768)  
  ; ********************************
  ; ********** crayon ****************
  CreateSprite( #crayon,taille*2,taille*2)
  StartDrawing(SpriteOutput(#crayon)) 
  Box(0,0,taille,taille,RGB(0,255,0))
  StopDrawing()
  ; ********************************
  
  ; ********** goute d'eau ****************
  CreateSprite( #goute,taille,taille)
  StartDrawing(SpriteOutput(#goute)) 
  Box(0,0,taille/2,taille/2,RGB(0,0,255))
  Box(taille/2,taille/2,taille,taille,RGB(0,0,255))
  Box(taille/2,0,taille,taille/2,RGB($24,$95,$E8))
  Box(0,taille/2,taille/2,taille,RGB($24,$95,$E8))
  StopDrawing()
  ; ********************************
  
  
  Repeat 
    Event = WindowEvent()
    ExamineKeyboard()
    ExamineMouse()
    ClearScreen(0)
    If KeyboardPushed(#PB_Key_Escape)
      End
    EndIf 
    
    DisplaySprite(#fond,0,0) 
    x = MouseX()
    Y = MouseY()
    DisplaySprite(#crayon,x,Y)
    
    If MouseButton(#PB_MouseButton_Left) 
      StartDrawing(SpriteOutput(#fond))
      Circle(x,Y,taille,RGB(255,0,0)) 
      StopDrawing()
    EndIf
    
    If  KeyboardPushed(#PB_Key_Space) 
      StartDrawing(SpriteOutput(#fond))
      Circle(x,Y,taille,RGB(0,0,0)) 
      StopDrawing()
    EndIf
    
    If MouseButton(#PB_MouseButton_Right) 
      ;Y=0
      ; x=Random(largeur)
      G=G+1
      Debug CountList(goute())  
      nouvel_goute(x,Y)  
      If G>1000 ; < ------------- seuil maximum
        ClearList(goute()) 
        G=0
      EndIf
      
      
    EndIf 
    gravite_collision() 
    Delay(1)
    FlipBuffers()
  ForEver
  End 
  
  
  
  Procedure nouvel_goute(x.l,Y.l) 
    AddElement(goute())
    goute()\x=x
    goute()\Y=Y  
    DisplaySprite(#goute,x,Y) 
  EndProcedure
  
  Procedure gravite_collision()
    ResetList(goute() )   
    While NextElement(goute()) 
      StartDrawing(ScreenOutput()) 
      If Point (goute()\x,goute()\Y+taille) = 0
        goute()\Y+taille
      Else 
        p = Random(1)
        If p = 1
          If  Point (goute()\x+taille,goute()\Y)= 0
            goute()\x+taille
          Else
            If  Point (goute()\x-1,goute()\Y)= 0 :goute()\x-taille:EndIf
          EndIf
        Else
          If  Point (goute()\x-1,goute()\Y)=0
            goute()\x-taille
          Else
            If  Point (goute()\x+taille,goute()\Y)= 0 :goute()\x+taille:EndIf
          EndIf
        EndIf
      EndIf 
      StopDrawing() 
      
      ; ******** test sorti en bas on remet en haut ! ************
      If  goute()\Y>= (hauteur) 
        goute()\Y=0
      EndIf  
      ; *******************************
      
      ; ******** test sorti  a droite et gauche************
      If  (goute()\x>= (largeur-taille) Or goute()\x<=0) 
        goute()\pasx=0  
        goute()\pasy=0    
      EndIf  
      ; *******************************  
 
      DisplaySprite(#goute,goute()\x,goute()\Y)  
    Wend  
    
  EndProcedure
  
  
  
  Procedure rapide_Point(x,Y)      
    ; de cpl Bator
    If (x > 0) And (x < largeur) And (Y > 0) And (Y < hauteur) 
      Select DrawingBufferPixelFormat()
        Case #PB_PixelFormat_8Bits         : PF=1:t=0
        Case #PB_PixelFormat_15Bits        : PF=2:t=0
        Case #PB_PixelFormat_16Bits        : PF=2:t=0
        Case #PB_PixelFormat_24Bits_RGB    : PF=3:t=0
        Case #PB_PixelFormat_24Bits_BGR    : PF=3:t=1
        Case #PB_PixelFormat_32Bits_RGB    : PF=4:t=0
        Case #PB_PixelFormat_32Bits_BGR    : PF=4:t=1
      EndSelect   
      color= PeekL(DrawingBuffer() + (x * PF) +DrawingBufferPitch()* ( Y )  ) 
      If t=1
        Rouge=Red(color)
        Vert=Green(color)
        Bleu=Blue(color)
        color=RGB(Bleu,Vert,Rouge) 
      EndIf 
      ProcedureReturn color 
    Else  
      color=RGB(0,0,0)
      ProcedureReturn color 
    EndIf 
  EndProcedure
  
  

Publié : sam. 29/sept./2007 23:39
par Buckethead
djes a écrit :Désolé d'être direct, mais je ne vois pas en quoi vos procédures sont "rapides".
Après ce tuto, je voulais seulemement tester cette methode, je ne pense pas avoir écrit que c'était pour faire l'ultime routine qui à la fin ne ressemble plus à du basic.

Ha mais je connais cet Avatar. Ca me fait penser à Téléchat. Le gluon ou quelque chose comme ça. :D

Publié : dim. 30/sept./2007 0:28
par djes
Buckethead a écrit :
djes a écrit :Désolé d'être direct, mais je ne vois pas en quoi vos procédures sont "rapides".
Après ce tuto, je voulais seulemement tester cette methode, je ne pense pas avoir écrit que c'était pour faire l'ultime routine qui à la fin ne ressemble plus à du basic.

Ha mais je connais cet Avatar. Ca me fait penser à Téléchat. Le gluon ou quelque chose comme ça. :D
C'es très bien de faire des tests, et ce genre de routine pourrait avoir des amateurs. Pour mon avatar, oui, c'est le gluon ;)

Publié : dim. 30/sept./2007 1:28
par djes
Buckethead a écrit :Je me souviens, il y avait toujours un gluon pour toutes situations =]

Je voulais me remettre à la programmation, j'ai commencé par Coolbasic il y a deux semaines. J'ai abandonné après divers tests. (des problèmes de compatibilité avec la beta, un board actif seulement en finnois)

Néanmoins j'ai eu le temps de voir les instructions SHL/SHR que beaucoup utilisent pour éviter RGB. Je n'ai pas poussé le truc mais j'ai vu que les utilisateurs avancés l'employaient pour les multiplications ou divisions. Et puis je suis tombé sur cette page: http://www.purebasic.fr/french/viewtopi ... 0bbc91a6b4 (4 ème commentaire de bombseb) Seulement fweil semble dire que le compilateur gère sa très bien si on utilise des multiples de 2.
Moi je n'utilise plus les rotations pour éviter RGB, car il faut faire des tests pour savoir quel est le format employé par la carte graphique, donc le gain ne me semble pas si important. Si possible par contre, je cache le résultat de RGB dans une variable. Oui, pure sait très bien utiliser les décalages quand il le faut. Je t'invite à utiliser pureasm pour t'amuser avec l'assembleur et voir ce que fait pure ;)

Publié : dim. 30/sept./2007 1:32
par Buckethead
oups, désolé d'avoir éffacé le message.
Ok, merci pour l'info.