Dessin de forme avec du lissage

Programmation d'applications complexes
Le Soldat Inconnu
Messages : 4312
Inscription : mer. 28/janv./2004 20:58
Localisation : Clermont ferrand OU Olsztyn
Contact :

Re: Dessin de forme avec du lissage

Message par Le Soldat Inconnu »

Mise à jour pour PB4.40

Code : Tout sélectionner

; Auteur : Le Soldat Inconnu
; Version de PB : 4.3
;
; Explication du programme :
; Dessin avec lissage

Procedure CircleAA(x, y, Radius, Color, Thickness = 1, Mode = #PB_2DDrawing_Default)
  Protected n, nn, Distance.f, Application.f, Couleur_Fond.l
  If Mode & #PB_2DDrawing_Outlined ; Cercle vide
    ; on dessine 1/4 du cercle et on duplique pour le reste
    For n = 0 To Radius
      For nn = 0 To Radius
        Distance.f = Sqr(n * n + nn * nn)
        If Distance <= Radius And Distance > Radius - 1
          Application.f = 1 - Abs(Radius - 1 - Distance)
          Alpha = 255 * Application
					Plot(x + n, y + nn, Color | Alpha << 24)
					Plot(x - n, y + nn, Color | Alpha << 24)
					Plot(x + n, y - nn, Color | Alpha << 24)
					Plot(x - n, y - nn, Color | Alpha << 24)
        ElseIf Distance <= Radius - Thickness And Distance > Radius - Thickness - 1
          Application.f = 1 - Abs(Radius - Thickness - Distance)
          Alpha = 255 * Application
					Plot(x + n, y + nn, Color | Alpha << 24)
					Plot(x - n, y + nn, Color | Alpha << 24)
					Plot(x + n, y - nn, Color | Alpha << 24)
					Plot(x - n, y - nn, Color | Alpha << 24)
        ElseIf Distance <= Radius - 1 And Distance > Radius - Thickness
          Plot(x + n, y + nn, Color | $FF000000)
          Plot(x - n, y + nn, Color | $FF000000)
          Plot(x + n, y - nn, Color | $FF000000)
          Plot(x - n, y - nn, Color | $FF000000)
        EndIf
      Next
    Next
  Else ; Cercle plein
    ; on dessine 1/4 du cercle et on duplique pour le reste
    For n = 0 To Radius
      For nn = 0 To Radius
        Distance.f = Sqr(n * n + nn * nn)
        If Distance <= Radius And Distance > Radius - 1
          Application.f = (Radius - Distance)
          Alpha = 255 * Application
					Plot(x + n, y + nn, Color | Alpha << 24)
					Plot(x - n, y + nn, Color | Alpha << 24)
					Plot(x + n, y - nn, Color | Alpha << 24)
					Plot(x - n, y - nn, Color | Alpha << 24)
        ElseIf Distance <= Radius - 1
          Plot(x + n, y + nn, Color | $FF000000)
          Plot(x - n, y + nn, Color | $FF000000)
          Plot(x + n, y - nn, Color | $FF000000)
          Plot(x - n, y - nn, Color | $FF000000)
        EndIf
      Next
    Next
  EndIf
EndProcedure

Procedure EllipseAA(x, y, RadiusX, RadiusY, Color, Thickness = 1, Mode = #PB_2DDrawing_Default)
  Protected n, nn, Distance.f, Application.f, Couleur_Fond.l, Ellispse_Rayon.f, Ellipse_E.f
  ; Précacul de l'équation de l'ellipse
  If RadiusX > RadiusY
    Ellipse_E = Sqr(RadiusX * RadiusX - RadiusY * RadiusY) / RadiusX
  Else
    Ellipse_E = Sqr(RadiusY * RadiusY - RadiusX * RadiusX) / RadiusY
  EndIf
  Ellipse_E * Ellipse_E
  If Mode & #PB_2DDrawing_Outlined ; ellipse vide
    ; on dessine 1/4 de l'ellipse et on duplique pour le reste
    For n = 0 To RadiusX
      For nn = 0 To RadiusY 
        Distance.f = Sqr(n * n + nn * nn)
        If RadiusX > RadiusY
          If n
            Ellipse_CosAngle.f = n / Distance
            Ellispse_Rayon = Sqr(RadiusY * RadiusY / (1 - Ellipse_E * Ellipse_CosAngle * Ellipse_CosAngle))
          Else
            Ellispse_Rayon = RadiusY
          EndIf
        Else
          If nn
            Ellipse_CosAngle.f = nn / Distance
            Ellispse_Rayon = Sqr(RadiusX * RadiusX / (1 - Ellipse_E * Ellipse_CosAngle * Ellipse_CosAngle))
          Else
            Ellispse_Rayon = RadiusX
          EndIf
        EndIf
        If Distance <= Ellispse_Rayon And Distance > Ellispse_Rayon - 1
          Application.f = 1 - Abs(Ellispse_Rayon - 1 - Distance)
					Alpha = 255 * Application
					Plot(x + n, y + nn, Color | Alpha << 24)
					Plot(x - n, y + nn, Color | Alpha << 24)
					Plot(x + n, y - nn, Color | Alpha << 24)
					Plot(x - n, y - nn, Color | Alpha << 24)
        ElseIf Distance <= Ellispse_Rayon - Thickness And Distance > Ellispse_Rayon - Thickness - 1
          Application.f = 1 - Abs(Ellispse_Rayon - Thickness - Distance)
					Alpha = 255 * Application
					Plot(x + n, y + nn, Color | Alpha << 24)
					Plot(x - n, y + nn, Color | Alpha << 24)
					Plot(x + n, y - nn, Color | Alpha << 24)
					Plot(x - n, y - nn, Color | Alpha << 24)
        ElseIf Distance <= Ellispse_Rayon - 1 And Distance > Ellispse_Rayon - Thickness
          Plot(x + n, y + nn, Color | $FF000000)
          Plot(x - n, y + nn, Color | $FF000000)
          Plot(x + n, y - nn, Color | $FF000000)
          Plot(x - n, y - nn, Color | $FF000000)
        EndIf
      Next
    Next
  Else ; ellipse pleine
    ; on dessine 1/4 de l'ellipse et on duplique pour le reste
    For n = 0 To RadiusX
      For nn = 0 To RadiusY
        Distance.f = Sqr(n * n + nn * nn)
        If RadiusX > RadiusY
          If n
            Ellipse_CosAngle.f = n / Distance
            Ellispse_Rayon = Sqr(RadiusY * RadiusY / (1 - Ellipse_E * Ellipse_CosAngle * Ellipse_CosAngle))
          Else
            Ellispse_Rayon = RadiusY
          EndIf
        Else
          If nn
            Ellipse_CosAngle.f = nn / Distance
            Ellispse_Rayon = Sqr(RadiusX * RadiusX / (1 - Ellipse_E * Ellipse_CosAngle * Ellipse_CosAngle))
          Else
            Ellispse_Rayon = RadiusX
          EndIf
        EndIf
        If Distance <= Ellispse_Rayon And Distance > Ellispse_Rayon - 1
          Application.f = (Ellispse_Rayon - Distance)
					Alpha = 255 * Application
					Plot(x + n, y + nn, Color | Alpha << 24)
					Plot(x - n, y + nn, Color | Alpha << 24)
					Plot(x + n, y - nn, Color | Alpha << 24)
					Plot(x - n, y - nn, Color | Alpha << 24)
        ElseIf Distance <= Ellispse_Rayon - 1
          Plot(x + n, y + nn, Color | $FF000000)
          Plot(x - n, y + nn, Color | $FF000000)
          Plot(x + n, y - nn, Color | $FF000000)
          Plot(x - n, y - nn, Color | $FF000000)
        EndIf
      Next
    Next
  EndIf
EndProcedure

Procedure LineAA(x, y, Width, Hight, Color, Thickness = 1)
  Protected SensX, SensY, n, nn, Epaisseur.f, x2.f, y2.f, Couleur_Fond.l, Application.f, Distance.f
  ; On mets la droite toujours dans le même sens pour l'analyse
  ; La sauvegarde du sens permettra de dessiner la droite ensuite dans le bon sens
  If Width >= 0
    SensX = 1
  Else
    SensX = -1
    Width = - Width
  EndIf
  If Hight >= 0
    SensY = 1
  Else
    SensY = -1
    Hight = - Hight
  EndIf
  
  
  ; Demi épaisseur de la ligne
  Epaisseur.f = Thickness / 2
  
  ; calcul pour le changement de repère qui permet de connaitre l'épaisseur du trait et de gérer l'AA
  Distance.f = Sqr(Width * Width + Hight * Hight)
  CosAngle.f = Width / Distance
  SinAngle.f = -Sin(ACos(CosAngle))
  
  ; Dessin de la ligne
  For n = -Thickness To Width + Thickness
    For nn = -Thickness To Hight + Thickness
      
      ; changement de base
      ; les y représentent l'épaisseur de la ligne
      x2 = n * CosAngle - nn * SinAngle
      y2 = Abs(n * SinAngle + nn * CosAngle)
      
      If y2 <= Epaisseur + 0.5
        Application =  0.5 + Epaisseur - y2
        If Application > 1
          Application = 1
        EndIf
        If x2 > -1 And x2 < Distance + 1
          If x2 < 0
            Application * (1 + x2)
          ElseIf x2 > Distance
            Application * (1 - x2 + Distance)
          EndIf
        Else
          Application = 0
        EndIf
        If Application > 0
          If Application < 1
						Alpha = 255 * Application
						Plot(x + n * SensX, y + nn * SensY, Color | Alpha << 24)
          Else
            Plot(x + n * SensX, y + nn * SensY, Color | $FF000000)
          EndIf
        EndIf
      EndIf
      
    Next
  Next
  
EndProcedure

Procedure TriangleAA(x1, y1, x2, y2, x3, y3, Color, Thickness = 1, Mode = #PB_2DDrawing_Default)
  Protected Epaisseur.f, Zone_G, Zone_D, Zone_H, Zone_B, Couleur_Fond, Application.f
  Protected Width12.l, Hight12.l, Distance12.f, CosAngle12.f, SinAngle12.f, Sens12.l, y1_r2.f, Application1.f, Interieur1
  Protected Width23.l, Hight23.l, Distance23.f, CosAngle23.f, SinAngle23.f, Sens23.l, y2_r2.f, Application2.f, Interieur2
  Protected Width31.l, Hight31.l, Distance31.f, CosAngle31.f, SinAngle31.f, Sens31.l, y3_r2.f, Application3.f, Interieur3
  
  ; Demi épaisseur de la ligne
  Epaisseur.f = Thickness / 2
  
  ; calcul pour le changement de repère qui permet de connaitre l'épaisseur du trait et de gérer l'AA
  ; Pour la ligne 12
  ; Le point de départ du repère est le point x1, y1
  Width12.l = x2 - x1
  Hight12.l = y2 - y1
  Distance12.f = Sqr(Width12 * Width12 + Hight12 * Hight12)
  CosAngle12.f = Width12 / Distance12
  SinAngle12.f = Sin(ACos(CosAngle12))
  If Hight12 > 0
    SinAngle12 = -SinAngle12
  EndIf
  ; changement de base
  y3_r2 = (x3 - x1) * SinAngle12 + (y3 - y1) * CosAngle12
  ; on regarde de quel coté de la ligne se trouve le triangle en regardant la position du point 3
  If y3_r2 > 0
    Sens12 = 1
  Else
    Sens12 = -1
  EndIf
  ; Pour la ligne 23
  ; Le point de départ du repère est le point x2, y2
  Width23.l = x3 - x2
  Hight23.l = y3 - y2
  Distance23.f = Sqr(Width23 * Width23 + Hight23 * Hight23)
  CosAngle23.f = Width23 / Distance23
  SinAngle23.f = Sin(ACos(CosAngle23))
  If Hight23 > 0
    SinAngle23 = -SinAngle23
  EndIf
  ; changement de base
  y1_r2 = (x1 - x2) * SinAngle23 + (y1 - y2) * CosAngle23
  ; on regarde de quel coté de la ligne se trouve le triangle en regardant la position du point 3
  If y1_r2 > 0
    Sens23 = 1
  Else
    Sens23 = -1
  EndIf
  ; Pour la ligne 31
  ; Le point de départ du repère est le point x3, y3
  Width31.l = x1 - x3
  Hight31.l = y1 - y3
  Distance31.f = Sqr(Width31 * Width31 + Hight31 * Hight31)
  CosAngle31.f = Width31 / Distance31
  SinAngle31.f = Sin(ACos(CosAngle31))
  If Hight31 > 0
    SinAngle31 = -SinAngle31
  EndIf
  ; changement de base
  y2_r2 = (x2 - x3) * SinAngle31 + (y2 - y3) * CosAngle31
  ; on regarde de quel coté de la ligne se trouve le triangle en regardant la position du point 3
  If y2_r2 > 0
    Sens31 = 1
  Else
    Sens31 = -1
  EndIf
  
  ; Détermination de la zone de dessin
  Zone_G = x1
  Zone_D = x1
  Zone_B = y1
  Zone_H = y1
  If x2 < Zone_G
    Zone_G = x2
  EndIf
  If x3 < Zone_G
    Zone_G = x3
  EndIf
  If x2 > Zone_D
    Zone_D = x2
  EndIf
  If x3 > Zone_D
    Zone_D = x3
  EndIf
  If y2 < Zone_B
    Zone_B = y2
  EndIf
  If y3 < Zone_B
    Zone_B = y3
  EndIf
  If y2 > Zone_H
    Zone_H = y2
  EndIf
  If y3 > Zone_H
    Zone_H = y3
  EndIf
  Zone_B - Thickness
  Zone_H + Thickness
  Zone_G - Thickness
  Zone_D + Thickness
  
  ; Dessin du triangle
  If Mode & #PB_2DDrawing_Outlined ; Triangle vide
    For n = Zone_G To Zone_D
      For nn = Zone_B To Zone_H
        
        y1_r2 = (n - x1) * SinAngle12 + (nn - y1) * CosAngle12
        y1_r2 * Sens12
        If y1_r2 >= -0.5 - Epaisseur
          
          Application1.f = 0.5 + Epaisseur + y1_r2
          If Application1 > 1
            Application1 =  1 + 0.5 + Epaisseur - Application1
            If Application1 < 0
              Application1 = 0
            EndIf
            Interieur1 = 1
          Else
            Interieur1 = 0
          EndIf
          
          y2_r2 = (n - x2) * SinAngle23 + (nn - y2) * CosAngle23
          y2_r2 * Sens23
          If y2_r2 >= -0.5 - Epaisseur
            
            Application2.f = 0.5 + Epaisseur + y2_r2
            If Application2 > 1
              Application2 = 1 + 0.5 + Epaisseur - Application2
              If Application2 < 0
                Application2 = 0
              EndIf
              Interieur2 = 1
            Else 
              Interieur2 = 0
            EndIf
            
            y3_r2 = (n - x3) * SinAngle31 + (nn - y3) * CosAngle31
            y3_r2 * Sens31
            If y3_r2 >= -0.5 - Epaisseur
              
              Application3.f = 0.5 + Epaisseur + y3_r2
              If Application3 > 1
                Application3 = 1 + 0.5 + Epaisseur - Application3
                If Application3 < 0
                  Application3 = 0
                EndIf
                Interieur3 = 1
              Else
                Interieur3 = 0
              EndIf
              
              
              If Interieur1 And Interieur2 And Interieur3
                Application = Application1 + Application2 + Application3
              Else
                Application = 1
                If Interieur1 = 0
                  Application * Application1
                EndIf
                If Interieur2 = 0
                  Application * Application2
                EndIf
                If Interieur3 = 0
                  Application * Application3
                EndIf
              EndIf
              If Application > 0
                If Application < 1
                  ; Couleur_Fond = Point(n, nn)
                  ; Plot(n, nn, ColorBlending(Color, Couleur_Fond, Application))
									Alpha = 255 * Application
									Plot(n, nn, Color | Alpha << 24)
                Else
                  Plot(n, nn, Color | $FF000000)
                EndIf
              EndIf
            
            EndIf
          EndIf
        EndIf
        
      Next
    Next
  Else ; Triangle plein
    For n = Zone_G To Zone_D
      For nn = Zone_B To Zone_H
        
        y1_r2 = (n - x1) * SinAngle12 + (nn - y1) * CosAngle12
        y1_r2 * Sens12
        If y1_r2 >= -0.5 - Epaisseur
          
          Application1.f = 0.5 + Epaisseur + y1_r2
          If Application1 > 1
            Application1 = 1
          EndIf
          
          y2_r2 = (n - x2) * SinAngle23 + (nn - y2) * CosAngle23
          y2_r2 * Sens23
          If y2_r2 >= -0.5 - Epaisseur
            
            Application2.f = 0.5 + Epaisseur + y2_r2
            If Application2 > 1
              Application2 = 1
            EndIf
            
            y3_r2 = (n - x3) * SinAngle31 + (nn - y3) * CosAngle31
            y3_r2 * Sens31
            If y3_r2 >= -0.5 - Epaisseur
              
              Application3.f = 0.5 + Epaisseur + y3_r2
              If Application3 > 1
                Application3 = 1
              EndIf
              
              Application = Application1 * Application2 * Application3
              If Application < 1
								Alpha = 255 * Application
								Plot(n, nn, Color | Alpha << 24)
              Else
                Plot(n, nn, Color | $FF000000)
              EndIf
              
            EndIf
          EndIf
        EndIf
        
      Next
    Next
  EndIf
  
EndProcedure





;/ Test des fonctions de dessin avec Anti-Aliazing ( AA )
; Création de la fenêtre et de la GadgetList
If OpenWindow(0, 0, 0, 500, 500, "Test", #PB_Window_SystemMenu | #PB_Window_ScreenCentered | #PB_Window_MinimizeGadget) = 0 Or CreateGadgetList(WindowID(0)) = 0
  End
EndIf

CreateImage(0, 500, 500, 32)
StartDrawing(ImageOutput(0))
	DrawingMode(#PB_2DDrawing_AlphaBlend)
  ; Un joli fond
  #Carreau = 25
  For n = 0 To 500 Step #Carreau
    For nn = 0 To 500 Step #Carreau
      If ((n + nn) / #Carreau) & %1 = %1
        Box(n, nn, #Carreau, #Carreau, $FFFFFFFF)
      Else
        Box(n, nn, #Carreau, #Carreau, $FF0000FF)
      EndIf
    Next
  Next
  
  ; Dessin de Cercle
  CircleAA(100, 100, 70, $000000)
  CircleAA(250, 100, 50, $000000, 1, #PB_2DDrawing_Outlined)
  CircleAA(250, 100, 70, $000000, 3, #PB_2DDrawing_Outlined)
  
  ; Dessin d'une ellipse
  EllipseAA(400, 100, 40, 60, $000000, 2, #PB_2DDrawing_Outlined)
  EllipseAA(400, 100, 50, 70, $000000, 1, #PB_2DDrawing_Outlined)
  EllipseAA(400, 100, 30, 20, $000000)
  
  
  
  ; Dessin de ligne
  For n = 0 To 150 Step 30
    LineAA(20, 200, 150, n, $000000)
  Next
  For n = 0 To 120 Step 30
    LineAA(20, 200, n, 150, $000000)
  Next
  Epaisseur = 2
  For n = 0 To 150 Step 30
    LineAA(200, 200, 150, n, $000000, Epaisseur)
    Epaisseur + 1
  Next
  Epaisseur = 2
  For n = 0 To 120 Step 30
    LineAA(200, 200, n, 150, $000000, Epaisseur)
    Epaisseur + 1
  Next
  
  ; dessin de triangles
  TriangleAA(420, 200, 480, 250, 370, 350, $000000)
  Epaisseur = 1
  For n = 0 To 30 Step 10
    TriangleAA(490 - n, 260 + n, 390 + n, 350, 460, 400 - n, $000000, Epaisseur, #PB_2DDrawing_Outlined)
    Epaisseur + 1
  Next
  
StopDrawing()

ImageGadget(0, 0, 0, 300, 300, ImageID(0))

Repeat
  Event = WaitWindowEvent()
  
  Select Event
    Case #PB_Event_Menu
      Select EventMenu() ; Menus
          
      EndSelect
      
    Case #PB_Event_Gadget
      Select EventGadget() ; Gadgets
          
      EndSelect
  EndSelect
  
Until Event = #PB_Event_CloseWindow

End
Je ne suis pas à moitié Polonais mais ma moitié est polonaise ... Vous avez suivi ?

[Intel quad core Q9400 2.66mhz, ATI 4870, 4Go Ram, XP (x86) / 7 (x64)]
Ollivier
Messages : 4190
Inscription : ven. 29/juin/2007 17:50
Localisation : Encore ?
Contact :

Re: Dessin de forme avec du lissage

Message par Ollivier »

@LSI

Dénué du désir de ma part de jouer le pissou, j'ai posté un code page 1 dont tu n'as point mentionné remarque.

Il permet cependant :
- d'intégrer la notion de dégradé,
- de disposer d'un transfert de ressources: plus le dessin est complexe, moins il perd de temps;
- d'intégrer toutes les fonctions des sprites 3D;
- (à titre de confort) d'exporter son dessin vers une fenêtre skinnée.

Vu la qualité des réponses, ça me motive grave pour poster quelque chose de plus souple et révélateur...

:?

Ollivier
Le Soldat Inconnu
Messages : 4312
Inscription : mer. 28/janv./2004 20:58
Localisation : Clermont ferrand OU Olsztyn
Contact :

Re: Dessin de forme avec du lissage

Message par Le Soldat Inconnu »

Ben oui, c'est joli :)

Mais je pipe rien au calcul a cause du ASM au milieu alors ... :mrgreen:

Par contre, j'ai bien vu le UpdateLayeredWindow qui me parle plus maintenant car j'ai compris comment utiliser cette fonction.

D'ailleurs, en passent, le rendu de ton dégradé qui ne marche pas bien sur les bord de la fenêtre est peut-être du au même problème que j'ai rencontré avec UpdateLayeredWindow, a savoir que microchiotte ne sait pas faire de mélange de couleur avec alpha
Je ne suis pas à moitié Polonais mais ma moitié est polonaise ... Vous avez suivi ?

[Intel quad core Q9400 2.66mhz, ATI 4870, 4Go Ram, XP (x86) / 7 (x64)]
Ollivier
Messages : 4190
Inscription : ven. 29/juin/2007 17:50
Localisation : Encore ?
Contact :

Re: Dessin de forme avec du lissage

Message par Ollivier »

Le seul inconvénient que je vois c'est la limitation des dimensions de l'image à celles de l'écran (ex: 1024x768). Pour une image haute résolution dans le genre 4000x4000, je n'ai pas idée du process à faire avec les sprite3D.

En revanche, je ne vois pas le problème que tu évoques. Est-ce que tu as un code qui révèle bien ce défaut, parce qu'à priori XP gère bien le mélange des couleurs de la fenêtre avec le bureau. Avec Vista, tu peux même faire un scrolling. Ce qui m'embête c'est que j'y connais couille à l'équivalent de UpdateLayeredWindow_() sous Linux.

Ollivier

PS: pour la partie ASM, ce n'est qu'une copie mémoire qui passe la copie des pixels noirs pour aller plus vite. (Il y a d'ailleurs son équivalent, CopyMemory(), commenté juste après l'ASM)
Le Soldat Inconnu
Messages : 4312
Inscription : mer. 28/janv./2004 20:58
Localisation : Clermont ferrand OU Olsztyn
Contact :

Re: Dessin de forme avec du lissage

Message par Le Soldat Inconnu »

regarde ce sujet
http://www.purebasic.fr/french/viewtopic.php?f=3&t=9746

c'est celui j'ai découvert UpdateLayeredWindow_( et le problème qui va avec
Il y a la solution aussi
Je ne suis pas à moitié Polonais mais ma moitié est polonaise ... Vous avez suivi ?

[Intel quad core Q9400 2.66mhz, ATI 4870, 4Go Ram, XP (x86) / 7 (x64)]
Ollivier
Messages : 4190
Inscription : ven. 29/juin/2007 17:50
Localisation : Encore ?
Contact :

Re: Dessin de forme avec du lissage

Message par Ollivier »

Ah oui tiens... ça date de Septembre 2009 ton lien...

Ben ça, je l'ai fait ici en Septembre 2007, et grâce à toi en plus!!! (C'est Flype qui le dit, t'as qu'à lire)

Deux ans d'écart pour la même chose... :D Désolé, j'avais comme qui dirait pris de l'avance... (Et visiblement, ce n'est pas fini!)

Ollivier
Ollivier
Messages : 4190
Inscription : ven. 29/juin/2007 17:50
Localisation : Encore ?
Contact :

Re: Dessin de forme avec du lissage

Message par Ollivier »

J'avais mis quelques heures avant de trouver la feinte:
Le paramètre Blend (c'est un double-mot type long),
vous l'aviez réglé à $XX000000 avec XX le byte = coef alpha global de la fenêtre. Et le ULW_Flag, après le paramètre Blend était à 3 je crois.
Je me suis débrouillé pour passer la paramètre Blend à $01FF0000 et le paramètre ULW à 2 je crois (si je ne dis pas de connerie)

Et le tour est joué. Une image stockée en mémoire (bitmap de l'API en 32 bits par pixel) avec chaque pixel 24 bits doté de 8 bits supplémentaires pour le coefficient alpha par pixel. Le mélange se fait nickel, je ne comprends pas ton problème, peut-être parce que toi tu utilise une image PNG alors que moi j'utilise une image Bitmap.(?) Je n'en sais trop rien en fait.

Ollivier
Le Soldat Inconnu
Messages : 4312
Inscription : mer. 28/janv./2004 20:58
Localisation : Clermont ferrand OU Olsztyn
Contact :

Re: Dessin de forme avec du lissage

Message par Le Soldat Inconnu »

Effectivement, tu n'as pas le problème visiblement. J'ai zappé ce code, il en passé pendant que je n'étais plus trop présent sur le forum je pense.
J'ai posté sur ton sujet pour voir ce problème avec UpdateLayeredWindow_(
Je ne suis pas à moitié Polonais mais ma moitié est polonaise ... Vous avez suivi ?

[Intel quad core Q9400 2.66mhz, ATI 4870, 4Go Ram, XP (x86) / 7 (x64)]
Ollivier
Messages : 4190
Inscription : ven. 29/juin/2007 17:50
Localisation : Encore ?
Contact :

Re: Dessin de forme avec du lissage

Message par Ollivier »

Petite MàJ de mon code page 1, c'est juste pour qu'il reste fonctionnel.

Le résultat est un lissage pris en charge par les sprites. Ce n'est pas le calcul même de LSI au pixel près.

Code : Tout sélectionner

; User des transformations graphiques natives
; et les copier sur une fenêtre alpha.
;24/08/15 MAJ 522 LTS x86

; [X] Windows	[X] 32bits
; [.] Linux		[.] 64bits
; [.] MacOS


DisableDebugger
Structure LW ; Cf Procedures >> Alphablending >> Layered Window

    WindowID.L                  ; Handle du DC de la fenetre translucide (WindowID)
    *ptWnd                      ;#Pointe vers une structure POINT (Position de la fenetre, 0 = inchangee)
    *szWnd                      ;#Pointe vers une structure SIZE (Taille de la fenetre, 0 = inchangee)
    hdcAIm.L                    ; Handle du DC source (Image Alpha)
    *ptAIm                      ;#Pointe vers une structure POINT
    crKey.L                     ; Couleur clef (transparence)
    *Blend                      ;#Pointe vers la structure BLENDFUNCTION (fBlend plus bas)
    *AImArea                    ;#Pointe vers 1 struc RECT specifiant la zone a copier depuis le DC source
    X.L                         ; Coordonnees X de la fenetre
    Y.L                         ; Coordonnees Y de la fenetre
    W.L                         ; Largeur de la fen�tre
    H.L                         ; Hauteur de la fen�tre
    XA.L                        ; Coordonn�es X dans l'image
    YA.L                        ; Coordonn�es Y dans l'image
    fBlend.L                    ; Fonction Blend (toujours $01FF0000)
    X1.L                        ; Vista
    Y1.L                        ; Vista
    X2.L                        ; Vista
    Y2.L                        ; Vista
    Window.L                    ; n� de fen�tre
    ImageID.L                   ; ID de l'image
   
    VX.F
    VY.F
    AA.F
    V.F
    Flip.L
   
EndStructure


Procedure LayeredWindow(Window.L, Stat.L)

    Protected NewFlag.L = GetWindowLong_(WindowID(Window), #GWL_EXSTYLE) | (#WS_EX_LAYERED * Stat)
   
    SetWindowLong_(WindowID(Window), #GWL_EXSTYLE, NewFlag)

EndProcedure


Procedure OpenLW(*LW.LW, X, Y, ImageID)

    Protected Bmp.BITMAP
    Protected PosiSrc.POINT
 
    With *LW
        \ImageID = ImageID
        GetObject_(\ImageID, SizeOf(BITMAP), @Bmp)
        \W = Bmp\BmWidth
        \H = Bmp\BmHeight
        \Window = OpenWindow(-1, X, Y, W, H, "", $90000000)
        \WindowID = WindowID(\Window)
        If \Window
            StickyWindow(\Window, 1)
            LayeredWindow(\Window, 1)
            \hdcAIm = CreateCompatibleDC_(StartDrawing(WindowOutput(\Window) ) )
                SelectObject_(\hdcAIm, \ImageID)     
                Blend.L = $1FF0000
                Result.L = UpdateLayeredWindow_(\WindowID, 0, 0, @\W, \HdcAIm, PosiSrc, 0, @Blend, 2)
            StopDrawing()
            DeleteDC_(\hdcAIm)
            HideWindow(\Window, 0)
        EndIf     
        If Result = 0: CloseWindow(\Window): EndIf
    EndWith
       
    ProcedureReturn Result

EndProcedure

InitSprite()
InitKeyboard()
OpenWindow(0, 0, 0, 1024, 768, "", $90000000)
OpenWindowedScreen(WindowID(0), 0, 0, 1024, 768, 0, 0, 0)
CreateSprite(0, 4, 4, #PB_Sprite_AlphaBlending)
StartDrawing(SpriteOutput(0) )
Box(0, 1, 2, 2, #White)
Box(2, 1, 2, 2, #Blue)
StopDrawing()
SpriteQuality(1)
Distance.F = 256.0
Thickness.F = 8.0
   Delay(1)
   ClearScreen(0)
      SpriteBlendingMode(3, 9)
      Angle.F = 0
      For A = 0 To 360 Step 10
     
         cx.F = 256
         cy.F = 256

         Angle = A * #PI / 180.0 + AngleR.F
     
         ix.F = Cos(Angle)
         iy.F = Sin(Angle)
         jx.F = Cos(Angle + #PI / 2.0)
         jy.F = Sin(Angle + #PI / 2.0)

         ex1.F = 0.0
         ey1.F = 0.0 - Thickness
         ex2.F = Distance
         ey2.F = 0.0 - Thickness
         ex3.F = Distance
         ey3.F = Thickness
         ex4.F = 0.0
         ey4.F = Thickness
     
         gx1.F = ex1 * ix + ey1 * iy
         gy1.F = ex1 * jx + ey1 * jy
         gx2.F = ex2 * ix + ey2 * iy
         gy2.F = ex2 * jx + ey2 * jy
         gx3.F = ex3 * ix + ey3 * iy
         gy3.F = ex3 * jx + ey3 * jy
         gx4.F = ex4 * ix + ey4 * iy
         gy4.F = ex4 * jx + ey4 * jy
         DisplayTransparentSprite(0, 0, 0)
         TransformSprite(0, cx+gx1, cy+gy1, cx+gx2, cy+gy2, cx+gx3, cy+gy3, cx+gx4, cy+gy4)     
      Next
   ExamineKeyboard()
   If KeyboardPushed(#PB_Key_Left): AngleR = (AngleR + 0.005): EndIf
   If KeyboardPushed(#PB_Key_Right): AngleR = (AngleR - 0.005): EndIf
   FlipBuffers()
   *X = AllocateMemory(1024 * 768 * 4 + 8)
   PokeL(*X, 1024)
   PokeL(*X + 4, 768)
   If StartDrawing(ScreenOutput())
      Buffer      = DrawingBuffer()             ; Get the start address of the screen buffer
      Pitch       = DrawingBufferPitch()        ; Get the length (in byte) took by one horizontal line
      PixelFormat = DrawingBufferPixelFormat()  ; Get the pixel format.
   *Ecran = Buffer
   *Start = *X + 8

   Qty = 1024 * 768
   ! mov esi, [p_Ecran]
   ! mov edi, [p_Start]
   ! mov ecx, [v_Qty]

Transfert:
   ! lodsd
   ! mov edx, eax
   ! xor ebx,ebx

   ! cmp bl, dl
   ! ja l_ici0
   ! mov bl, dl
ici0:
   ! shr edx, 8

   ! cmp bl, dl
   ! ja l_ici1
   ! mov bl, dl
ici1:
   ! shr edx, 8

   ! cmp bl, dl
   ! ja l_ici2
   ! mov bl, dl
ici2:
   ! shl ebx, 24
   ! or  eax, ebx
   ! stosd
   ! loop l_transfert
   
   ;   CopyMemory(*Ecran, *Start, 1024 * 768 * 4)
      StopDrawing()
   EndIf
   AlphaImage.L = CreateBitmap_(1024, 768, 1, 32, *X + 8)
   ULW.LW
   OpenLW(ULW, 100, 100, AlphaImage)
   Delay(8000)
CloseScreen()
CloseWindow(0)
End
Répondre