Défi Fonction 2D d'éclairage super optimisé

Programmation d'applications complexes
Avatar de l’utilisateur
Thyphoon
Messages : 2706
Inscription : mer. 25/août/2004 6:31
Localisation : Eragny
Contact :

Message par Thyphoon »

Je viens d'avoir une nouvelle idée d'optimisation
Dans mon code actuel lorsque je fais un lancer de rayon je fais 2 peek
le premier pour avoir la couleur de la pixel et le deuxième sur le mask pour savoir si il y a colision ou pas. Et je pense avoir trouvé une solution pour n'en faire plus qu'un.
Je vais intégré dans l'image mes informations de colision.
Je pense utilisé le bit de poids faible de la couleur pour determiner si 0 pas de colision ou 1 il y a colision. Cette modification ne devrait pas alterer les couleurs ... :D
Qu'en pensez vous ? allez je me lance...mais il me faut faire un petit utilitaire pour traiter mon image et lui donner ces infos... :wink:
Apres cela je vous donnerais le code ... :D
Dr. Dri
Messages : 2527
Inscription : ven. 23/janv./2004 18:10

Message par Dr. Dri »

Je te recommande aussi les pointeurs qui vont plus vite que les peek/poke...

Sinon j'ai retrouvé une démo de mon truc en version "Sprite3D" (vu.zip) et ca m'a fait penser que tu peux définir la couleur de chaque sommet d'un Sprite3D, les couleurs intermédiaires seront directement calculées par la carte graphique. En faisant comme moi dans mon "T3D" (ah au fait je l'ai repris ^^) tu peux afficher un Sprite3D en triangle, il suffit de confondre deux des coins en le transformant.

Je suis sûr qu'avec ca tu peux obtenir un éclarage ultra rapide en triangle (avec éventuellement d'autre triangle pour faire un peu arrondi au bout du champ de vision) et en plus un éclairage coloré.

J'essairai de te pondre un exemple "statique" peut être la semaine prochaine.

Dri
Avatar de l’utilisateur
Thyphoon
Messages : 2706
Inscription : mer. 25/août/2004 6:31
Localisation : Eragny
Contact :

Message par Thyphoon »

Dr. Dri a écrit :Je te recommande aussi les pointeurs qui vont plus vite que les peek/poke...

Sinon j'ai retrouvé une démo de mon truc en version "Sprite3D" (vu.zip) et ca m'a fait penser que tu peux définir la couleur de chaque sommet d'un Sprite3D, les couleurs intermédiaires seront directement calculées par la carte graphique. En faisant comme moi dans mon "T3D" (ah au fait je l'ai repris ^^) tu peux afficher un Sprite3D en triangle, il suffit de confondre deux des coins en le transformant.

Je suis sûr qu'avec ca tu peux obtenir un éclarage ultra rapide en triangle (avec éventuellement d'autre triangle pour faire un peu arrondi au bout du champ de vision) et en plus un éclairage coloré.

J'essairai de te pondre un exemple "statique" peut être la semaine prochaine.

Dri
C'est génial ton truc ! :) Si tu peux me pondre un exemple même statique ça serait génial .. :o)
Avatar de l’utilisateur
Thyphoon
Messages : 2706
Inscription : mer. 25/août/2004 6:31
Localisation : Eragny
Contact :

Message par Thyphoon »

Le resultat est de mieux en mieux...et je suis certain qu'on peu encore optimisé
voici mon code
mais il ne faut pas utilisé n'importe quel image.voici l'image a utilisé
Image
le relief est codé dans chaque pixel....
Vous pouvez diriger la lampe avec les fleches et la souris....
Dites moi ce que vous en pensez... chez moi ça tourne a 30 fps.
Mais j'éspère pouvoir encore améliorer cela. Quand je pense que mon premier code je tournais a 1FPS et que l'éclairage était moins beau...Y a du progres...

Code : Tout sélectionner

If InitSprite() = 0 Or InitKeyboard()=0 Or InitMouse()=0 Or InitSprite3D()=0
  MessageRequester("Error","DirectX 7+ is needed.",0)
EndIf

Global ScreenWidth.l,ScreenHeight.l
ScreenWidth=640
ScreenHeight=480
Enumeration
#Screen
#Map
#Mask
#Buffer
EndEnumeration

;#PI = 3.14159265 

Procedure.f winkel(x1.f,y1.f,x2.f,y2.f) 
  a.f = x2-x1 
  b.f = y2-y1 
  c.f = Sqr(a*a+b*b) 
  winkel.f = ACos(a/c)*57.29577 
  If y1 < y2 : winkel=360-winkel : EndIf 
  ProcedureReturn winkel 
EndProcedure


Procedure.f GradToDeg(Ang.l) 
  ProcedureReturn 9*Ang/10 
EndProcedure 
Procedure.f RadToDeg(Ang.l) 
  ProcedureReturn 180*Ang/#PI 
EndProcedure 
Procedure.f DegToGrad(Ang.l) 
  ProcedureReturn 10*Ang/9 
EndProcedure 
Procedure.f RadToGrad(Ang.l) 
  ProcedureReturn 200*Ang/#PI 
EndProcedure 
Procedure.f DegToRad(Ang.l) 
  ProcedureReturn Ang*#PI/180 
EndProcedure 
Procedure.f GradToRad(Ang.l) 
  ProcedureReturn Ang*#PI/200 
EndProcedure

;Constante
#Rad=#PI/180 

Structure Surface
  *Address.l
  Pitch.l
  PixelFormat.l
  Width.l
  Height.l
EndStructure

Global Dim Buffer(640,480)
Global Dim Surface.Surface(10)
Global Dim CosTable.f(73000)
Global Dim SinTable.f(73000)
For z=0 To 72000
CosTable(z)=Cos(z/100*#Rad) 
SinTable(z)=Sin(z/100*#Rad)
Next
;IncludeFile("2d.pb")
OpenScreen(ScreenWidth, ScreenHeight, 32, "Aliens")
  UsePNGImageDecoder()
  TransparentSpriteColor(#PB_Default,RGB(255,0,255))
  LoadSprite(1,"image.png")
  ;LoadSprite(2,"body.bmp",#PB_Sprite_Texture)
  ;CreateSprite3D(2, 2)
  CreateSprite(3,640,480)
  CreateSprite(4,32,32)
  StartDrawing(SpriteOutput(4))
  Line(0,0,32,32,RGB(255,255,255))
  Line(0,32,32,-32,RGB(255,255,255))
  StopDrawing()

;Initialisation des différentes surfaces
StartDrawing(ScreenOutput())
  Surface(#Screen)\Address=DrawingBuffer() 
  Surface(#Screen)\Pitch=DrawingBufferPitch()
  Surface(#Screen)\PixelFormat=DrawingBufferPixelFormat()
  Surface(#Screen)\Width=ScreenWidth
  Surface(#Screen)\Height=ScreenHeight
StopDrawing()

StartDrawing(SpriteOutput(1))
  Surface(#Map)\Address=DrawingBuffer() 
  Surface(#Map)\Pitch=DrawingBufferPitch()
  Surface(#Map)\PixelFormat=DrawingBufferPixelFormat()
  Surface(#Map)\Width=SpriteWidth(1) 
  Surface(#Map)\Height=SpriteHeight(1) 
StopDrawing()  

StartDrawing(SpriteOutput(3))
  Surface(#Buffer)\Address=DrawingBuffer() 
  Surface(#Buffer)\Pitch=DrawingBufferPitch()
  Surface(#Buffer)\PixelFormat=DrawingBufferPixelFormat()
  Surface(#Buffer)\Width=SpriteWidth(3) 
  Surface(#Buffer)\Height=SpriteHeight(3) 
StopDrawing()  

Procedure Light(LightX.l,LightY.l,Angle.l,Anglef.l,Puissance.l,Color.l) 
  If Angle-Anglef<0:Angle=Angle+360:EndIf
  If Angle+Anglef>720:Angle=Angle-360:EndIf
  Dim MemPlot.b(640,480)  ; Un petit tableau pour verifier si la pixel au coordonée x et y du faisceau lumineux a déjà été traité
  For i = -Anglef To Anglef Step 1 
    a.f=(i/3+Angle) 
    f.l=0
    For p = 0 To Puissance 
      ;Calcul des coordonées X et Y a traité
      X = LightX + p * CosTable(Int(a*100));Cos(a*#Rad) ;
      Y = LightY + p * SinTable(Int(a*100));Sin(a*#Rad);
      
      If X>0 And X<Surface(#Buffer)\Width And Y>0 And Y<Surface(#Buffer)\Height
        ;On verifie si on tombe sur un obstacle: col=0,0,0 pas d'obstacte / col=255,255,255 il y a un obstacle 
        col=PeekL(Surface(#Map)\Address+x*4+Surface(#Map)\Pitch*y)
        Obstacle=(col & %11 )
        If Obstacle=0 Or f<10 ;Si il n'ya pas d'obstacle alors on trace (col=0) / si f>0 c'est qu'on a trouvé un obstacle mais il faut l'illuminé
          If Obstacle>0 Or f>0:f=f+1:EndIf ;Si on a trouvé un obstacle on l'illumine            
          ; si cette pixel n'a pas été traité on la traite
          ;On verifie qu'on est bien dans les limites
          If MemPlot(X,Y)=0
            ;Je mémorise que cette pixel a été traité pour ce faisceau là          
            MemPlot(X,Y)=1
            ;Je prélève la couleur dans le buffer au cas ou une autre source lumineuse serait déjà dans le coin 
            colb=Buffer(X,Y);PeekL(Surface(#Buffer)\Address+x*4+Surface(#Map)\Pitch*y)
            ;Je prend la couleur dans le decor
            ;col=PeekL(Surface(#Map)\Address+x*4+Surface(#Map)\Pitch*y)
            If f=0 Or Obstacle=0
              ;si on a pas encore trouvé d'obstacle alors on calcul l'éclairage
              ;lightlevel=(Puissance-p)*255/Puissance
              lightlevel=(((Puissance-p-10)*200/Puissance+(250*(Anglef-Abs(i))/Anglef))/2)-50;ça donne la forme de la luminosité
            Else
              ;si on a trouvé un obstacle on calcul l'illumination de cet objet
              lightlevel=255-(f*255/10)
            EndIf  
            ;il faut qu'il y est un minimum d'éclairage pour aller plus loin           
            If lightlevel>1 And lightlevel<256 
              ;Calcul de la couleur de la pixem
              red=(Red(col)*Red(Color)*lightlevel)/65536
              green=(Green(col)*Green(Color)*lightlevel)/65536
              blue=(Blue(col)*Blue(Color)*lightlevel)/65536
              ;col=RGB(red,green,blue)
              ;Melange de faisceau lumineux si il y a besoin
              If colb>0
                If Red(colb)>red:red=Red(colb):Else:red=red:EndIf
                If Green(colb)>green:green=Green(colb):Else:green=green:EndIf
                If Blue(colb)>blue:blue=Blue(colb):Else:blue=blue:EndIf
              EndIf
              col=RGB(red,green,blue)

              ;Hop on affiche dans le buffer le pixel
              Buffer(X,Y)=col
              PokeL(Surface(#Buffer)\Address+x*4+Surface(#Buffer)\Pitch*y,col) 
            EndIf
          EndIf
        Else
          Break;
        EndIf
      EndIf
    Next p    
  Next i 
EndProcedure 

gx=320
gy=200

Repeat
 ExamineMouse() 
  ExamineKeyboard()
  ga=winkel(gx,MouseY(),MouseX(),gy)
  UseBuffer(3)
  ClearScreen(0)
 
  If Time=0:Time=ElapsedMilliseconds():EndIf 
  t.l=(ElapsedMilliseconds()-Time)
  Time=ElapsedMilliseconds()
  An=An+(40*t/100)
  If An>360:An=An-360:EndIf
  Light(250,250,A,45,150,RGB(255,255,255)) 
  Light(gx,gy,ga,90,90,RGB(255,255,255)) 
  Light(200,240,An+180,10,150,RGB(100,100,255))
  Light(200,240,An,10,150,RGB(100,100,255))  

  A=A+1 
  If A>360:A=A-360:EndIf 
 
  If KeyboardPushed(#PB_Key_Up) And gy>0:gy-1:EndIf
  If KeyboardPushed(#PB_Key_Down) And gy<480:gy+1:EndIf
  If KeyboardPushed(#PB_Key_Right) And gx<640:gx+1:EndIf
  If KeyboardPushed(#PB_Key_Left) And gx>0:gx-1:EndIf
    
  Delay(1)
   
  If Val(FormatDate("%ss", Date()))=sek
    FPS+1
  Else
    FPS$=Str(FPS)
    Time$=Str(ElapsedMilliseconds()-Elapsetime)
    FPS=0
  EndIf
  sek=Val(FormatDate("%ss", Date()))
  ;Affichage
  ;UseBuffer(3)
  ;Start3D()
  ;RotateSprite3D(2, ga, 0)
  ;DisplaySprite3D(2, gx, gy, 255)
  ;Stop3D()
 UseBuffer(-1)
  DisplaySprite(3,0,0)
  DisplaySprite(4,MouseX()-16,MouseY()-16)
  Dim Buffer(640,480)
  StartDrawing(ScreenOutput()) 
    DrawingMode(1)
    FrontColor(RGB(255,255,255))
    DrawText(100,1,"FPS: "+FPS$+" Time:"+Time$+" Angle:"+Str(ga))
    Elapsetime=ElapsedMilliseconds()
  StopDrawing()
    FlipBuffers(0)
  Until KeyboardPushed(#PB_Key_Escape)
End  
Dernière modification par Thyphoon le ven. 12/mai/2006 17:52, modifié 1 fois.
Avatar de l’utilisateur
flaith
Messages : 1487
Inscription : jeu. 07/avr./2005 1:06
Localisation : Rennes
Contact :

Message par flaith »

Bah, il doit manquer qqchose, car à part l'affichage du fps, il n'y a rien d'autre !!!
Avatar de l’utilisateur
Thyphoon
Messages : 2706
Inscription : mer. 25/août/2004 6:31
Localisation : Eragny
Contact :

Message par Thyphoon »

flaith a écrit :Bah, il doit manquer qqchose, car à part l'affichage du fps, il n'y a rien d'autre !!!
reteste car lors de mon copier coller j'avais fait une erreur là ça devrait marcher.
Avatar de l’utilisateur
flaith
Messages : 1487
Inscription : jeu. 07/avr./2005 1:06
Localisation : Rennes
Contact :

Message par flaith »

ca marche mieux, merci, c'est tout petit, mais ca marche ;)
Avatar de l’utilisateur
Thyphoon
Messages : 2706
Inscription : mer. 25/août/2004 6:31
Localisation : Eragny
Contact :

Message par Thyphoon »

flaith a écrit :ca marche mieux, merci, c'est tout petit, mais ca marche ;)
lolllll bon c'est vrai que je ne peux pas encore faire un eclairage de cathédral en temps reel avec ce code :P
Faut juste que je trouve un code pour optimiser mon lancer de rayon...
Dr. Dri
Messages : 2527
Inscription : ven. 23/janv./2004 18:10

Message par Dr. Dri »

Thyphoon a écrit :
flaith a écrit :ca marche mieux, merci, c'est tout petit, mais ca marche ;)
lolllll bon c'est vrai que je ne peux pas encore faire un eclairage de cathédral en temps reel avec ce code :P
Faut juste que je trouve un code pour optimiser mon lancer de rayon...
A priori avec mon code ca devrait le faire, quand tu parles de lancer de rayon, c'est la même chose que dans mes démos "vu" où le champ de vision s'arrêe sur les obstacles ?

C'est un truc que j'ai codé plusieurs fois (en DB, en C et en PB ^^) et à priori je devrais pouvoir le refaire ^^ (et en V4 !!!)

Dri
Avatar de l’utilisateur
Thyphoon
Messages : 2706
Inscription : mer. 25/août/2004 6:31
Localisation : Eragny
Contact :

Message par Thyphoon »

Dr. Dri a écrit :
Thyphoon a écrit : A priori avec mon code ca devrait le faire, quand tu parles de lancer de rayon, c'est la même chose que dans mes démos "vu" où le champ de vision s'arrêe sur les obstacles ?

C'est un truc que j'ai codé plusieurs fois (en DB, en C et en PB ^^) et à priori je devrais pouvoir le refaire ^^ (et en V4 !!!)

Dri
Oui c'est presque comme dans ta démos en un peu plus detailé (précision a la pixel, et ça gère 3 niveau de relief
As tu testé mon code ?
Dr. Dri
Messages : 2527
Inscription : ven. 23/janv./2004 18:10

Message par Dr. Dri »

J'ai testé (6 de FPS) et je vois a peu près comment ca fonctionne. Sinon je ne travaille pas au pixel près mais sur une grille (16*16, 32*32, c'est au choix...)

Enfin on verra ce que ca donne avec les Sprite3D, je referais mon lancer de rayon pour l'occasion ^^

Dri
Avatar de l’utilisateur
Thyphoon
Messages : 2706
Inscription : mer. 25/août/2004 6:31
Localisation : Eragny
Contact :

Message par Thyphoon »

Dr. Dri a écrit :J'ai testé (6 de FPS) et je vois a peu près comment ca fonctionne. Sinon je ne travaille pas au pixel près mais sur une grille (16*16, 32*32, c'est au choix...)

Enfin on verra ce que ca donne avec les Sprite3D, je referais mon lancer de rayon pour l'occasion ^^

Dri
en 16*16 ça pourait le faire....ou même 32*32 ...comme ça t'arrange :P
Avatar de l’utilisateur
Thyphoon
Messages : 2706
Inscription : mer. 25/août/2004 6:31
Localisation : Eragny
Contact :

Message par Thyphoon »

Dr. Dri a écrit :Je te recommande aussi les pointeurs qui vont plus vite que les peek/poke...
Apres pas mal de galère...j'ai compris le fonctionnement des pointeurs...
et d'apres mes tests (ecriture de 100 ecran de 640x480) les pointeurs sont plus lents que Poke ou même Peek.... peut être que c'est nouveau avec la V4

pour Lire 100 ecran 32bits de 640x480
pointeur :17000 ms
PeekL:1680ms

pour écrire 100 ecran 32bits de 640x480
pointeur:5610ms
PokeL:4265ms

Quelqu'un peu confirmer ce que je dis ??
AWEAR
Messages : 264
Inscription : ven. 28/oct./2005 8:20
Localisation : Mayotte ( 976 ), Océan Indien, France

Message par AWEAR »

pour Lire 100 ecran 32bits de 640x480
pointeur :17000 ms
PeekL:1680ms
La différence entre pointeur et peek me parait excessivement élevé (plus de 10 fois).
Ton code avec les pointeurs n'est peut-être pas optimisé, poste-le et on verra bien, car une difference si importante est vraiment étrange.
La vie est une rose dont il faut accepter les épines, mais la mienne est fannée, arrosée par le goût de mes larmes. (Soprano)
Avatar de l’utilisateur
Thyphoon
Messages : 2706
Inscription : mer. 25/août/2004 6:31
Localisation : Eragny
Contact :

Message par Thyphoon »

erreur de retranscription c'est :
pour Lire 100 ecran 32bits de 640x480
pointeur :17000 ms
PeekL:16800ms
de mémoire vite fait...car je l'ai effacer c'est en faisant comme ça


ouvrir un ecran 32bit

Code : Tout sélectionner

Structure Pixel
  Pixel.l
EndStructure

createsprite(1,640,480)

startdrawing(spriteoutput(1))
  Adresse=DrawingBuffer()
  Pitch=DrawingBufferPitch()
stopdrawing()

t=ElapsedMilliseconds()
for z=0 to 100
  for x=0 to 640
    for y=0 to 480
       *Plot.Pixel=Address+x*4+Pitch*y
       col=*plot\Pixel
    next
  next
next
tempsA=ElapsedMilliseconds()-t

t=ElapsedMilliseconds()
for z=0 to 100
  for x=0 to 640
    for y=0 to 480
       col=Peekl(Address+x*4+Pitch*y)
    next
  next
next
tempsB=ElapsedMilliseconds()-t
Répondre